The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=99cb3dca4773fe4a16c500f9cb55fcd62cd8d7f3
commit 99cb3dca4773fe4a16c500f9cb55fcd62cd8d7f3 Author: Mark Johnston <[email protected]> AuthorDate: 2025-11-11 14:47:06 +0000 Commit: Mark Johnston <[email protected]> CommitDate: 2025-11-11 14:58:59 +0000 vnode: Rework vput() to avoid holding the vnode lock after decrementing It is not safe to modify the vnode structure after releasing one's reference. Modify vput() to avoid this. Use refcount_release_if_last() to opportunistically call vput_final() with the vnode lock held since we need the vnode lock in order to deactivate the vnode, and it's silly to drop the vnode lock and immediately reacquire it in this common case. Note that vunref() has a similar flaw. D52628 aims to fix the problem more holistically, but this change fixes observable panics in the meantime. Reported by: [email protected] Reported by: [email protected] Reviewed by: kib MFC after: 3 days Differential Revision: https://reviews.freebsd.org/D52608 --- sys/kern/vfs_subr.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 58975f7ac932..9cf983f6f89d 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -3713,11 +3713,12 @@ vput(struct vnode *vp) ASSERT_VOP_LOCKED(vp, __func__); ASSERT_VI_UNLOCKED(vp, __func__); - if (!refcount_release(&vp->v_usecount)) { - VOP_UNLOCK(vp); + if (refcount_release_if_last(&vp->v_usecount)) { + vput_final(vp, VPUT); return; } - vput_final(vp, VPUT); + VOP_UNLOCK(vp); + vrele(vp); } /*
