Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/external/cddl/osnet Zfs_write() may hide write errors if uio...



details:   https://anonhg.NetBSD.org/src/rev/373da189157c
branches:  trunk
changeset: 446311:373da189157c
user:      hannken <hannken%NetBSD.org@localhost>
date:      Fri Nov 30 09:53:40 2018 +0000

description:
Zfs_write() may hide write errors if uiomove() succeeds but a
further dmu_tx_assign() fails because over quota or no space.

Use the emulated uiocopy() and uioskip() like illumos does.

Fix the uiocopy() emulation to not clobber the iovecs.

diffstat:

 external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c |  17 +-------
 external/cddl/osnet/sys/sys/uio.h                      |  36 ++++++++++++------
 2 files changed, 27 insertions(+), 26 deletions(-)

diffs (105 lines):

diff -r b98f57e993eb -r 373da189157c external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c
--- a/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c    Fri Nov 30 09:52:39 2018 +0000
+++ b/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c    Fri Nov 30 09:53:40 2018 +0000
@@ -1182,7 +1182,7 @@
                         * holding up the transaction if the data copy hangs
                         * up on a pagefault (e.g., from an NFS server mapping).
                         */
-#ifdef illumos
+#if defined(illumos) || defined(__NetBSD__)
                        size_t cbytes;
 #endif
 
@@ -1190,7 +1190,7 @@
                            max_blksz);
                        ASSERT(abuf != NULL);
                        ASSERT(arc_buf_size(abuf) == max_blksz);
-#ifdef illumos
+#if defined(illumos) || defined(__NetBSD__)
                        if (error = uiocopy(abuf->b_data, max_blksz,
                            UIO_WRITE, uio, &cbytes)) {
                                dmu_return_arcbuf(abuf);
@@ -1209,17 +1209,6 @@
                                break;
                        }
 #endif
-#ifdef __NetBSD__
-                       ssize_t resid = uio->uio_resid;
-
-                       error = uiomove(abuf->b_data, max_blksz, UIO_WRITE, uio);
-                       if (error != 0) {
-                               uio->uio_offset -= resid - uio->uio_resid;
-                               uio->uio_resid = resid;
-                               dmu_return_arcbuf(abuf);
-                               break;
-                       }
-#endif
                }
 
                /*
@@ -1297,7 +1286,7 @@
                                dmu_assign_arcbuf(sa_get_db(zp->z_sa_hdl),
                                    woff, abuf, tx);
                        }
-#ifdef illumos
+#if defined(illumos) || defined(__NetBSD__)
                        ASSERT(tx_bytes <= uio->uio_resid);
                        uioskip(uio, tx_bytes);
 #endif
diff -r b98f57e993eb -r 373da189157c external/cddl/osnet/sys/sys/uio.h
--- a/external/cddl/osnet/sys/sys/uio.h Fri Nov 30 09:52:39 2018 +0000
+++ b/external/cddl/osnet/sys/sys/uio.h Fri Nov 30 09:53:40 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uio.h,v 1.11 2018/05/28 21:05:10 chs Exp $     */
+/*     $NetBSD: uio.h,v 1.12 2018/11/30 09:53:40 hannken Exp $ */
 
 /*-
  * Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -107,24 +107,36 @@
        return (uiomove(cp, n, uio));
 }
 
+#define        ZFS_MIN(a,b)    ((/*CONSTCOND*/(a)<(b))?(a):(b))
+
 static __inline int
 zfs_uiocopy(void *cp, size_t n, enum uio_rw dir, uio_t *uio, size_t *cbytes)
 {
-       uio_t uio2;
-       int err;
-       
-       memcpy(&uio2, uio, sizeof(*uio));
-       assert(uio->uio_rw == dir);
-       if ((err = uiomove(cp, n, &uio2)) != 0)
-               return err;
+       uio_t auio;
+       struct iovec aiov;
+       size_t cnt;
+       int i, error;
 
-       *cbytes = (size_t)(uio->uio_resid - uio2.uio_resid);
+       *cbytes = 0;
+       memcpy(&auio, uio, sizeof(*uio));
+       for (i = 0; i < uio->uio_iovcnt && n > 0; i++) {
+               auio.uio_iov = &aiov;
+               auio.uio_iovcnt = 1;
+               aiov = uio->uio_iov[i];
+               cnt = ZFS_MIN(aiov.iov_len, n);
+               if (cnt == 0)
+                       continue;
+               error = uiomove(cp, cnt, &auio);
+               if (error)
+                       return error;
+               cp = (char *)cp + cnt;
+               n -= cnt;
+               *cbytes += cnt;
+       }
 
-       return (0);
+       return 0;
 }
 
-#define        ZFS_MIN(a,b)    ((/*CONSTCOND*/(a)<(b))?(a):(b))
-
 static __inline void
 zfs_uioskip(uio_t *uiop, size_t n)
 {



Home | Main Index | Thread Index | Old Index