Module Name: src Committed By: hannken Date: Fri Nov 30 09:53:41 UTC 2018
Modified Files: src/external/cddl/osnet/dist/uts/common/fs/zfs: zfs_vnops.c src/external/cddl/osnet/sys/sys: uio.h Log Message: 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. To generate a diff of this commit: cvs rdiff -u -r1.35 -r1.36 \ src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c cvs rdiff -u -r1.11 -r1.12 src/external/cddl/osnet/sys/sys/uio.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c diff -u src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c:1.35 src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c:1.36 --- src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c:1.35 Wed Nov 28 10:01:28 2018 +++ src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c Fri Nov 30 09:53:40 2018 @@ -1182,7 +1182,7 @@ zfs_write(vnode_t *vp, uio_t *uio, int i * 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 @@ zfs_write(vnode_t *vp, uio_t *uio, int i 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 @@ zfs_write(vnode_t *vp, uio_t *uio, int i 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 @@ zfs_write(vnode_t *vp, uio_t *uio, int i 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 Index: src/external/cddl/osnet/sys/sys/uio.h diff -u src/external/cddl/osnet/sys/sys/uio.h:1.11 src/external/cddl/osnet/sys/sys/uio.h:1.12 --- src/external/cddl/osnet/sys/sys/uio.h:1.11 Mon May 28 21:05:10 2018 +++ src/external/cddl/osnet/sys/sys/uio.h Fri Nov 30 09:53:40 2018 @@ -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 @@ zfs_uiomove(void *cp, size_t n, enum uio 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; - - *cbytes = (size_t)(uio->uio_resid - uio2.uio_resid); + uio_t auio; + struct iovec aiov; + size_t cnt; + int i, error; + + *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) {