changeset 1793:d371fba21a3e

6407444 unhandled i/o error from dnode_next_offset_level() 6411780 unhandled i/o error from dnode_sync_free() due to faulty pre-read logic
author ahrens
date Tue, 11 Apr 2006 15:06:44 -0700
parents 7e25f1c5948e
children bc0b5efe21a1
files usr/src/lib/libzfs/common/libzfs_dataset.c usr/src/uts/common/fs/zfs/dmu_tx.c usr/src/uts/common/fs/zfs/dnode.c
diffstat 3 files changed, 43 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c	Tue Apr 11 13:06:32 2006 -0700
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c	Tue Apr 11 15:06:44 2006 -0700
@@ -2073,6 +2073,15 @@
 			    zhp->zfs_name);
 			break;
 
+		case EIO:
+			/*
+			 * I/O error.
+			 */
+			zfs_error(dgettext(TEXT_DOMAIN,
+			    "cannot destroy '%s': I/O error"),
+			    zhp->zfs_name);
+			break;
+
 		case ENOENT:
 			/*
 			 * We've hit a race condition where the dataset has been
--- a/usr/src/uts/common/fs/zfs/dmu_tx.c	Tue Apr 11 13:06:32 2006 -0700
+++ b/usr/src/uts/common/fs/zfs/dmu_tx.c	Tue Apr 11 15:06:44 2006 -0700
@@ -449,7 +449,7 @@
 	zio_t *zio;
 
 	/* first block */
-	if (off != 0 /* || dn->dn_maxblkid == 0 */)
+	if (off != 0)
 		dmu_tx_count_write(tx, dn, off, 1);
 	/* last block */
 	if (len != DMU_OBJECT_END)
@@ -465,32 +465,36 @@
 	 * blocks, and all the level-1 blocks.  The above count_write's
 	 * will take care of the level-0 blocks.
 	 */
-	shift = dn->dn_datablkshift + dn->dn_indblkshift - SPA_BLKPTRSHIFT;
-	start = off >> shift;
-	end = dn->dn_datablkshift ? ((off+len) >> shift) : 0;
+	if (dn->dn_nlevels > 1) {
+		shift = dn->dn_datablkshift + dn->dn_indblkshift -
+		    SPA_BLKPTRSHIFT;
+		start = off >> shift;
+		end = dn->dn_datablkshift ? ((off+len) >> shift) : 0;
 
-	zio = zio_root(tx->tx_pool->dp_spa, NULL, NULL, ZIO_FLAG_CANFAIL);
-	for (i = start+1; i < end; i++) {
-		uint64_t ibyte = i << shift;
-		err = dnode_next_offset(dn, FALSE, &ibyte, 2, 1);
-		i = ibyte >> shift;
-		if (err == ESRCH)
-			break;
+		zio = zio_root(tx->tx_pool->dp_spa,
+		    NULL, NULL, ZIO_FLAG_CANFAIL);
+		for (i = start; i <= end; i++) {
+			uint64_t ibyte = i << shift;
+			err = dnode_next_offset(dn, FALSE, &ibyte, 2, 1);
+			i = ibyte >> shift;
+			if (err == ESRCH)
+				break;
+			if (err) {
+				tx->tx_err = err;
+				return;
+			}
+
+			err = dmu_tx_check_ioerr(zio, dn, 1, i);
+			if (err) {
+				tx->tx_err = err;
+				return;
+			}
+		}
+		err = zio_wait(zio);
 		if (err) {
 			tx->tx_err = err;
 			return;
 		}
-
-		err = dmu_tx_check_ioerr(zio, dn, 1, i);
-		if (err) {
-			tx->tx_err = err;
-			return;
-		}
-	}
-	err = zio_wait(zio);
-	if (err) {
-		tx->tx_err = err;
-		return;
 	}
 
 	dmu_tx_count_dnode(tx, dn);
--- a/usr/src/uts/common/fs/zfs/dnode.c	Tue Apr 11 13:06:32 2006 -0700
+++ b/usr/src/uts/common/fs/zfs/dnode.c	Tue Apr 11 15:06:44 2006 -0700
@@ -1180,8 +1180,11 @@
 				return (hole ? 0 : ESRCH);
 			return (error);
 		}
-		(void) dbuf_read(db, NULL,
-		    DB_RF_MUST_SUCCEED | DB_RF_HAVESTRUCT);
+		error = dbuf_read(db, NULL, DB_RF_CANFAIL | DB_RF_HAVESTRUCT);
+		if (error) {
+			dbuf_rele(db, FTAG);
+			return (error);
+		}
 		data = db->db.db_data;
 	}
 
@@ -1275,7 +1278,7 @@
 
 	for (lvl = minlvl; lvl <= maxlvl; lvl++) {
 		error = dnode_next_offset_level(dn, hole, offset, lvl, blkfill);
-		if (error == 0)
+		if (error != ESRCH)
 			break;
 	}
 
@@ -1284,8 +1287,8 @@
 
 	rw_exit(&dn->dn_struct_rwlock);
 
-	if (initial_offset > *offset)
-		return (ESRCH);
+	if (error == 0 && initial_offset > *offset)
+		error = ESRCH;
 
 	return (error);
 }