git: 36b155a2b3ba - main - vfs: work around the race between vget() and vnlru
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 14 Jun 2026 02:05:14 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=36b155a2b3baa747c1968a9094df9fa7fb0d02b3
commit 36b155a2b3baa747c1968a9094df9fa7fb0d02b3
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-05-28 09:42:38 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
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 <ssw01@mathistry.net>, Vladimir Grebenshchikov <vova@zote.me>
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);