From: Alexander Bluhm Subject: Unlock sysctl kern.maxclusters To: tech@openbsd.org Date: Tue, 3 Jun 2025 11:51:11 +0200 Hi, Sysctl KERN_MAXCLUSTERS only needs a mutex to keep nmbclust and mbuf_mem_limit in sync. All other read access happens atomically. ok? bluhm Index: kern/kern_sysctl.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/kern/kern_sysctl.c,v diff -u -p -r1.469 kern_sysctl.c --- kern/kern_sysctl.c 1 Jun 2025 03:43:48 -0000 1.469 +++ kern/kern_sysctl.c 2 Jun 2025 18:27:49 -0000 @@ -553,6 +553,15 @@ kern_sysctl(int *name, u_int namelen, vo microboottime(&bt); return (sysctl_rdstruct(oldp, oldlenp, newp, &bt, sizeof bt)); } + case KERN_MAXCLUSTERS: { + int oval, nval; + + oval = nval = atomic_load_long(&nmbclust); + error = sysctl_int(oldp, oldlenp, newp, newlen, &nval); + if (error == 0 && oval != nval) + error = nmbclust_update(nval); + return (error); + } case KERN_MBSTAT: { uint64_t counters[MBSTAT_COUNT]; struct mbstat mbs; @@ -758,13 +767,6 @@ kern_sysctl_locked(int *name, u_int name return (EINVAL); stackgap_random = stackgap; return (0); - case KERN_MAXCLUSTERS: { - int val = nmbclust; - error = sysctl_int(oldp, oldlenp, newp, newlen, &val); - if (error == 0 && val != nmbclust) - error = nmbclust_update(val); - return (error); - } case KERN_CACHEPCT: { u_int64_t dmapages; int opct, pgs; Index: kern/uipc_mbuf.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/kern/uipc_mbuf.c,v diff -u -p -r1.296 uipc_mbuf.c --- kern/uipc_mbuf.c 1 Jan 2025 13:44:22 -0000 1.296 +++ kern/uipc_mbuf.c 2 Jun 2025 18:27:49 -0000 @@ -129,6 +129,9 @@ struct mutex m_extref_mtx = MUTEX_INITIA void m_extfree(struct mbuf *); void m_zero(struct mbuf *); +/* keep nmbclust and mbuf_mem_limit in sync */ +struct mutex mbuf_nmbclust_mtx = MUTEX_INITIALIZER(IPL_NET); + unsigned long mbuf_mem_limit; /* [a] how much memory can be allocated */ unsigned long mbuf_mem_alloc; /* [a] how much memory has been allocated */ @@ -218,8 +221,10 @@ nmbclust_update(long newval) if (newval <= 0 || newval > LONG_MAX / MCLBYTES) return ERANGE; /* update the global mbuf memory limit */ - nmbclust = newval; - atomic_store_long(&mbuf_mem_limit, nmbclust * MCLBYTES); + mtx_enter(&mbuf_nmbclust_mtx); + atomic_store_long(&nmbclust, newval); + atomic_store_long(&mbuf_mem_limit, newval * MCLBYTES); + mtx_leave(&mbuf_nmbclust_mtx); pool_wakeup(&mbpool); for (i = 0; i < nitems(mclsizes); i++) Index: net/pf_ioctl.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf_ioctl.c,v diff -u -p -r1.421 pf_ioctl.c --- net/pf_ioctl.c 22 May 2025 06:34:03 -0000 1.421 +++ net/pf_ioctl.c 2 Jun 2025 18:27:49 -0000 @@ -2134,7 +2134,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a goto fail; } /* Fragments reference mbuf clusters. */ - if (pl->index == PF_LIMIT_FRAGS && pl->limit > nmbclust) { + if (pl->index == PF_LIMIT_FRAGS && pl->limit > + (long)atomic_load_long(&nmbclust)) { error = EINVAL; PF_UNLOCK(); goto fail;