changeset 10209:91f47f0e7728

6830541 zfs_get_data trips on a verify 6696242 multiple zfs_fillpage() zfs: accessing past end of object panics 6785914 zfs fails to drop dn_struct_rwlock in recovery code path
author Mark J Musante <Mark.Musante@Sun.COM>
date Thu, 30 Jul 2009 08:43:06 -0400
parents 98cb0a515a01
children a7483403391a
files usr/src/uts/common/fs/zfs/dmu.c usr/src/uts/common/fs/zfs/zfs_vnops.c usr/src/uts/common/fs/zfs/zil.c
diffstat 3 files changed, 28 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/dmu.c	Thu Jul 30 02:52:07 2009 -0400
+++ b/usr/src/uts/common/fs/zfs/dmu.c	Thu Jul 30 08:43:06 2009 -0400
@@ -195,7 +195,7 @@
 
 	ASSERT(length <= DMU_MAX_ACCESS);
 
-	dbuf_flags = DB_RF_CANFAIL | DB_RF_NEVERWAIT;
+	dbuf_flags = DB_RF_CANFAIL | DB_RF_NEVERWAIT | DB_RF_HAVESTRUCT;
 	if (flags & DMU_READ_NO_PREFETCH || length > zfetch_array_rd_sz)
 		dbuf_flags |= DB_RF_NOPREFETCH;
 
@@ -212,6 +212,7 @@
 			    os_dsl_dataset->ds_object,
 			    (longlong_t)dn->dn_object, dn->dn_datablksz,
 			    (longlong_t)offset, (longlong_t)length);
+			rw_exit(&dn->dn_struct_rwlock);
 			return (EIO);
 		}
 		nblks = 1;
@@ -234,9 +235,7 @@
 		}
 		/* initiate async i/o */
 		if (read) {
-			rw_exit(&dn->dn_struct_rwlock);
 			(void) dbuf_read(db, zio, dbuf_flags);
-			rw_enter(&dn->dn_struct_rwlock, RW_READER);
 		}
 		dbp[i] = &db->db;
 	}
@@ -543,7 +542,7 @@
 {
 	dnode_t *dn;
 	dmu_buf_t **dbp;
-	int numbufs, i, err;
+	int numbufs, err;
 
 	err = dnode_hold(os->os, object, FTAG, &dn);
 	if (err)
@@ -554,7 +553,7 @@
 	 * block.  If we ever do the tail block optimization, we will need to
 	 * handle that here as well.
 	 */
-	if (dn->dn_datablkshift == 0) {
+	if (dn->dn_maxblkid == 0) {
 		int newsz = offset > dn->dn_datablksz ? 0 :
 		    MIN(size, dn->dn_datablksz - offset);
 		bzero((char *)buf + newsz, size - newsz);
@@ -563,6 +562,7 @@
 
 	while (size > 0) {
 		uint64_t mylen = MIN(size, DMU_MAX_ACCESS / 2);
+		int i;
 
 		/*
 		 * NB: we could do this block-at-a-time, but it's nice
--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c	Thu Jul 30 02:52:07 2009 -0400
+++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c	Thu Jul 30 08:43:06 2009 -0400
@@ -855,6 +855,10 @@
 	kmem_free(zgd, sizeof (zgd_t));
 }
 
+#ifdef DEBUG
+static int zil_fault_io = 0;
+#endif
+
 /*
  * Get data to generate a TX_WRITE intent log record.
  */
@@ -936,7 +940,21 @@
 		zgd->zgd_rl = rl;
 		zgd->zgd_zilog = zfsvfs->z_log;
 		zgd->zgd_bp = &lr->lr_blkptr;
-		VERIFY(0 == dmu_buf_hold(os, lr->lr_foid, boff, zgd, &db));
+#ifdef DEBUG
+		if (zil_fault_io) {
+			error = EIO;
+			zil_fault_io = 0;
+		} else {
+			error = dmu_buf_hold(os, lr->lr_foid, boff, zgd, &db);
+		}
+#else
+		error = dmu_buf_hold(os, lr->lr_foid, boff, zgd, &db);
+#endif
+		if (error != 0) {
+			kmem_free(zgd, sizeof (zgd_t));
+			goto out;
+		}
+
 		ASSERT(boff == db->db_offset);
 		lr->lr_blkoff = off - boff;
 		error = dmu_sync(zio, db, &lr->lr_blkptr,
--- a/usr/src/uts/common/fs/zfs/zil.c	Thu Jul 30 02:52:07 2009 -0400
+++ b/usr/src/uts/common/fs/zfs/zil.c	Thu Jul 30 08:43:06 2009 -0400
@@ -926,6 +926,10 @@
 			}
 			error = zilog->zl_get_data(
 			    itx->itx_private, lr, dbuf, lwb->lwb_zio);
+			if (error == EIO) {
+				txg_wait_synced(zilog->zl_dmu_pool, txg);
+				return (lwb);
+			}
 			if (error) {
 				ASSERT(error == ENOENT || error == EEXIST ||
 				    error == EALREADY);