diff options
author | avg <avg@FreeBSD.org> | 2016-08-23 07:55:05 +0000 |
---|---|---|
committer | avg <avg@FreeBSD.org> | 2016-08-23 07:55:05 +0000 |
commit | 676dadf5d990b18804fb8f759fd37d64096786c5 (patch) | |
tree | c35f8d8b5e686bb01018e1dd5096607ae9a6c912 /sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c | |
parent | c9e20f46e50a195b260fd60e06f117050633caab (diff) | |
download | FreeBSD-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.c | 88 |
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); |