summaryrefslogtreecommitdiffstats
path: root/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
diff options
context:
space:
mode:
authoravg <avg@FreeBSD.org>2016-08-23 07:55:05 +0000
committeravg <avg@FreeBSD.org>2016-08-23 07:55:05 +0000
commit676dadf5d990b18804fb8f759fd37d64096786c5 (patch)
treec35f8d8b5e686bb01018e1dd5096607ae9a6c912 /sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
parentc9e20f46e50a195b260fd60e06f117050633caab (diff)
downloadFreeBSD-src-676dadf5d990b18804fb8f759fd37d64096786c5.zip
FreeBSD-src-676dadf5d990b18804fb8f759fd37d64096786c5.tar.gz
MFC r303763,303791,303869: zfs: honour and make use of vfs vnode locking protocol
PR: 209158
Diffstat (limited to 'sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c')
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c88
1 files changed, 40 insertions, 48 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
index 3853838..c947e54 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
@@ -124,16 +124,12 @@ zfs_znode_cache_constructor(void *buf, void *arg, int kmflags)
list_link_init(&zp->z_link_node);
- mutex_init(&zp->z_lock, NULL, MUTEX_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);
avl_create(&zp->z_range_avl, zfs_range_compare,
sizeof (rl_t), offsetof(rl_t, r_node));
- zp->z_dirlocks = NULL;
zp->z_acl_cached = NULL;
zp->z_vnode = NULL;
zp->z_moved = 0;
@@ -150,14 +146,10 @@ zfs_znode_cache_destructor(void *buf, void *arg)
ASSERT(ZTOV(zp) == NULL);
vn_free(ZTOV(zp));
ASSERT(!list_link_active(&zp->z_link_node));
- mutex_destroy(&zp->z_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);
mutex_destroy(&zp->z_range_lock);
- ASSERT(zp->z_dirlocks == NULL);
ASSERT(zp->z_acl_cached == NULL);
}
@@ -559,8 +551,6 @@ zfs_znode_sa_init(zfsvfs_t *zfsvfs, znode_t *zp,
ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs) || (zfsvfs == zp->z_zfsvfs));
ASSERT(MUTEX_HELD(ZFS_OBJ_MUTEX(zfsvfs, zp->z_id)));
- mutex_enter(&zp->z_lock);
-
ASSERT(zp->z_sa_hdl == NULL);
ASSERT(zp->z_acl_cached == NULL);
if (sa_hdl == NULL) {
@@ -580,7 +570,6 @@ zfs_znode_sa_init(zfsvfs_t *zfsvfs, znode_t *zp,
if (zp->z_id == zfsvfs->z_root && zfsvfs->z_parent == zfsvfs)
ZTOV(zp)->v_flag |= VROOT;
- mutex_exit(&zp->z_lock);
vn_exists(ZTOV(zp));
}
@@ -637,7 +626,6 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
zp->z_vnode = vp;
vp->v_data = zp;
- ASSERT(zp->z_dirlocks == NULL);
ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs));
zp->z_moved = 0;
@@ -739,7 +727,14 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
/*
* Acquire vnode lock before making it available to the world.
*/
+#ifdef DIAGNOSTIC
+ vop_lock1_t *orig_lock = vp->v_op->vop_lock1;
+ vp->v_op->vop_lock1 = vop_stdlock;
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ vp->v_op->vop_lock1 = orig_lock;
+#else
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+#endif
VN_LOCK_AREC(vp);
if (vp->v_type != VFIFO)
VN_LOCK_ASHARE(vp);
@@ -1161,54 +1156,55 @@ again:
if (hdl != NULL) {
zp = sa_get_userdata(hdl);
-
/*
* Since "SA" does immediate eviction we
* should never find a sa handle that doesn't
* know about the znode.
*/
-
ASSERT3P(zp, !=, NULL);
-
- mutex_enter(&zp->z_lock);
ASSERT3U(zp->z_id, ==, obj_num);
- if (zp->z_unlinked) {
- err = SET_ERROR(ENOENT);
- } else {
- vp = ZTOV(zp);
- *zpp = zp;
- err = 0;
- }
+ *zpp = zp;
+ vp = ZTOV(zp);
/* Don't let the vnode disappear after ZFS_OBJ_HOLD_EXIT. */
- if (err == 0)
- VN_HOLD(vp);
+ VN_HOLD(vp);
- mutex_exit(&zp->z_lock);
sa_buf_rele(db, NULL);
ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
- if (err == 0) {
- locked = VOP_ISLOCKED(vp);
- VI_LOCK(vp);
- if ((vp->v_iflag & VI_DOOMED) != 0 &&
- locked != LK_EXCLUSIVE) {
- /*
- * The vnode is doomed and this thread doesn't
- * hold the exclusive lock on it, so the vnode
- * must be being reclaimed by another thread.
- * Otherwise the doomed vnode is being reclaimed
- * by this thread and zfs_zget is called from
- * ZIL internals.
- */
- VI_UNLOCK(vp);
- VN_RELE(vp);
- goto again;
- }
+ locked = VOP_ISLOCKED(vp);
+ VI_LOCK(vp);
+ if ((vp->v_iflag & VI_DOOMED) != 0 &&
+ locked != LK_EXCLUSIVE) {
+ /*
+ * The vnode is doomed and this thread doesn't
+ * hold the exclusive lock on it, so the vnode
+ * must be being reclaimed by another thread.
+ * Otherwise the doomed vnode is being reclaimed
+ * by this thread and zfs_zget is called from
+ * ZIL internals.
+ */
VI_UNLOCK(vp);
+
+ /*
+ * XXX vrele() locks the vnode when the last reference
+ * is dropped. Although in this case the vnode is
+ * doomed / dead and so no inactivation is required,
+ * the vnode lock is still acquired. That could result
+ * in a LOR with z_teardown_lock if another thread holds
+ * the vnode's lock and tries to take z_teardown_lock.
+ * But that is only possible if the other thread peforms
+ * a ZFS vnode operation on the vnode. That either
+ * should not happen if the vnode is dead or the thread
+ * should also have a refrence to the vnode and thus
+ * our reference is not last.
+ */
+ VN_RELE(vp);
+ goto again;
}
+ VI_UNLOCK(vp);
getnewvnode_drop_reserve();
- return (err);
+ return (0);
}
/*
@@ -1391,20 +1387,16 @@ zfs_zinactive(znode_t *zp)
*/
ZFS_OBJ_HOLD_ENTER(zfsvfs, z_id);
- mutex_enter(&zp->z_lock);
-
/*
* If this was the last reference to a file with no links,
* remove the file from the file system.
*/
if (zp->z_unlinked) {
- mutex_exit(&zp->z_lock);
ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id);
zfs_rmnode(zp);
return;
}
- mutex_exit(&zp->z_lock);
zfs_znode_dmu_fini(zp);
ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id);
zfs_znode_free(zp);
OpenPOWER on IntegriCloud