diff --git a/module/os/freebsd/zfs/zfs_znode.c b/module/os/freebsd/zfs/zfs_znode.c index 76ae09f811..304bc71f90 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