Let's start to unlock (*pr_sysctl)() handlers. We have many of them, so
introduce temporary PR_MPSAFE flag to mark MP safe instead of pushing
kernel lock within handlers.
Unlock ip_sysctl(). Still take kernel lock within IPCTL_MRTSTATS case.
It looks like `mrtstat' protection is inconsistent, so keep locking as
it was. Since `mrtstat' are counters, it make sense to rework them into
per CPU counters with separate diffs.
mrt_sysctl_mfc() and mrt_sysctl_vif() do read-only access so, netlock
could be replaced by shared netlock and pushed within, but also with
separate diffs.
ok?
This is not related to (*pr_sysctl)() unlocking, but if there is no
objections, I want to replace tabs by space after #define in PR_* flags
definitions.
Index: sys/kern/uipc_domain.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_domain.c,v
retrieving revision 1.61
diff -u -p -r1.61 uipc_domain.c
--- sys/kern/uipc_domain.c 4 May 2023 09:40:36 -0000 1.61
+++ sys/kern/uipc_domain.c 16 May 2023 10:50:53 -0000
@@ -244,10 +244,12 @@ net_sysctl(int *name, u_int namelen, voi
protocol = name[1];
for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
if (pr->pr_protocol == protocol && pr->pr_sysctl) {
- KERNEL_LOCK();
+ if ((pr->pr_flags & PR_MPSAFE) == 0)
+ KERNEL_LOCK();
error = (*pr->pr_sysctl)(name + 2, namelen - 2,
oldp, oldlenp, newp, newlen);
- KERNEL_UNLOCK();
+ if ((pr->pr_flags & PR_MPSAFE) == 0)
+ KERNEL_UNLOCK();
return (error);
}
return (ENOPROTOOPT);
Index: sys/netinet/in_proto.c
===================================================================
RCS file: /cvs/src/sys/netinet/in_proto.c,v
retrieving revision 1.99
diff -u -p -r1.99 in_proto.c
--- sys/netinet/in_proto.c 15 Aug 2022 09:11:38 -0000 1.99
+++ sys/netinet/in_proto.c 16 May 2023 10:50:53 -0000
@@ -177,6 +177,7 @@ u_char ip_protox[IPPROTO_MAX];
const struct protosw inetsw[] = {
{
.pr_domain = &inetdomain,
+ .pr_flags = PR_MPSAFE,
.pr_init = ip_init,
.pr_slowtimo = ip_slowtimo,
.pr_sysctl = ip_sysctl
Index: sys/netinet/ip_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.383
diff -u -p -r1.383 ip_input.c
--- sys/netinet/ip_input.c 5 Apr 2023 21:51:47 -0000 1.383
+++ sys/netinet/ip_input.c 16 May 2023 10:50:53 -0000
@@ -1704,8 +1704,11 @@ ip_sysctl(int *name, u_int namelen, void
return (ip_sysctl_ipstat(oldp, oldlenp, newp));
#ifdef MROUTING
case IPCTL_MRTSTATS:
- return (sysctl_rdstruct(oldp, oldlenp, newp,
- &mrtstat, sizeof(mrtstat)));
+ KERNEL_LOCK();
+ error = sysctl_rdstruct(oldp, oldlenp, newp,
+ &mrtstat, sizeof(mrtstat));
+ KERNEL_UNLOCK();
+ return (error);
case IPCTL_MRTMFC:
if (newp)
return (EPERM);
Index: sys/sys/protosw.h
===================================================================
RCS file: /cvs/src/sys/sys/protosw.h,v
retrieving revision 1.59
diff -u -p -r1.59 protosw.h
--- sys/sys/protosw.h 26 Nov 2022 17:52:35 -0000 1.59
+++ sys/sys/protosw.h 16 May 2023 10:50:53 -0000
@@ -131,6 +131,8 @@ struct protosw {
#define PR_ABRTACPTDIS 0x20 /* abort on accept(2) to
disconnected
socket */
#define PR_SPLICE 0x40 /* socket splicing is possible
*/
+#define PR_MPSAFE 0x80 /* (*pr_sysctl)() doesn't
require
+ kernel lock */
/*
* The arguments to usrreq are: