On Wed, Sep 13 2017, Martin Pieuchot <[email protected]> wrote:
> 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?
Looks good to me, ok jca@
> 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, ð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 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,
> - ð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,
> - ðeripstat, sizeof(etheripstat)));
> + NET_LOCK();
> + error = sysctl_struct(oldp, oldlenp, newp, newlen,
> + ðeripstat, 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 */
>
--
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF DDCC 0DFA 74AE 1524 E7EE