Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/external/cddl/osnet/sys/sys Zfs_write() may hide write error...
details: https://anonhg.NetBSD.org/src/rev/5b47a1c20669
branches: trunk
changeset: 994972:5b47a1c20669
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 4f56951f4ee1 -r 5b47a1c20669 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 4f56951f4ee1 -r 5b47a1c20669 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