summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/fs/zfs/arc.c4
-rw-r--r--usr/src/uts/common/fs/zfs/dbuf.c2
-rw-r--r--usr/src/uts/common/fs/zfs/dmu_objset.c3
-rw-r--r--usr/src/uts/common/fs/zfs/dsl_pool.c3
-rw-r--r--usr/src/uts/common/fs/zfs/sys/zfs_znode.h1
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_dir.c3
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_vnops.c13
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_znode.c2
-rw-r--r--usr/src/uts/common/fs/zfs/zvol.c20
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: