svn commit: r353610 - vendor-sys/illumos/dist/uts/common/fs/zfs

Andriy Gapon avg at FreeBSD.org
Wed Oct 16 06:11:12 UTC 2019


Author: avg
Date: Wed Oct 16 06:11:11 2019
New Revision: 353610
URL: https://svnweb.freebsd.org/changeset/base/353610

Log:
  10230 zfs mishandles partial writes
  
  illumos/illumos-gate at b0ef425652e5cfce27df9fa5826a9cd64cee110a
  https://github.com/illumos/illumos-gate/commit/b0ef425652e5cfce27df9fa5826a9cd64cee110a
  
  https://www.illumos.org/issues/10230
    The trinity fuzzer calls pwritev with an iovec that has one or more entries
    which point to some initial valid data and then the rest point to addresses
    which are not mapped. This yields EFAULT once the write hits the invalid
    address, but we do successfully complete some amount of writing. The zfs_write
    code does not handle this properly. It loses track of the error return from
    dmu_write_uio_dbuf and it has an invalid ASSERT which does not account for the
    partial write case.
  
  Author: Jerry Jelinek <jerry.jelinek at joyent.com>

Modified:
  vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_vnops.c

Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_vnops.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_vnops.c	Wed Oct 16 06:09:00 2019	(r353609)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_vnops.c	Wed Oct 16 06:11:11 2019	(r353610)
@@ -23,7 +23,7 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2012, 2017 by Delphix. All rights reserved.
  * Copyright (c) 2014 Integros [integros.com]
- * Copyright 2015 Joyent, Inc.
+ * Copyright 2019 Joyent, Inc.
  * Copyright 2017 Nexenta Systems, Inc.
  */
 
@@ -665,6 +665,7 @@ zfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t 
 	ssize_t		n, nbytes;
 	int		max_blksz = zfsvfs->z_max_blksz;
 	int		error = 0;
+	int		prev_error;
 	arc_buf_t	*abuf;
 	iovec_t		*aiov = NULL;
 	xuio_t		*xuio = NULL;
@@ -972,7 +973,6 @@ zfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t 
 		while ((end_size = zp->z_size) < uio->uio_loffset) {
 			(void) atomic_cas_64(&zp->z_size, end_size,
 			    uio->uio_loffset);
-			ASSERT(error == 0);
 		}
 		/*
 		 * If we are replaying and eof is non zero then force
@@ -982,12 +982,17 @@ zfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t 
 		if (zfsvfs->z_replay && zfsvfs->z_replay_eof != 0)
 			zp->z_size = zfsvfs->z_replay_eof;
 
+		/*
+		 * Keep track of a possible pre-existing error from a partial
+		 * write via dmu_write_uio_dbuf above.
+		 */
+		prev_error = error;
 		error = sa_bulk_update(zp->z_sa_hdl, bulk, count, tx);
 
 		zfs_log_write(zilog, tx, TX_WRITE, zp, woff, tx_bytes, ioflag);
 		dmu_tx_commit(tx);
 
-		if (error != 0)
+		if (prev_error != 0 || error != 0)
 			break;
 		ASSERT(tx_bytes == nbytes);
 		n -= nbytes;


More information about the svn-src-all mailing list