The branch main has been updated by kib:

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

commit 36b155a2b3baa747c1968a9094df9fa7fb0d02b3
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2026-05-28 09:42:38 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2026-06-14 02:02:38 +0000

    vfs: work around the race between vget() and vnlru
    
    Specifically, do not let vtryrecycle() to recycle a used vnode. It is
    possible for a vnode to be vref-ed or vuse-ed lockless after it is held
    by vhold_recycle_free(). Then, since vtryrecycle() does not recheck the
    hold count, we might end up freeing vused vnode.
    
    Since vget_finish() increments v_usecount after obtaining the vnode
    lock, we would observe the hold reference anyway when the parallel
    vget() is blocked waiting on the vnode lock.
    
    PR:     281749
    Reported and tested by: Steve Peurifoy <[email protected]>, Vladimir 
Grebenshchikov <[email protected]>
    Reviewed by:    olce
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D57305
---
 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 65529bc195bb..7b2718269a1f 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -1936,9 +1936,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);

Reply via email to