git: 33355275247c - main - vnlru: avoid cache line contention

From: Ryan Libby <rlibby_at_FreeBSD.org>
Date: Wed, 13 May 2026 17:45:30 UTC
The branch main has been updated by rlibby:

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

commit 33355275247c462e1204bd1db5905a7d132eb502
Author:     Ryan Libby <rlibby@FreeBSD.org>
AuthorDate: 2026-05-13 17:43:21 +0000
Commit:     Ryan Libby <rlibby@FreeBSD.org>
CommitDate: 2026-05-13 17:43:21 +0000

    vnlru: avoid cache line contention
    
    Reviewed by:    kib, olce
    Sponsored by:   Dell Inc.
    Differential Revision:  https://reviews.freebsd.org/D56951
---
 sys/kern/vfs_subr.c | 35 +++++++++++++++++++++--------------
 1 file changed, 21 insertions(+), 14 deletions(-)

diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 4bfbc0a7057e..54e883038046 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -160,13 +160,6 @@ int vttoif_tab[10] = {
 	S_IFSOCK, S_IFIFO, S_IFMT, S_IFMT
 };
 
-/*
- * List of allocates vnodes in the system.
- */
-static TAILQ_HEAD(freelst, vnode) vnode_list;
-static struct vnode *vnode_list_free_marker;
-static struct vnode *vnode_list_reclaim_marker;
-
 /*
  * "Free" vnode target.  Free vnodes are rarely completely free, but are
  * just ones that are cheap to recycle.  Usually they are for files which
@@ -190,7 +183,7 @@ static struct vnode *vnode_list_reclaim_marker;
  * E.g., 9% of 75% of MAXVNODES is more than 566000 vnodes to reclaim
  * whenever vnlru_proc() becomes active.
  */
-static long wantfreevnodes;
+static long __read_mostly wantfreevnodes;
 static long __exclusive_cache_line freevnodes;
 static long freevnodes_old;
 
@@ -326,12 +319,26 @@ static enum { SYNCER_RUNNING, SYNCER_SHUTTING_DOWN, SYNCER_FINAL_DELAY }
     syncer_state;
 
 /* Target for maximum number of vnodes. */
-u_long desiredvnodes;
-static u_long gapvnodes;		/* gap between wanted and desired */
-static u_long vhiwat;		/* enough extras after expansion */
+u_long __read_mostly desiredvnodes;
 static u_long vlowat;		/* minimal extras before expansion */
 static bool vstir;		/* nonzero to stir non-free vnodes */
-static volatile int vsmalltrigger = 8;	/* pref to keep if > this many pages */
+/* pref to keep vnode if > this many resident pages */
+static volatile int __read_mostly vsmalltrigger = 8;
+
+/* Group globals accessed only under vnode_list_mtx together. */
+struct {
+	/* List of allocated vnodes in the system. */
+	TAILQ_HEAD(freelst, vnode) vnode_list;
+	struct vnode *vnode_list_free_marker;
+	struct vnode *vnode_list_reclaim_marker;
+	u_long gapvnodes;	/* gap between wanted and desired */
+	u_long vhiwat;		/* enough extras after expansion */
+} g_vnlru __exclusive_cache_line;
+#define	vnode_list	g_vnlru.vnode_list
+#define	vnode_list_free_marker	g_vnlru.vnode_list_free_marker
+#define	vnode_list_reclaim_marker	g_vnlru.vnode_list_reclaim_marker
+#define	gapvnodes	g_vnlru.gapvnodes
+#define	vhiwat	g_vnlru.vhiwat
 
 static u_long vnlru_read_freevnodes(void);
 
@@ -1345,7 +1352,7 @@ next_iter:
 	return (done);
 }
 
-static int max_free_per_call = 10000;
+static int __read_mostly max_free_per_call = 10000;
 SYSCTL_INT(_debug, OID_AUTO, max_vnlru_free, CTLFLAG_RW, &max_free_per_call, 0,
     "limit on vnode free requests per call to the vnlru_free routine (legacy)");
 SYSCTL_INT(_vfs_vnode_vnlru, OID_AUTO, max_free_per_call, CTLFLAG_RW,
@@ -1535,7 +1542,7 @@ vnlru_recalc(void)
  * Calling vlrurecycle() from the bowels of filesystem code has some
  * interesting deadlock problems.
  */
-static struct proc *vnlruproc;
+static struct proc * __read_mostly vnlruproc;
 static int vnlruproc_sig;
 static u_long vnlruproc_kicks;