aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndriy Gapon <[email protected]>2023-03-07 02:30:54 +0200
committerGitHub <[email protected]>2023-03-06 16:30:54 -0800
commit28bf26acb6735f95c47e3f1056cd1142607c0bcc (patch)
tree31f67b4d3d99d5764cce538b43dc8036c133accf
parentca9e32d3a7f47cf9b4c564f5b16beadc29647804 (diff)
[FreeBSD] zfs_znode_alloc: lock the vnode earlier
This is needed because of a possible error path where zfs_vnode_forget() is called. That function calls vgone() and vput(), the former requires the vnode to be exclusively locked and the latter expects it to be locked. It should be safe to lock the vnode as early as possible because it is not yet visible, so there is no interaction with other locks. While here, remove a tautological assignment to 'vp'. Reviewed-by: Alexander Motin <[email protected]> Reviewed-by: Richard Yao <[email protected]> Signed-off-by: Andriy Gapon <[email protected]> Closes #14565
-rw-r--r--module/os/freebsd/zfs/zfs_znode.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/module/os/freebsd/zfs/zfs_znode.c b/module/os/freebsd/zfs/zfs_znode.c
index 76ae09f81..304bc71f9 100644
--- a/module/os/freebsd/zfs/zfs_znode.c
+++ b/module/os/freebsd/zfs/zfs_znode.c
@@ -448,6 +448,13 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
zp->z_vnode = vp;
vp->v_data = zp;
+ /*
+ * Acquire the vnode lock before any possible interaction with the
+ * outside world. Specifically, there is an error path that calls
+ * zfs_vnode_forget() and the vnode should be exclusively locked.
+ */
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+
ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs));
zp->z_sa_hdl = NULL;
@@ -464,8 +471,6 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
atomic_store_ptr(&zp->z_cached_symlink, NULL);
#endif
- vp = ZTOV(zp);
-
zfs_znode_sa_init(zfsvfs, zp, db, obj_type, hdl);
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL, &mode, 8);
@@ -535,10 +540,6 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
zp->z_zfsvfs = zfsvfs;
mutex_exit(&zfsvfs->z_znodes_lock);
- /*
- * Acquire vnode lock before making it available to the world.
- */
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
#if __FreeBSD_version >= 1400077
vn_set_state(vp, VSTATE_CONSTRUCTED);
#endif