From: Vitaliy Makkoveev Subject: tcp, sysctl: unlock TCPCTL_REASS_LIMIT and TCPCTL_SACKHOLE_LIMIT To: Alexander Bluhm , tech@openbsd.org Date: Sat, 10 May 2025 08:00:27 +0300 They are identical, so unlock them both. The temporary `tcp_sysctl_lock' and the pool_sethardlimit() serialization are useless because we are serialized with sysctl_lock rwlock(9). However I want to do this serialization for consistency reason. I will replace `tcp_sysctl_lock' with `sysctl_lock' after tcp_sysctl() unlocked. Index: sys/netinet/tcp_usrreq.c =================================================================== RCS file: /cvs/src/sys/netinet/tcp_usrreq.c,v retrieving revision 1.245 diff -u -p -r1.245 tcp_usrreq.c --- sys/netinet/tcp_usrreq.c 10 Mar 2025 15:11:46 -0000 1.245 +++ sys/netinet/tcp_usrreq.c 10 May 2025 04:54:26 -0000 @@ -1405,6 +1405,9 @@ tcp_sysctl_tcpstat(void *oldp, size_t *o &tcpstat, sizeof(tcpstat))); } +/* XXXSMP: temporary, until tcp_sysctl() unlocked */ +struct rwlock tcp_sysctl_lock = RWLOCK_INITIALIZER("tcpctllk"); + /* * Sysctl for tcp variables. */ @@ -1442,29 +1445,34 @@ tcp_sysctl(int *name, u_int namelen, voi return tcp_ident(oldp, oldlenp, newp, newlen, 1); case TCPCTL_REASS_LIMIT: - NET_LOCK(); - nval = tcp_reass_limit; - error = sysctl_int(oldp, oldlenp, newp, newlen, &nval); - if (!error && nval != tcp_reass_limit) { - error = pool_sethardlimit(&tcpqe_pool, nval, NULL, 0); - if (!error) - tcp_reass_limit = nval; + case TCPCTL_SACKHOLE_LIMIT: { + struct pool *pool; + int *var; + + if (name[0] == TCPCTL_REASS_LIMIT) { + pool = &tcpqe_pool; + var = &tcp_reass_limit; + } else { + pool = &sackhl_pool; + var = &tcp_sackhole_limit; } - NET_UNLOCK(); - return (error); - case TCPCTL_SACKHOLE_LIMIT: - NET_LOCK(); - nval = tcp_sackhole_limit; + oval = nval = atomic_load_int(var); error = sysctl_int(oldp, oldlenp, newp, newlen, &nval); - if (!error && nval != tcp_sackhole_limit) { - error = pool_sethardlimit(&sackhl_pool, nval, NULL, 0); - if (!error) - tcp_sackhole_limit = nval; + + if (error == 0 && oval != nval) { + rw_enter_write(&tcp_sysctl_lock); + if (nval != atomic_load_int(var)) { + error = pool_sethardlimit(pool, nval, + NULL, 0); + if (error == 0) + atomic_store_int(var, nval); + } + rw_exit_write(&tcp_sysctl_lock); } - NET_UNLOCK(); - return (error); + return (error); + } case TCPCTL_STATS: return (tcp_sysctl_tcpstat(oldp, oldlenp, newp));