The branch main has been updated by rlibby: URL: https://cgit.FreeBSD.org/src/commit/?id=33355275247c462e1204bd1db5905a7d132eb502
commit 33355275247c462e1204bd1db5905a7d132eb502 Author: Ryan Libby <[email protected]> AuthorDate: 2026-05-13 17:43:21 +0000 Commit: Ryan Libby <[email protected]> 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;
