changeset 3897:278bade789ba

6437750 panic: db->db_buf==0||arc_referenced(db->db_buf), file: dbuf.c,line:1539 6466866 assertion failed: dlen <= zp->z_blksz (0x188b4 <= 0x13200), zfs_vnops.c, line: 884 6512661 unowned mutex panic during stress test 6524889 Hang adding zvol-based devices to a pool or creating a pool from zvols 6531759 zfs_rmdir() can return EEXIST on an empty directory when spotlight is messing with it 6532056 missing dmu_tx_commit() in zfs_write() eventually hangs zfs
author maybee
date Mon, 26 Mar 2007 12:01:20 -0700
parents 1d5fb739bf40
children c788126f2a20
files usr/src/uts/common/fs/zfs/arc.c usr/src/uts/common/fs/zfs/dbuf.c usr/src/uts/common/fs/zfs/dmu_objset.c usr/src/uts/common/fs/zfs/dsl_pool.c usr/src/uts/common/fs/zfs/sys/zfs_znode.h usr/src/uts/common/fs/zfs/zfs_dir.c usr/src/uts/common/fs/zfs/zfs_vnops.c usr/src/uts/common/fs/zfs/zfs_znode.c usr/src/uts/common/fs/zfs/zvol.c
diffstat 9 files changed, 36 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/arc.c	Mon Mar 26 10:41:59 2007 -0700
+++ b/usr/src/uts/common/fs/zfs/arc.c	Mon Mar 26 12:01:20 2007 -0700
@@ -2363,6 +2363,7 @@
 		while (*bufp != buf)
 			bufp = &(*bufp)->b_next;
 		*bufp = (*bufp)->b_next;
+		buf->b_next = NULL;
 
 		ASSERT3U(hdr->b_state->arcs_size, >=, hdr->b_size);
 		atomic_add_64(&hdr->b_state->arcs_size, -hdr->b_size);
@@ -2385,9 +2386,8 @@
 		nhdr->b_flags = 0;
 		nhdr->b_datacnt = 1;
 		nhdr->b_freeze_cksum = NULL;
+		(void) refcount_add(&nhdr->b_refcnt, tag);
 		buf->b_hdr = nhdr;
-		buf->b_next = NULL;
-		(void) refcount_add(&nhdr->b_refcnt, tag);
 		atomic_add_64(&arc_anon->arcs_size, blksz);
 
 		hdr = nhdr;
--- a/usr/src/uts/common/fs/zfs/dbuf.c	Mon Mar 26 10:41:59 2007 -0700
+++ b/usr/src/uts/common/fs/zfs/dbuf.c	Mon Mar 26 12:01:20 2007 -0700
@@ -1846,9 +1846,9 @@
 	dbuf_check_blkptr(dn, db);
 
 	db->db_data_pending = dr;
-	mutex_exit(&db->db_mtx);
 
 	arc_release(db->db_buf, db);
+	mutex_exit(&db->db_mtx);
 
 	/*
 	 * XXX -- we should design a compression algorithm
--- a/usr/src/uts/common/fs/zfs/dmu_objset.c	Mon Mar 26 10:41:59 2007 -0700
+++ b/usr/src/uts/common/fs/zfs/dmu_objset.c	Mon Mar 26 12:01:20 2007 -0700
@@ -750,9 +750,6 @@
 		    os->os_synctx);
 	}
 	arc_release(os->os_phys_buf, &os->os_phys_buf);
-
-	if (os->os_dsl_dataset)
-		dmu_buf_rele(os->os_dsl_dataset->ds_dbuf, os->os_dsl_dataset);
 }
 
 /* called from dsl */
--- a/usr/src/uts/common/fs/zfs/dsl_pool.c	Mon Mar 26 10:41:59 2007 -0700
+++ b/usr/src/uts/common/fs/zfs/dsl_pool.c	Mon Mar 26 12:01:20 2007 -0700
@@ -182,6 +182,8 @@
 	while (ds = txg_list_remove(&dp->dp_dirty_datasets, txg)) {
 		if (!list_link_active(&ds->ds_synced_link))
 			list_insert_tail(&dp->dp_synced_objsets, ds);
+		else
+			dmu_buf_rele(ds->ds_dbuf, ds);
 		dsl_dataset_sync(ds, zio, tx);
 	}
 	err = zio_wait(zio);
@@ -214,6 +216,7 @@
 		list_remove(&dp->dp_synced_objsets, ds);
 		ASSERT(ds->ds_user_ptr != NULL);
 		zil_clean(((objset_impl_t *)ds->ds_user_ptr)->os_zil);
+		dmu_buf_rele(ds->ds_dbuf, ds);
 	}
 }
 
--- a/usr/src/uts/common/fs/zfs/sys/zfs_znode.h	Mon Mar 26 10:41:59 2007 -0700
+++ b/usr/src/uts/common/fs/zfs/sys/zfs_znode.h	Mon Mar 26 12:01:20 2007 -0700
@@ -139,6 +139,7 @@
 	kmutex_t	z_lock;		/* znode modification lock */
 	krwlock_t	z_map_lock;	/* page map lock */
 	krwlock_t	z_parent_lock;	/* parent lock for directories */
+	krwlock_t	z_name_lock;	/* "master" lock for dirent locks */
 	zfs_dirlock_t	*z_dirlocks;	/* directory entry lock list */
 	kmutex_t	z_range_lock;	/* protects changes to z_range_avl */
 	avl_tree_t	z_range_avl;	/* avl tree of file range locks */
--- a/usr/src/uts/common/fs/zfs/zfs_dir.c	Mon Mar 26 10:41:59 2007 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_dir.c	Mon Mar 26 12:01:20 2007 -0700
@@ -100,10 +100,12 @@
 	/*
 	 * Wait until there are no locks on this name.
 	 */
+	rw_enter(&dzp->z_name_lock, RW_READER);
 	mutex_enter(&dzp->z_lock);
 	for (;;) {
 		if (dzp->z_unlinked) {
 			mutex_exit(&dzp->z_lock);
+			rw_exit(&dzp->z_name_lock);
 			return (ENOENT);
 		}
 		for (dl = dzp->z_dirlocks; dl != NULL; dl = dl->dl_next)
@@ -208,6 +210,7 @@
 	zfs_dirlock_t **prev_dl, *cur_dl;
 
 	mutex_enter(&dzp->z_lock);
+	rw_exit(&dzp->z_name_lock);
 	if (dl->dl_sharecnt > 1) {
 		dl->dl_sharecnt--;
 		mutex_exit(&dzp->z_lock);
--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c	Mon Mar 26 10:41:59 2007 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c	Mon Mar 26 12:01:20 2007 -0700
@@ -714,6 +714,7 @@
 		 * partial progress, update the znode and ZIL accordingly.
 		 */
 		if (tx_bytes == 0) {
+			dmu_tx_commit(tx);
 			ASSERT(error != 0);
 			break;
 		}
@@ -838,7 +839,6 @@
 	} else { /* indirect write */
 		uint64_t boff; /* block starting offset */
 
-		ASSERT3U(dlen, <=, zp->z_blksz);
 		/*
 		 * Have to lock the whole block to ensure when it's
 		 * written out and it's checksum is being calculated
@@ -872,6 +872,7 @@
 		lr->lr_blkoff = off - boff;
 		error = dmu_sync(zio, db, &lr->lr_blkptr,
 		    lr->lr_common.lrc_txg, zfs_get_done, zgd);
+		ASSERT(error == EEXIST || lr->lr_length <= zp->z_blksz);
 		if (error == 0) {
 			zil_add_vdev(zfsvfs->z_log,
 			    DVA_GET_VDEV(BP_IDENTITY(&lr->lr_blkptr)));
@@ -1512,7 +1513,13 @@
 	vnevent_rmdir(vp);
 
 	/*
-	 * Grab a lock on the parent pointer make sure we play well
+	 * Grab a lock on the directory to make sure that noone is
+	 * trying to add (or lookup) entries while we are removing it.
+	 */
+	rw_enter(&zp->z_name_lock, RW_WRITER);
+
+	/*
+	 * Grab a lock on the parent pointer to make sure we play well
 	 * with the treewalk and directory rename code.
 	 */
 	rw_enter(&zp->z_parent_lock, RW_WRITER);
@@ -1524,6 +1531,7 @@
 	error = dmu_tx_assign(tx, zfsvfs->z_assign);
 	if (error) {
 		rw_exit(&zp->z_parent_lock);
+		rw_exit(&zp->z_name_lock);
 		zfs_dirent_unlock(dl);
 		VN_RELE(vp);
 		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
@@ -1544,6 +1552,7 @@
 	dmu_tx_commit(tx);
 
 	rw_exit(&zp->z_parent_lock);
+	rw_exit(&zp->z_name_lock);
 out:
 	zfs_dirent_unlock(dl);
 
--- a/usr/src/uts/common/fs/zfs/zfs_znode.c	Mon Mar 26 10:41:59 2007 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_znode.c	Mon Mar 26 12:01:20 2007 -0700
@@ -96,6 +96,7 @@
 	mutex_init(&zp->z_lock, NULL, MUTEX_DEFAULT, NULL);
 	rw_init(&zp->z_map_lock, NULL, RW_DEFAULT, NULL);
 	rw_init(&zp->z_parent_lock, NULL, RW_DEFAULT, NULL);
+	rw_init(&zp->z_name_lock, NULL, RW_DEFAULT, NULL);
 	mutex_init(&zp->z_acl_lock, NULL, MUTEX_DEFAULT, NULL);
 
 	mutex_init(&zp->z_range_lock, NULL, MUTEX_DEFAULT, NULL);
@@ -117,6 +118,7 @@
 	mutex_destroy(&zp->z_lock);
 	rw_destroy(&zp->z_map_lock);
 	rw_destroy(&zp->z_parent_lock);
+	rw_destroy(&zp->z_name_lock);
 	mutex_destroy(&zp->z_acl_lock);
 	avl_destroy(&zp->z_range_avl);
 
--- a/usr/src/uts/common/fs/zfs/zvol.c	Mon Mar 26 10:41:59 2007 -0700
+++ b/usr/src/uts/common/fs/zfs/zvol.c	Mon Mar 26 12:01:20 2007 -0700
@@ -961,9 +961,10 @@
 zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
 {
 	zvol_state_t *zv;
-	struct dk_cinfo dkc;
+	struct dk_cinfo dki;
 	struct dk_minfo dkm;
 	dk_efi_t efi;
+	struct dk_callback *dkc;
 	struct uuid uuid = EFI_RESERVED;
 	uint32_t crc;
 	int error = 0;
@@ -980,13 +981,13 @@
 	switch (cmd) {
 
 	case DKIOCINFO:
-		bzero(&dkc, sizeof (dkc));
-		(void) strcpy(dkc.dki_cname, "zvol");
-		(void) strcpy(dkc.dki_dname, "zvol");
-		dkc.dki_ctype = DKC_UNKNOWN;
-		dkc.dki_maxtransfer = 1 << (SPA_MAXBLOCKSHIFT - zv->zv_min_bs);
+		bzero(&dki, sizeof (dki));
+		(void) strcpy(dki.dki_cname, "zvol");
+		(void) strcpy(dki.dki_dname, "zvol");
+		dki.dki_ctype = DKC_UNKNOWN;
+		dki.dki_maxtransfer = 1 << (SPA_MAXBLOCKSHIFT - zv->zv_min_bs);
 		mutex_exit(&zvol_state_lock);
-		if (ddi_copyout(&dkc, (void *)arg, sizeof (dkc), flag))
+		if (ddi_copyout(&dki, (void *)arg, sizeof (dki), flag))
 			error = EFAULT;
 		return (error);
 
@@ -1074,7 +1075,12 @@
 		return (error);
 
 	case DKIOCFLUSHWRITECACHE:
+		dkc = (struct dk_callback *)arg;
 		zil_commit(zv->zv_zilog, UINT64_MAX, ZVOL_OBJ);
+		if ((flag & FKIOCTL) && dkc != NULL && dkc->dkc_callback) {
+			(*dkc->dkc_callback)(dkc->dkc_cookie, error);
+			error = 0;
+		}
 		break;
 
 	case DKIOCGGEOM: