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)
 {

Reply via email to