git: ef9f11abea38 - stable/15 - vfs: work around the race between vget() and vnlru

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Sun, 21 Jun 2026 10:15:55 UTC
The branch stable/15 has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=ef9f11abea383fd55d027a270532bc030f90d805

commit ef9f11abea383fd55d027a270532bc030f90d805
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-05-28 09:42:38 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-06-21 10:05:27 +0000

    vfs: work around the race between vget() and vnlru
    
    PR:     281749
    
    (cherry picked from commit 36b155a2b3baa747c1968a9094df9fa7fb0d02b3)
---
 sys/kern/vfs_subr.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 5248f7fad25f..d2894858fc94 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -1931,9 +1931,14 @@ vtryrecycle(struct vnode *vp, bool isvnlru)
 	 * anyone picked up this vnode from another list.  If not, we will
 	 * mark it with DOOMED via vgonel() so that anyone who does find it
 	 * will skip over it.
+	 *
+	 * We cannot check only for v_usecount > 0 there, since
+	 * v_usecount increment is lockless.  Instead check for
+	 * v_holdcnt > 1, with the side effect that a parallel vhold()
+	 * also aborts freeing this vnode.
 	 */
 	VI_LOCK(vp);
-	if (vp->v_usecount) {
+	if (vp->v_holdcnt > 1) {
 		VOP_UNLOCK(vp);
 		vdropl_recycle(vp);
 		vn_finished_write(vnmp);