Diff below reduces the scope of the NET_LOCK(), this time in sysctl
path. It is interesting for multiple reasons:
- It reduces the contention on the NET_LOCK(), which should improve
the overall latency on the system when counters are frequently
queried. Accesses to read-only operations and per-CPU counters
are no longer protected by the NET_LOCK().
- It allows per-CPU counters to be accessed in parallel. counters_read(9)
is now executed without holding the NET_LOCK().
- sysctl_mq() is now MP-safe, by serializing access using the mq's
mutex. However a dance is required to not hold a mutex around
copyin(9)/copyout(9).
- The NET_LOCK() is now taken around all sysctl_int(), sysctl_struct()
and sysctl_int_arr(). This is not nice but it will allow people to
fix parts of the sysctl path independently.
Note that all data structure currently protected in these sysctl paths
do not necessarily need the NET_LOCK(). Take CARP's carp_opts[] for
example. Does it need the NET_LOCK()? Is it at all the right primitive?
Well interested readers can answer with diffs and explanations to these
questions :)
Comments, oks?
Index: kern/uipc_domain.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_domain.c,v
retrieving revision 1.52
diff -u -p -r1.52 uipc_domain.c
--- kern/uipc_domain.c 11 Aug 2017 21:24:19 -0000 1.52
+++ kern/uipc_domain.c 12 Sep 2017 13:20:42 -0000
@@ -207,10 +207,8 @@ 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) {
- NET_LOCK();
error = (*pr->pr_sysctl)(name + 2, namelen - 2,
oldp, oldlenp, newp, newlen);
- NET_UNLOCK();
return (error);
}
return (ENOPROTOOPT);
Index: net/if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.512
diff -u -p -r1.512 if.c
--- net/if.c 22 Aug 2017 15:02:34 -0000 1.512
+++ net/if.c 12 Sep 2017 13:44:41 -0000
@@ -2666,10 +2666,14 @@ ifpromisc(struct ifnet *ifp, int pswitch
return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
}
+/* XXX move to kern/uipc_mbuf.c */
int
sysctl_mq(int *name, u_int namelen, void *oldp, size_t *oldlenp,
void *newp, size_t newlen, struct mbuf_queue *mq)
{
+ unsigned int maxlen;
+ int error;
+
/* All sysctl names at this level are terminal. */
if (namelen != 1)
return (ENOTDIR);
@@ -2678,8 +2682,14 @@ sysctl_mq(int *name, u_int namelen, void
case IFQCTL_LEN:
return (sysctl_rdint(oldp, oldlenp, newp, mq_len(mq)));
case IFQCTL_MAXLEN:
- return (sysctl_int(oldp, oldlenp, newp, newlen,
- &mq->mq_maxlen)); /* XXX directly accessing maxlen */
+ maxlen = mq->mq_maxlen;
+ error = sysctl_int(oldp, oldlenp, newp, newlen, &maxlen);
+ if (!error && maxlen != mq->mq_maxlen) {
+ mtx_enter(&mq->mq_mtx);
+ mq->mq_maxlen = maxlen;
+ mtx_leave(&mq->mq_mtx);
+ }
+ return (error);
case IFQCTL_DROPS:
return (sysctl_rdint(oldp, oldlenp, newp, mq_drops(mq)));
default:
Index: net/if_etherip.c
===================================================================
RCS file: /cvs/src/sys/net/if_etherip.c,v
retrieving revision 1.19
diff -u -p -r1.19 if_etherip.c
--- net/if_etherip.c 6 Jun 2017 11:51:13 -0000 1.19
+++ net/if_etherip.c 12 Sep 2017 12:38:46 -0000
@@ -662,18 +662,26 @@ int
ip_etherip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
void *newp, size_t newlen)
{
+ int error;
+
/* All sysctl names at this level are terminal. */
if (namelen != 1)
return ENOTDIR;
switch (name[0]) {
case ETHERIPCTL_ALLOW:
- return sysctl_int(oldp, oldlenp, newp, newlen, ðerip_allow);
+ NET_LOCK();
+ error = sysctl_int(oldp, oldlenp, newp, newlen, ðerip_allow);
+ NET_UNLOCK();
+ return (error);
case ETHERIPCTL_STATS:
if (newp != NULL)
return EPERM;
- return sysctl_struct(oldp, oldlenp, newp, newlen,
+ NET_LOCK();
+ error = sysctl_struct(oldp, oldlenp, newp, newlen,
ðeripstat, sizeof(etheripstat));
+ NET_UNLOCK();
+ return (error);
default:
break;
}
Index: net/pfkeyv2.c
===================================================================
RCS file: /cvs/src/sys/net/pfkeyv2.c,v
retrieving revision 1.166
diff -u -p -r1.166 pfkeyv2.c
--- net/pfkeyv2.c 8 Sep 2017 05:36:53 -0000 1.166
+++ net/pfkeyv2.c 12 Sep 2017 12:43:06 -0000
@@ -2386,8 +2386,6 @@ pfkeyv2_sysctl(int *name, u_int namelen,
int error = EINVAL;
u_int rdomain;
- NET_ASSERT_LOCKED();
-
if (new)
return (EPERM);
if (namelen < 1)
@@ -2403,7 +2401,9 @@ pfkeyv2_sysctl(int *name, u_int namelen,
case NET_KEY_SADB_DUMP:
if ((error = suser(curproc, 0)) != 0)
return (error);
+ NET_LOCK();
error = tdb_walk(rdomain, pfkeyv2_sysctl_walker, &w);
+ NET_UNLOCK();
if (oldp)
*oldlenp = w.w_where - oldp;
else
@@ -2411,8 +2411,10 @@ pfkeyv2_sysctl(int *name, u_int namelen,
break;
case NET_KEY_SPD_DUMP:
+ NET_LOCK();
error = pfkeyv2_ipo_walk(rdomain,
pfkeyv2_sysctl_policydumper, &w);
+ NET_UNLOCK();
if (oldp)
*oldlenp = w.w_where - oldp;
else
Index: net/rtsock.c
===================================================================
RCS file: /cvs/src/sys/net/rtsock.c,v
retrieving revision 1.250
diff -u -p -r1.250 rtsock.c
--- net/rtsock.c 5 Sep 2017 07:59:11 -0000 1.250
+++ net/rtsock.c 12 Sep 2017 13:15:47 -0000
@@ -1733,8 +1733,6 @@ sysctl_rtable(int *name, u_int namelen,
struct rt_tableinfo tableinfo;
u_int tableid = 0;
- NET_ASSERT_LOCKED();
-
if (new)
return (EPERM);
if (namelen < 3 || namelen > 4)
@@ -1757,6 +1755,7 @@ sysctl_rtable(int *name, u_int namelen,
switch (w.w_op) {
case NET_RT_DUMP:
case NET_RT_FLAGS:
+ NET_LOCK();
for (i = 1; i <= AF_MAX; i++) {
if (af != 0 && af != i)
continue;
@@ -1767,10 +1766,13 @@ sysctl_rtable(int *name, u_int namelen,
if (error)
break;
}
+ NET_UNLOCK();
break;
case NET_RT_IFLIST:
+ NET_LOCK();
error = sysctl_iflist(af, &w);
+ NET_UNLOCK();
break;
case NET_RT_STATS:
@@ -1786,7 +1788,9 @@ sysctl_rtable(int *name, u_int namelen,
&tableinfo, sizeof(tableinfo));
return (error);
case NET_RT_IFNAMES:
+ NET_LOCK();
error = sysctl_ifnames(&w);
+ NET_UNLOCK();
break;
}
free(w.w_tmem, M_RTABLE, 0);
Index: netinet/igmp.c
===================================================================
RCS file: /cvs/src/sys/netinet/igmp.c,v
retrieving revision 1.69
diff -u -p -r1.69 igmp.c
--- netinet/igmp.c 19 Jun 2017 17:58:49 -0000 1.69
+++ netinet/igmp.c 12 Sep 2017 12:50:23 -0000
@@ -680,6 +680,8 @@ int
igmp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
void *newp, size_t newlen)
{
+ int error;
+
/* All sysctl names at this level are terminal. */
if (namelen != 1)
return (ENOTDIR);
@@ -690,9 +692,13 @@ igmp_sysctl(int *name, u_int namelen, vo
return (EPERM);
return (igmp_sysctl_igmpstat(oldp, oldlenp, newp));
default:
- if (name[0] < IGMPCTL_MAXID)
- return (sysctl_int_arr(igmpctl_vars, name, namelen,
- oldp, oldlenp, newp, newlen));
+ if (name[0] < IGMPCTL_MAXID) {
+ NET_LOCK();
+ error = sysctl_int_arr(igmpctl_vars, name, namelen,
+ oldp, oldlenp, newp, newlen);
+ NET_UNLOCK();
+ return (error);
+ }
return (ENOPROTOOPT);
}
/* NOTREACHED */
Index: netinet/ip_carp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_carp.c,v
retrieving revision 1.315
diff -u -p -r1.315 ip_carp.c
--- netinet/ip_carp.c 11 Aug 2017 21:24:19 -0000 1.315
+++ netinet/ip_carp.c 12 Sep 2017 12:30:54 -0000
@@ -739,6 +739,8 @@ int
carp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
size_t newlen)
{
+ int error;
+
/* All sysctl names at this level are terminal. */
if (namelen != 1)
return (ENOTDIR);
@@ -749,8 +751,11 @@ carp_sysctl(int *name, u_int namelen, vo
default:
if (name[0] <= 0 || name[0] >= CARPCTL_MAXID)
return (ENOPROTOOPT);
- return sysctl_int(oldp, oldlenp, newp, newlen,
+ NET_LOCK();
+ error = sysctl_int(oldp, oldlenp, newp, newlen,
&carp_opts[name[0]]);
+ NET_UNLOCK();
+ return (error);
}
}
Index: netinet/ip_divert.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_divert.c,v
retrieving revision 1.52
diff -u -p -r1.52 ip_divert.c
--- netinet/ip_divert.c 6 Sep 2017 11:43:04 -0000 1.52
+++ netinet/ip_divert.c 12 Sep 2017 12:34:40 -0000
@@ -367,23 +367,35 @@ int
divert_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void
*newp,
size_t newlen)
{
+ int error;
+
/* All sysctl names at this level are terminal. */
if (namelen != 1)
return (ENOTDIR);
switch (name[0]) {
case DIVERTCTL_SENDSPACE:
- return (sysctl_int(oldp, oldlenp, newp, newlen,
- &divert_sendspace));
+ NET_LOCK();
+ error = sysctl_int(oldp, oldlenp, newp, newlen,
+ &divert_sendspace);
+ NET_UNLOCK();
+ return (error);
case DIVERTCTL_RECVSPACE:
- return (sysctl_int(oldp, oldlenp, newp, newlen,
- &divert_recvspace));
+ NET_LOCK();
+ error = sysctl_int(oldp, oldlenp, newp, newlen,
+ &divert_recvspace);
+ NET_UNLOCK();
+ return (error);
case DIVERTCTL_STATS:
return (divert_sysctl_divstat(oldp, oldlenp, newp));
default:
- if (name[0] < DIVERTCTL_MAXID)
- return sysctl_int_arr(divertctl_vars, name, namelen,
+ if (name[0] < DIVERTCTL_MAXID) {
+ NET_LOCK();
+ error = sysctl_int_arr(divertctl_vars, name, namelen,
oldp, oldlenp, newp, newlen);
+ NET_UNLOCK();
+ return (error);
+ }
return (ENOPROTOOPT);
}
Index: netinet/ip_gre.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_gre.c,v
retrieving revision 1.66
diff -u -p -r1.66 ip_gre.c
--- netinet/ip_gre.c 15 Aug 2017 17:47:15 -0000 1.66
+++ netinet/ip_gre.c 12 Sep 2017 13:19:01 -0000
@@ -373,15 +373,23 @@ int
gre_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
size_t newlen)
{
+ int error;
+
/* All sysctl names at this level are terminal. */
if (namelen != 1)
return (ENOTDIR);
switch (name[0]) {
case GRECTL_ALLOW:
- return (sysctl_int(oldp, oldlenp, newp, newlen, &gre_allow));
+ NET_LOCK();
+ error = sysctl_int(oldp, oldlenp, newp, newlen, &gre_allow);
+ NET_UNLOCK();
+ return (error);
case GRECTL_WCCP:
- return (sysctl_int(oldp, oldlenp, newp, newlen, &gre_wccp));
+ NET_LOCK();
+ error = sysctl_int(oldp, oldlenp, newp, newlen, &gre_wccp);
+ NET_UNLOCK();
+ return (error);
default:
return (ENOPROTOOPT);
}
@@ -392,14 +400,19 @@ int
ipmobile_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
void *newp, size_t newlen)
{
+ int error;
+
/* All sysctl names at this level are terminal. */
if (namelen != 1)
return (ENOTDIR);
switch (name[0]) {
case MOBILEIPCTL_ALLOW:
- return (sysctl_int(oldp, oldlenp, newp, newlen,
- &ip_mobile_allow));
+ NET_LOCK();
+ error = sysctl_int(oldp, oldlenp, newp, newlen,
+ &ip_mobile_allow);
+ NET_UNLOCK();
+ return (error);
default:
return (ENOPROTOOPT);
}
Index: netinet/ip_icmp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_icmp.c,v
retrieving revision 1.171
diff -u -p -r1.171 ip_icmp.c
--- netinet/ip_icmp.c 10 Aug 2017 02:26:26 -0000 1.171
+++ netinet/ip_icmp.c 12 Sep 2017 12:51:36 -0000
@@ -881,8 +881,6 @@ icmp_sysctl(int *name, u_int namelen, vo
{
int error;
- NET_ASSERT_LOCKED();
-
/* All sysctl names at this level are terminal. */
if (namelen != 1)
return (ENOTDIR);
@@ -890,6 +888,7 @@ icmp_sysctl(int *name, u_int namelen, vo
switch (name[0]) {
case ICMPCTL_REDIRTIMEOUT:
+ NET_LOCK();
error = sysctl_int(oldp, oldlenp, newp, newlen,
&icmp_redirtimeout);
if (icmp_redirect_timeout_q != NULL) {
@@ -903,6 +902,7 @@ icmp_sysctl(int *name, u_int namelen, vo
icmp_redirect_timeout_q =
rt_timer_queue_create(icmp_redirtimeout);
}
+ NET_UNLOCK();
break;
case ICMPCTL_STATS:
@@ -911,8 +911,10 @@ icmp_sysctl(int *name, u_int namelen, vo
default:
if (name[0] < ICMPCTL_MAXID) {
+ NET_LOCK();
error = sysctl_int_arr(icmpctl_vars, name, namelen,
oldp, oldlenp, newp, newlen);
+ NET_UNLOCK();
break;
}
error = ENOPROTOOPT;
Index: netinet/ip_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.322
diff -u -p -r1.322 ip_input.c
--- netinet/ip_input.c 7 Sep 2017 10:54:49 -0000 1.322
+++ netinet/ip_input.c 12 Sep 2017 13:11:51 -0000
@@ -1617,26 +1617,24 @@ ip_sysctl(int *name, u_int namelen, void
extern struct mrtstat mrtstat;
#endif
- NET_ASSERT_LOCKED();
-
/* Almost all sysctl names at this level are terminal. */
if (namelen != 1 && name[0] != IPCTL_IFQUEUE)
return (ENOTDIR);
switch (name[0]) {
-#ifdef notyet
- case IPCTL_DEFMTU:
- return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtu));
-#endif
case IPCTL_SOURCEROUTE:
/*
* Don't allow this to change in a secure environment.
*/
if (newp && securelevel > 0)
return (EPERM);
- return (sysctl_int(oldp, oldlenp, newp, newlen,
- &ip_dosourceroute));
+ NET_LOCK();
+ error = sysctl_int(oldp, oldlenp, newp, newlen,
+ &ip_dosourceroute);
+ NET_UNLOCK();
+ return (error);
case IPCTL_MTUDISC:
+ NET_LOCK();
error = sysctl_int(oldp, oldlenp, newp, newlen,
&ip_mtudisc);
if (ip_mtudisc != 0 && ip_mtudisc_timeout_q == NULL) {
@@ -1646,25 +1644,37 @@ ip_sysctl(int *name, u_int namelen, void
rt_timer_queue_destroy(ip_mtudisc_timeout_q);
ip_mtudisc_timeout_q = NULL;
}
+ NET_UNLOCK();
return error;
case IPCTL_MTUDISCTIMEOUT:
+ NET_LOCK();
error = sysctl_int(oldp, oldlenp, newp, newlen,
&ip_mtudisc_timeout);
if (ip_mtudisc_timeout_q != NULL)
rt_timer_queue_change(ip_mtudisc_timeout_q,
ip_mtudisc_timeout);
+ NET_UNLOCK();
return (error);
case IPCTL_IPSEC_ENC_ALGORITHM:
- return (sysctl_tstring(oldp, oldlenp, newp, newlen,
- ipsec_def_enc, sizeof(ipsec_def_enc)));
+ NET_LOCK();
+ error = sysctl_tstring(oldp, oldlenp, newp, newlen,
+ ipsec_def_enc, sizeof(ipsec_def_enc));
+ NET_UNLOCK();
+ return (error);
case IPCTL_IPSEC_AUTH_ALGORITHM:
- return (sysctl_tstring(oldp, oldlenp, newp, newlen,
+ NET_LOCK();
+ error = sysctl_tstring(oldp, oldlenp, newp, newlen,
ipsec_def_auth,
- sizeof(ipsec_def_auth)));
+ sizeof(ipsec_def_auth));
+ NET_UNLOCK();
+ return (error);
case IPCTL_IPSEC_IPCOMP_ALGORITHM:
- return (sysctl_tstring(oldp, oldlenp, newp, newlen,
+ NET_LOCK();
+ error = sysctl_tstring(oldp, oldlenp, newp, newlen,
ipsec_def_comp,
- sizeof(ipsec_def_comp)));
+ sizeof(ipsec_def_comp));
+ NET_UNLOCK();
+ return (error);
case IPCTL_IFQUEUE:
return (sysctl_niq(name + 1, namelen - 1,
oldp, oldlenp, newp, newlen, &ipintrq));
@@ -1679,11 +1689,17 @@ ip_sysctl(int *name, u_int namelen, void
case IPCTL_MRTMFC:
if (newp)
return (EPERM);
- return mrt_sysctl_mfc(oldp, oldlenp);
+ NET_LOCK();
+ error = mrt_sysctl_mfc(oldp, oldlenp);
+ NET_UNLOCK();
+ return (error);
case IPCTL_MRTVIF:
if (newp)
return (EPERM);
- return mrt_sysctl_vif(oldp, oldlenp);
+ NET_LOCK();
+ error = mrt_sysctl_vif(oldp, oldlenp);
+ NET_UNLOCK();
+ return (error);
#else
case IPCTL_MRTPROTO:
case IPCTL_MRTSTATS:
@@ -1692,9 +1708,13 @@ ip_sysctl(int *name, u_int namelen, void
return (EOPNOTSUPP);
#endif
default:
- if (name[0] < IPCTL_MAXID)
- return (sysctl_int_arr(ipctl_vars, name, namelen,
- oldp, oldlenp, newp, newlen));
+ if (name[0] < IPCTL_MAXID) {
+ NET_LOCK();
+ error = sysctl_int_arr(ipctl_vars, name, namelen,
+ oldp, oldlenp, newp, newlen);
+ NET_UNLOCK();
+ return (error);
+ }
return (EOPNOTSUPP);
}
/* NOTREACHED */
Index: netinet/ip_ipip.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_ipip.c,v
retrieving revision 1.86
diff -u -p -r1.86 ip_ipip.c
--- netinet/ip_ipip.c 5 Jul 2017 11:34:10 -0000 1.86
+++ netinet/ip_ipip.c 12 Sep 2017 12:49:38 -0000
@@ -592,13 +592,18 @@ int
ipip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
size_t newlen)
{
+ int error;
+
/* All sysctl names at this level are terminal. */
if (namelen != 1)
return (ENOTDIR);
switch (name[0]) {
case IPIPCTL_ALLOW:
- return (sysctl_int(oldp, oldlenp, newp, newlen, &ipip_allow));
+ NET_LOCK();
+ error = sysctl_int(oldp, oldlenp, newp, newlen, &ipip_allow);
+ NET_UNLOCK();
+ return (error);
case IPIPCTL_STATS:
return (ipip_sysctl_ipipstat(oldp, oldlenp, newp));
default:
Index: netinet/ipsec_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ipsec_input.c,v
retrieving revision 1.156
diff -u -p -r1.156 ipsec_input.c
--- netinet/ipsec_input.c 5 Jul 2017 11:34:10 -0000 1.156
+++ netinet/ipsec_input.c 12 Sep 2017 12:37:20 -0000
@@ -615,6 +615,8 @@ int
esp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
size_t newlen)
{
+ int error;
+
/* All sysctl names at this level are terminal. */
if (namelen != 1)
return (ENOTDIR);
@@ -623,12 +625,19 @@ esp_sysctl(int *name, u_int namelen, voi
case ESPCTL_STATS:
if (newp != NULL)
return (EPERM);
- return (sysctl_struct(oldp, oldlenp, newp, newlen,
- &espstat, sizeof(espstat)));
+ NET_LOCK();
+ error = sysctl_struct(oldp, oldlenp, newp, newlen,
+ &espstat, sizeof(espstat));
+ NET_UNLOCK();
+ return (error);
default:
- if (name[0] < ESPCTL_MAXID)
- return (sysctl_int_arr(espctl_vars, name, namelen,
- oldp, oldlenp, newp, newlen));
+ if (name[0] < ESPCTL_MAXID) {
+ NET_LOCK();
+ error = sysctl_int_arr(espctl_vars, name, namelen,
+ oldp, oldlenp, newp, newlen);
+ NET_UNLOCK();
+ return (error);
+ }
return (ENOPROTOOPT);
}
}
@@ -637,6 +646,8 @@ int
ah_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
size_t newlen)
{
+ int error;
+
/* All sysctl names at this level are terminal. */
if (namelen != 1)
return (ENOTDIR);
@@ -645,12 +656,19 @@ ah_sysctl(int *name, u_int namelen, void
case AHCTL_STATS:
if (newp != NULL)
return (EPERM);
- return (sysctl_struct(oldp, oldlenp, newp, newlen,
- &ahstat, sizeof(ahstat)));
+ NET_LOCK();
+ error = sysctl_struct(oldp, oldlenp, newp, newlen,
+ &ahstat, sizeof(ahstat));
+ NET_UNLOCK();
+ return (error);
default:
- if (name[0] < AHCTL_MAXID)
- return (sysctl_int_arr(ahctl_vars, name, namelen,
- oldp, oldlenp, newp, newlen));
+ if (name[0] < AHCTL_MAXID) {
+ NET_LOCK();
+ error = sysctl_int_arr(ahctl_vars, name, namelen,
+ oldp, oldlenp, newp, newlen);
+ NET_UNLOCK();
+ return (error);
+ }
return (ENOPROTOOPT);
}
}
@@ -659,6 +677,8 @@ int
ipcomp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void
*newp,
size_t newlen)
{
+ int error;
+
/* All sysctl names at this level are terminal. */
if (namelen != 1)
return (ENOTDIR);
@@ -667,12 +687,19 @@ ipcomp_sysctl(int *name, u_int namelen,
case IPCOMPCTL_STATS:
if (newp != NULL)
return (EPERM);
- return (sysctl_struct(oldp, oldlenp, newp, newlen,
- &ipcompstat, sizeof(ipcompstat)));
+ NET_LOCK();
+ error = sysctl_struct(oldp, oldlenp, newp, newlen,
+ &ipcompstat, sizeof(ipcompstat));
+ NET_UNLOCK();
+ return (error);
default:
- if (name[0] < IPCOMPCTL_MAXID)
- return (sysctl_int_arr(ipcompctl_vars, name, namelen,
- oldp, oldlenp, newp, newlen));
+ if (name[0] < IPCOMPCTL_MAXID) {
+ NET_LOCK();
+ error = sysctl_int_arr(ipcompctl_vars, name, namelen,
+ oldp, oldlenp, newp, newlen);
+ NET_UNLOCK();
+ return (error);
+ }
return (ENOPROTOOPT);
}
}
Index: netinet/tcp_usrreq.c
===================================================================
RCS file: /cvs/src/sys/netinet/tcp_usrreq.c,v
retrieving revision 1.155
diff -u -p -r1.155 tcp_usrreq.c
--- netinet/tcp_usrreq.c 5 Sep 2017 07:59:11 -0000 1.155
+++ netinet/tcp_usrreq.c 12 Sep 2017 13:01:27 -0000
@@ -955,8 +955,6 @@ tcp_sysctl(int *name, u_int namelen, voi
{
int error, nval;
- NET_ASSERT_LOCKED();
-
/* All sysctl names at this level are terminal. */
if (namelen != 1)
return (ENOTDIR);
@@ -964,73 +962,91 @@ tcp_sysctl(int *name, u_int namelen, voi
switch (name[0]) {
#ifdef TCP_SACK
case TCPCTL_SACK:
- return (sysctl_int(oldp, oldlenp, newp, newlen,
- &tcp_do_sack));
+ NET_LOCK();
+ error = sysctl_int(oldp, oldlenp, newp, newlen,
+ &tcp_do_sack);
+ NET_UNLOCK();
+ return (error);
#endif
case TCPCTL_SLOWHZ:
return (sysctl_rdint(oldp, oldlenp, newp, PR_SLOWHZ));
case TCPCTL_BADDYNAMIC:
- return (sysctl_struct(oldp, oldlenp, newp, newlen,
- baddynamicports.tcp, sizeof(baddynamicports.tcp)));
+ NET_LOCK();
+ error = sysctl_struct(oldp, oldlenp, newp, newlen,
+ baddynamicports.tcp, sizeof(baddynamicports.tcp));
+ NET_UNLOCK();
+ return (error);
case TCPCTL_ROOTONLY:
if (newp && securelevel > 0)
return (EPERM);
- return (sysctl_struct(oldp, oldlenp, newp, newlen,
- rootonlyports.tcp, sizeof(rootonlyports.tcp)));
+ NET_LOCK();
+ error = sysctl_struct(oldp, oldlenp, newp, newlen,
+ rootonlyports.tcp, sizeof(rootonlyports.tcp));
+ NET_UNLOCK();
+ return (error);
case TCPCTL_IDENT:
- return (tcp_ident(oldp, oldlenp, newp, newlen, 0));
+ NET_LOCK();
+ error = tcp_ident(oldp, oldlenp, newp, newlen, 0);
+ NET_UNLOCK();
+ return (error);
case TCPCTL_DROP:
- return (tcp_ident(oldp, oldlenp, newp, newlen, 1));
+ NET_LOCK();
+ error = tcp_ident(oldp, oldlenp, newp, newlen, 1);
+ NET_UNLOCK();
+ return (error);
case TCPCTL_ALWAYS_KEEPALIVE:
- return (sysctl_int(oldp, oldlenp, newp, newlen,
- &tcp_always_keepalive));
+ NET_LOCK();
+ error = sysctl_int(oldp, oldlenp, newp, newlen,
+ &tcp_always_keepalive);
+ NET_UNLOCK();
+ return (error);
#ifdef TCP_ECN
case TCPCTL_ECN:
- return (sysctl_int(oldp, oldlenp, newp, newlen,
- &tcp_do_ecn));
+ NET_LOCK();
+ error = sysctl_int(oldp, oldlenp, newp, newlen,
+ &tcp_do_ecn);
+ NET_UNLOCK();
+ return (error);
#endif
case TCPCTL_REASS_LIMIT:
+ NET_LOCK();
nval = tcp_reass_limit;
error = sysctl_int(oldp, oldlenp, newp, newlen, &nval);
- if (error)
- return (error);
- if (nval != tcp_reass_limit) {
+ if (!error && nval != tcp_reass_limit) {
error = pool_sethardlimit(&tcpqe_pool, nval, NULL, 0);
- if (error)
- return (error);
- tcp_reass_limit = nval;
+ if (!error)
+ tcp_reass_limit = nval;
}
- return (0);
+ NET_UNLOCK();
+ return (error);
#ifdef TCP_SACK
case TCPCTL_SACKHOLE_LIMIT:
+ NET_LOCK();
nval = tcp_sackhole_limit;
error = sysctl_int(oldp, oldlenp, newp, newlen, &nval);
- if (error)
- return (error);
- if (nval != tcp_sackhole_limit) {
+ if (!error && nval != tcp_sackhole_limit) {
error = pool_sethardlimit(&sackhl_pool, nval, NULL, 0);
- if (error)
- return (error);
- tcp_sackhole_limit = nval;
+ if (!error)
+ tcp_sackhole_limit = nval;
}
- return (0);
+ NET_UNLOCK();
+ return (error);
#endif
case TCPCTL_STATS:
return (tcp_sysctl_tcpstat(oldp, oldlenp, newp));
case TCPCTL_SYN_USE_LIMIT:
+ NET_LOCK();
error = sysctl_int(oldp, oldlenp, newp, newlen,
&tcp_syn_use_limit);
- if (error)
- return (error);
- if (newp != NULL) {
+ if (!error && newp != NULL) {
/*
* Global tcp_syn_use_limit is used when reseeding a
* new cache. Also update the value in active cache.
@@ -1040,33 +1056,40 @@ tcp_sysctl(int *name, u_int namelen, voi
if (tcp_syn_cache[1].scs_use > tcp_syn_use_limit)
tcp_syn_cache[1].scs_use = tcp_syn_use_limit;
}
- return (0);
+ NET_UNLOCK();
+ return (error);
case TCPCTL_SYN_HASH_SIZE:
+ NET_LOCK();
nval = tcp_syn_hash_size;
error = sysctl_int(oldp, oldlenp, newp, newlen, &nval);
- if (error)
- return (error);
- if (nval != tcp_syn_hash_size) {
- if (nval < 1 || nval > 100000)
- return (EINVAL);
- /*
- * If global hash size has been changed, switch sets as
- * soon as possible. Then the actual hash array will
- * be reallocated.
- */
- if (tcp_syn_cache[0].scs_size != nval)
- tcp_syn_cache[0].scs_use = 0;
- if (tcp_syn_cache[1].scs_size != nval)
- tcp_syn_cache[1].scs_use = 0;
- tcp_syn_hash_size = nval;
+ if (!error && nval != tcp_syn_hash_size) {
+ if (nval < 1 || nval > 100000) {
+ error = EINVAL;
+ } else {
+ /*
+ * If global hash size has been changed,
+ * switch sets as soon as possible. Then
+ * the actual hash array will be reallocated.
+ */
+ if (tcp_syn_cache[0].scs_size != nval)
+ tcp_syn_cache[0].scs_use = 0;
+ if (tcp_syn_cache[1].scs_size != nval)
+ tcp_syn_cache[1].scs_use = 0;
+ tcp_syn_hash_size = nval;
+ }
}
+ NET_UNLOCK();
return (0);
default:
- if (name[0] < TCPCTL_MAXID)
- return (sysctl_int_arr(tcpctl_vars, name, namelen,
- oldp, oldlenp, newp, newlen));
+ if (name[0] < TCPCTL_MAXID) {
+ NET_LOCK();
+ error = sysctl_int_arr(tcpctl_vars, name, namelen,
+ oldp, oldlenp, newp, newlen);
+ NET_UNLOCK();
+ return (error);
+ }
return (ENOPROTOOPT);
}
/* NOTREACHED */
Index: netinet/udp_usrreq.c
===================================================================
RCS file: /cvs/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.240
diff -u -p -r1.240 udp_usrreq.c
--- netinet/udp_usrreq.c 5 Sep 2017 07:59:11 -0000 1.240
+++ netinet/udp_usrreq.c 12 Sep 2017 12:53:41 -0000
@@ -1277,20 +1277,28 @@ int
udp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
size_t newlen)
{
+ int error;
+
/* All sysctl names at this level are terminal. */
if (namelen != 1)
return (ENOTDIR);
switch (name[0]) {
case UDPCTL_BADDYNAMIC:
- return (sysctl_struct(oldp, oldlenp, newp, newlen,
- baddynamicports.udp, sizeof(baddynamicports.udp)));
+ NET_LOCK();
+ error = sysctl_struct(oldp, oldlenp, newp, newlen,
+ baddynamicports.udp, sizeof(baddynamicports.udp));
+ NET_UNLOCK();
+ return (error);
case UDPCTL_ROOTONLY:
if (newp && securelevel > 0)
return (EPERM);
- return (sysctl_struct(oldp, oldlenp, newp, newlen,
- rootonlyports.udp, sizeof(rootonlyports.udp)));
+ NET_LOCK();
+ error = sysctl_struct(oldp, oldlenp, newp, newlen,
+ rootonlyports.udp, sizeof(rootonlyports.udp));
+ NET_UNLOCK();
+ return (error);
case UDPCTL_STATS:
if (newp != NULL)
@@ -1299,9 +1307,13 @@ udp_sysctl(int *name, u_int namelen, voi
return (udp_sysctl_udpstat(oldp, oldlenp, newp));
default:
- if (name[0] < UDPCTL_MAXID)
- return (sysctl_int_arr(udpctl_vars, name, namelen,
- oldp, oldlenp, newp, newlen));
+ if (name[0] < UDPCTL_MAXID) {
+ NET_LOCK();
+ error = sysctl_int_arr(udpctl_vars, name, namelen,
+ oldp, oldlenp, newp, newlen);
+ NET_UNLOCK();
+ return (error);
+ }
return (ENOPROTOOPT);
}
/* NOTREACHED */
Index: netinet6/icmp6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/icmp6.c,v
retrieving revision 1.216
diff -u -p -r1.216 icmp6.c
--- netinet6/icmp6.c 1 Sep 2017 15:05:31 -0000 1.216
+++ netinet6/icmp6.c 12 Sep 2017 12:52:09 -0000
@@ -1887,6 +1887,8 @@ int
icmp6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
void *newp, size_t newlen)
{
+ int error;
+
/* All sysctl names at this level are terminal. */
if (namelen != 1)
return ENOTDIR;
@@ -1896,9 +1898,13 @@ icmp6_sysctl(int *name, u_int namelen, v
case ICMPV6CTL_STATS:
return icmp6_sysctl_icmp6stat(oldp, oldlenp, newp);
default:
- if (name[0] < ICMPV6CTL_MAXID)
- return (sysctl_int_arr(icmpv6ctl_vars, name, namelen,
- oldp, oldlenp, newp, newlen));
+ if (name[0] < ICMPV6CTL_MAXID) {
+ NET_LOCK();
+ error = sysctl_int_arr(icmpv6ctl_vars, name, namelen,
+ oldp, oldlenp, newp, newlen);
+ NET_UNLOCK();
+ return (error);
+ }
return ENOPROTOOPT;
}
/* NOTREACHED */
Index: netinet6/ip6_divert.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_divert.c,v
retrieving revision 1.51
diff -u -p -r1.51 ip6_divert.c
--- netinet6/ip6_divert.c 6 Sep 2017 11:43:04 -0000 1.51
+++ netinet6/ip6_divert.c 12 Sep 2017 12:35:00 -0000
@@ -370,23 +370,35 @@ int
divert6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
void *newp, size_t newlen)
{
+ int error;
+
/* All sysctl names at this level are terminal. */
if (namelen != 1)
return (ENOTDIR);
switch (name[0]) {
case DIVERT6CTL_SENDSPACE:
- return (sysctl_int(oldp, oldlenp, newp, newlen,
- &divert6_sendspace));
+ NET_LOCK();
+ error = sysctl_int(oldp, oldlenp, newp, newlen,
+ &divert6_sendspace);
+ NET_UNLOCK();
+ return (error);
case DIVERT6CTL_RECVSPACE:
- return (sysctl_int(oldp, oldlenp, newp, newlen,
- &divert6_recvspace));
+ NET_LOCK();
+ error = sysctl_int(oldp, oldlenp, newp, newlen,
+ &divert6_recvspace);
+ NET_UNLOCK();
+ return (error);
case DIVERT6CTL_STATS:
return (divert6_sysctl_div6stat(oldp, oldlenp, newp));
default:
- if (name[0] < DIVERT6CTL_MAXID)
- return sysctl_int_arr(divert6ctl_vars, name, namelen,
+ if (name[0] < DIVERT6CTL_MAXID) {
+ NET_LOCK();
+ error = sysctl_int_arr(divert6ctl_vars, name, namelen,
oldp, oldlenp, newp, newlen);
+ NET_UNLOCK();
+ return (error);
+ }
return (ENOPROTOOPT);
}
Index: netinet6/ip6_input.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.202
diff -u -p -r1.202 ip6_input.c
--- netinet6/ip6_input.c 22 Aug 2017 15:02:34 -0000 1.202
+++ netinet6/ip6_input.c 12 Sep 2017 13:13:51 -0000
@@ -1383,8 +1383,6 @@ ip6_sysctl(int *name, u_int namelen, voi
#endif
int error;
- NET_ASSERT_LOCKED();
-
/* Almost all sysctl names at this level are terminal. */
if (namelen != 1 && name[0] != IPV6CTL_IFQUEUE)
return (ENOTDIR);
@@ -1398,18 +1396,27 @@ ip6_sysctl(int *name, u_int namelen, voi
case IPV6CTL_MRTSTATS:
if (newp != NULL)
return (EPERM);
- return (sysctl_struct(oldp, oldlenp, newp, newlen,
- &mrt6stat, sizeof(mrt6stat)));
+ NET_LOCK();
+ error = sysctl_struct(oldp, oldlenp, newp, newlen,
+ &mrt6stat, sizeof(mrt6stat));
+ NET_UNLOCK();
+ return (error);
case IPV6CTL_MRTPROTO:
return sysctl_rdint(oldp, oldlenp, newp, ip6_mrtproto);
case IPV6CTL_MRTMIF:
if (newp)
return (EPERM);
- return mrt6_sysctl_mif(oldp, oldlenp);
+ NET_LOCK();
+ error = mrt6_sysctl_mif(oldp, oldlenp);
+ NET_UNLOCK();
+ return (error);
case IPV6CTL_MRTMFC:
if (newp)
return (EPERM);
- return mrt6_sysctl_mfc(oldp, oldlenp);
+ NET_LOCK();
+ error = mrt6_sysctl_mfc(oldp, oldlenp);
+ NET_UNLOCK();
+ return (error);
#else
case IPV6CTL_MRTSTATS:
case IPV6CTL_MRTPROTO:
@@ -1418,19 +1425,25 @@ ip6_sysctl(int *name, u_int namelen, voi
return (EOPNOTSUPP);
#endif
case IPV6CTL_MTUDISCTIMEOUT:
+ NET_LOCK();
error = sysctl_int(oldp, oldlenp, newp, newlen,
&ip6_mtudisc_timeout);
if (icmp6_mtudisc_timeout_q != NULL)
rt_timer_queue_change(icmp6_mtudisc_timeout_q,
ip6_mtudisc_timeout);
+ NET_UNLOCK();
return (error);
case IPV6CTL_IFQUEUE:
return (sysctl_niq(name + 1, namelen - 1,
oldp, oldlenp, newp, newlen, &ip6intrq));
default:
- if (name[0] < IPV6CTL_MAXID)
- return (sysctl_int_arr(ipv6ctl_vars, name, namelen,
- oldp, oldlenp, newp, newlen));
+ if (name[0] < IPV6CTL_MAXID) {
+ NET_LOCK();
+ error = sysctl_int_arr(ipv6ctl_vars, name, namelen,
+ oldp, oldlenp, newp, newlen);
+ NET_UNLOCK();
+ return (error);
+ }
return (EOPNOTSUPP);
}
/* NOTREACHED */