On 12/09/17(Tue) 15:53, Martin Pieuchot wrote:
> 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?

Updated diff fixing two issues spotted by visa@.

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  13 Sep 2017 08:28:27 -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    13 Sep 2017 08:28:27 -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    13 Sep 2017 08:28:27 -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, &etherip_allow);
+               NET_LOCK();
+               error = sysctl_int(oldp, oldlenp, newp, newlen, &etherip_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,
                    &etheripstat, 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       13 Sep 2017 08:28:27 -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        13 Sep 2017 08:28:27 -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      13 Sep 2017 08:28:27 -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   13 Sep 2017 08:28:27 -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 13 Sep 2017 08:28:27 -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_ether.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_ether.c,v
retrieving revision 1.86
diff -u -p -r1.86 ip_ether.c
--- netinet/ip_ether.c  19 Jun 2017 17:58:49 -0000      1.86
+++ netinet/ip_ether.c  13 Sep 2017 08:29:36 -0000
@@ -468,19 +468,27 @@ int
 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,
-                   &etherip_allow));
+               NET_LOCK();
+               error = sysctl_int(oldp, oldlenp, newp, newlen,
+                   &etherip_allow);
+               NET_UNLOCK();
+               return (error);
        case ETHERIPCTL_STATS:
                if (newp != NULL)
                        return (EPERM);
-               return (sysctl_struct(oldp, oldlenp, newp, newlen,
-                   &etheripstat, sizeof(etheripstat)));
+               NET_LOCK();
+               error = sysctl_struct(oldp, oldlenp, newp, newlen,
+                   &etheripstat, sizeof(etheripstat));
+               NET_UNLOCK();
+               return (error);
        default:
                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    13 Sep 2017 08:28:27 -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   13 Sep 2017 08:28:27 -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  13 Sep 2017 08:28:27 -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   13 Sep 2017 08:28:27 -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       13 Sep 2017 08:28:27 -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        13 Sep 2017 08:28: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;
+                       }
                }
-               return (0);
+               NET_UNLOCK();
+               return (error);
 
        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        13 Sep 2017 08:28:27 -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    13 Sep 2017 08:28:27 -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       13 Sep 2017 08:28:27 -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        13 Sep 2017 08:28:27 -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 */

Reply via email to