6407842 zfs panic when closing a file
authormaybee
Mon, 17 Apr 2006 11:37:08 -0700
changeset 1819 570a79e4d798
parent 1818 e8dfcbd4692e
child 1820 0d1dc50542d0
6407842 zfs panic when closing a file 6410836 zfs umount hang during ZFS stress testing.
usr/src/uts/common/fs/zfs/arc.c
usr/src/uts/common/fs/zfs/dbuf.c
usr/src/uts/common/fs/zfs/dmu_tx.c
usr/src/uts/common/fs/zfs/zfs_vnops.c
--- a/usr/src/uts/common/fs/zfs/arc.c	Mon Apr 17 10:16:06 2006 -0700
+++ b/usr/src/uts/common/fs/zfs/arc.c	Mon Apr 17 11:37:08 2006 -0700
@@ -1077,8 +1077,8 @@
 		buf->b_hdr = NULL;
 		mutex_exit(&arc_eviction_mtx);
 
-		ASSERT(buf->b_efunc != NULL);
-		VERIFY(buf->b_efunc(buf) == 0);
+		if (buf->b_efunc != NULL)
+			VERIFY(buf->b_efunc(buf) == 0);
 
 		buf->b_efunc = NULL;
 		buf->b_private = NULL;
@@ -1943,15 +1943,16 @@
 		mutex_exit(&arc_eviction_mtx);
 		return (0);
 	} else if (buf->b_data == NULL) {
+		arc_buf_t copy = *buf; /* structure assignment */
 		/*
-		 * We are on the eviction list, pull us off.
+		 * We are on the eviction list.  Process this buffer
+		 * now but let arc_do_user_evicts() do the reaping.
 		 */
-		bufp = &arc_eviction_list;
-		while (*bufp != buf)
-			bufp = &(*bufp)->b_next;
-		*bufp = buf->b_next;
+		buf->b_efunc = NULL;
+		buf->b_hdr = NULL;
 		mutex_exit(&arc_eviction_mtx);
-		goto out;
+		VERIFY(copy.b_efunc(&copy) == 0);
+		return (1);
 	} else {
 		/*
 		 * Prevent a race with arc_evict()
@@ -1998,7 +1999,7 @@
 		mutex_exit(&old_state->mtx);
 	}
 	mutex_exit(hash_lock);
-out:
+
 	VERIFY(buf->b_efunc(buf) == 0);
 	buf->b_efunc = NULL;
 	buf->b_private = NULL;
--- a/usr/src/uts/common/fs/zfs/dbuf.c	Mon Apr 17 10:16:06 2006 -0700
+++ b/usr/src/uts/common/fs/zfs/dbuf.c	Mon Apr 17 11:37:08 2006 -0700
@@ -1394,7 +1394,6 @@
 	if (!MUTEX_HELD(&db->db_mtx))
 		mutex_enter(&db->db_mtx);
 
-	ASSERT(db->db_buf == buf);
 	ASSERT(refcount_is_zero(&db->db_holds));
 
 	if (db->db_state != DB_EVICTING) {
--- a/usr/src/uts/common/fs/zfs/dmu_tx.c	Mon Apr 17 10:16:06 2006 -0700
+++ b/usr/src/uts/common/fs/zfs/dmu_tx.c	Mon Apr 17 11:37:08 2006 -0700
@@ -318,7 +318,7 @@
 {
 	ASSERT(tx->tx_txg == 0);
 	ASSERT(len < DMU_MAX_ACCESS);
-	ASSERT(UINT64_MAX - off >= len - 1);
+	ASSERT(len == 0 || UINT64_MAX - off >= len - 1);
 
 	dmu_tx_hold_object_impl(tx, tx->tx_objset, object, THT_WRITE,
 	    dmu_tx_hold_write_impl, off, len);
--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c	Mon Apr 17 10:16:06 2006 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c	Mon Apr 17 11:37:08 2006 -0700
@@ -2823,6 +2823,13 @@
 top:
 	off = pp->p_offset;
 	rl = zfs_range_lock(zp, off, PAGESIZE, RL_WRITER);
+	/*
+	 * Can't push pages past end-of-file.
+	 */
+	if (off >= zp->z_phys->zp_size) {
+		zfs_range_unlock(zp, rl);
+		return (EIO);
+	}
 	len = MIN(PAGESIZE, zp->z_phys->zp_size - off);
 
 	tx = dmu_tx_create(zfsvfs->z_os);
@@ -3087,8 +3094,9 @@
 			klen = plsz;
 			koff = P2ALIGN(off, (u_offset_t)klen);
 		}
-		if (klen > filesz)
-			klen = P2ROUNDUP(filesz, (uint64_t)PAGESIZE);
+		ASSERT(koff <= filesz);
+		if (koff + klen > filesz)
+			klen = P2ROUNDUP(filesz, (uint64_t)PAGESIZE) - koff;
 		pp = pvn_read_kluster(vp, off, seg, addr, &io_off,
 			    &io_len, koff, klen, 0);
 	}