diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/common/fs/zfs/arc.c | 4 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/dbuf.c | 2 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/dmu_objset.c | 3 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/dsl_pool.c | 3 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/sys/zfs_znode.h | 1 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_dir.c | 3 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_vnops.c | 13 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_znode.c | 2 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zvol.c | 20 |
9 files changed, 36 insertions, 15 deletions
diff --git a/usr/src/uts/common/fs/zfs/arc.c b/usr/src/uts/common/fs/zfs/arc.c index b23da4d668..e8d3ef0f40 100644 --- a/usr/src/uts/common/fs/zfs/arc.c +++ b/usr/src/uts/common/fs/zfs/arc.c @@ -2363,6 +2363,7 @@ arc_release(arc_buf_t *buf, void *tag) 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 @@ arc_release(arc_buf_t *buf, void *tag) nhdr->b_flags = 0; nhdr->b_datacnt = 1; nhdr->b_freeze_cksum = NULL; - buf->b_hdr = nhdr; - buf->b_next = NULL; (void) refcount_add(&nhdr->b_refcnt, tag); + buf->b_hdr = nhdr; atomic_add_64(&arc_anon->arcs_size, blksz); hdr = nhdr; diff --git a/usr/src/uts/common/fs/zfs/dbuf.c b/usr/src/uts/common/fs/zfs/dbuf.c index 31db9146f8..b3bd8c506b 100644 --- a/usr/src/uts/common/fs/zfs/dbuf.c +++ b/usr/src/uts/common/fs/zfs/dbuf.c @@ -1846,9 +1846,9 @@ dbuf_sync_indirect(dbuf_dirty_record_t *dr, dmu_tx_t *tx) 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 --git a/usr/src/uts/common/fs/zfs/dmu_objset.c b/usr/src/uts/common/fs/zfs/dmu_objset.c index fe2b80f2e6..07f8c864a4 100644 --- a/usr/src/uts/common/fs/zfs/dmu_objset.c +++ b/usr/src/uts/common/fs/zfs/dmu_objset.c @@ -750,9 +750,6 @@ killer(zio_t *zio, arc_buf_t *abuf, void *arg) 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 --git a/usr/src/uts/common/fs/zfs/dsl_pool.c b/usr/src/uts/common/fs/zfs/dsl_pool.c index cbda63af43..7046254db8 100644 --- a/usr/src/uts/common/fs/zfs/dsl_pool.c +++ b/usr/src/uts/common/fs/zfs/dsl_pool.c @@ -182,6 +182,8 @@ dsl_pool_sync(dsl_pool_t *dp, uint64_t txg) 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 @@ dsl_pool_zil_clean(dsl_pool_t *dp) 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 --git a/usr/src/uts/common/fs/zfs/sys/zfs_znode.h b/usr/src/uts/common/fs/zfs/sys/zfs_znode.h index 3113225967..2b52f57c4c 100644 --- a/usr/src/uts/common/fs/zfs/sys/zfs_znode.h +++ b/usr/src/uts/common/fs/zfs/sys/zfs_znode.h @@ -139,6 +139,7 @@ typedef struct znode { 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 --git a/usr/src/uts/common/fs/zfs/zfs_dir.c b/usr/src/uts/common/fs/zfs/zfs_dir.c index bd759a16c1..2f161f987a 100644 --- a/usr/src/uts/common/fs/zfs/zfs_dir.c +++ b/usr/src/uts/common/fs/zfs/zfs_dir.c @@ -100,10 +100,12 @@ zfs_dirent_lock(zfs_dirlock_t **dlpp, znode_t *dzp, char *name, znode_t **zpp, /* * 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_dirent_unlock(zfs_dirlock_t *dl) 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 --git a/usr/src/uts/common/fs/zfs/zfs_vnops.c b/usr/src/uts/common/fs/zfs/zfs_vnops.c index 7afa49b07a..4299bb60f2 100644 --- a/usr/src/uts/common/fs/zfs/zfs_vnops.c +++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c @@ -714,6 +714,7 @@ zfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct) * partial progress, update the znode and ZIL accordingly. */ if (tx_bytes == 0) { + dmu_tx_commit(tx); ASSERT(error != 0); break; } @@ -838,7 +839,6 @@ zfs_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio) } 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 @@ zfs_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio) 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 @@ top: 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 @@ top: 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 @@ top: dmu_tx_commit(tx); rw_exit(&zp->z_parent_lock); + rw_exit(&zp->z_name_lock); out: zfs_dirent_unlock(dl); diff --git a/usr/src/uts/common/fs/zfs/zfs_znode.c b/usr/src/uts/common/fs/zfs/zfs_znode.c index 6fe9847126..b004c1350a 100644 --- a/usr/src/uts/common/fs/zfs/zfs_znode.c +++ b/usr/src/uts/common/fs/zfs/zfs_znode.c @@ -96,6 +96,7 @@ zfs_znode_cache_constructor(void *buf, void *cdrarg, int kmflags) 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 @@ zfs_znode_cache_destructor(void *buf, void *cdarg) 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 --git a/usr/src/uts/common/fs/zfs/zvol.c b/usr/src/uts/common/fs/zfs/zvol.c index 4628ff4aa3..1335207aa6 100644 --- a/usr/src/uts/common/fs/zfs/zvol.c +++ b/usr/src/uts/common/fs/zfs/zvol.c @@ -961,9 +961,10 @@ int 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 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) 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 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) 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: |