# HG changeset patch # User maybee # Date 1174935680 25200 # Node ID 278bade789ba739d23c153615d8c556045874b9e # Parent 1d5fb739bf40d07bbfc859deffb319cc29f0aee5 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 diff -r 1d5fb739bf40 -r 278bade789ba usr/src/uts/common/fs/zfs/arc.c --- 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; diff -r 1d5fb739bf40 -r 278bade789ba usr/src/uts/common/fs/zfs/dbuf.c --- 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 diff -r 1d5fb739bf40 -r 278bade789ba usr/src/uts/common/fs/zfs/dmu_objset.c --- 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 */ diff -r 1d5fb739bf40 -r 278bade789ba usr/src/uts/common/fs/zfs/dsl_pool.c --- 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); } } diff -r 1d5fb739bf40 -r 278bade789ba usr/src/uts/common/fs/zfs/sys/zfs_znode.h --- 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 */ diff -r 1d5fb739bf40 -r 278bade789ba usr/src/uts/common/fs/zfs/zfs_dir.c --- 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); diff -r 1d5fb739bf40 -r 278bade789ba usr/src/uts/common/fs/zfs/zfs_vnops.c --- 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); diff -r 1d5fb739bf40 -r 278bade789ba usr/src/uts/common/fs/zfs/zfs_znode.c --- 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); diff -r 1d5fb739bf40 -r 278bade789ba usr/src/uts/common/fs/zfs/zvol.c --- 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: