On Wed, Jan 25, 2017 at 11:14:57AM -0500, David Hill wrote:
> On Wed, Jan 25, 2017 at 04:32:25PM +1000, Martin Pieuchot wrote:
> > I just enabled the NET_LOCK() again and I'm looking for test reports.
> > Please go build a kernel from sources or wait for the next snapshot,
> > run it and report back.
> > 
> > If you're looking for some small coding tasks related to the NET_LOCK()
> > just do:
> > 
> >     # sysctl kern.splassert=2
> >     # sysctl kern.pool_debug=2
> >     
> > Then watch for the traces on your console.
> > 
> > You'll see something like:
> > 
> >     Starting stack trace...
> >     yield(0,1,d09dac52,f5549dbc,d94e9378) at yield+0xa4
> >     yield(d0bc8f40,1,f5549e18,80,14) at yield+0xa4
> >     pool_get(d0bc8f40,1,f5549ec8,d03ecbfb,d97815f4) at pool_get+0x1ba
> >     m_get(1,3,f5549ec0,d03a9362,d0bc22e0) at m_get+0x30
> >     doaccept(d977e6c4,3,cf7ee4f8,cf7ee4ec,2000) at doaccept+0x193
> >     sys_accept(d977e6c4,f5549f5c,f5549f7c,0,f5549fa8) at sys_accept+0x37
> >     syscall() at syscall+0x250
> >     
> > This means accept(2) is doing a memory allocation that can sleep, here
> > with m_get(9), while holding the NET_LOCK().  Even if these should be
> > ok, it is easy to avoid them.  In the case of doaccept() a mbuf could
> > be allocated beforehand or simply use the stack for that.
> > 
> > Cheers,
> > Martin
> >
> 
> splassert: yield: want 0 have 1
> Starting stack trace...
> yield() at yield+0xac
> pool_get() at pool_get+0x1ca
> m_get() at m_get+0x28
> ip_ctloutput() at ip_ctloutput+0x4bf
> sogetopt() at sogetopt+0x7e
> sys_getsockopt() at sys_getsockopt+0xbf
> syscall() at syscall+0x27b
> --- syscall (number 118) ---
> end of kernel
> end trace frame: 0x3, count: 250
> 0x978bdd844a:
> End of stack trace.
>  
>

Attempted to solve this and am running with this diff:

Index: kern/uipc_socket.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.174
diff -u -p -r1.174 uipc_socket.c
--- kern/uipc_socket.c  26 Jan 2017 00:08:50 -0000      1.174
+++ kern/uipc_socket.c  27 Jan 2017 18:08:26 -0000
@@ -1758,11 +1758,19 @@ sogetopt(struct socket *so, int level, i
 
        if (level != SOL_SOCKET) {
                if (so->so_proto && so->so_proto->pr_ctloutput) {
+                       m = m_get(M_WAIT, MT_SOOPTS);
+                       m->m_len = 0;
+
                        NET_LOCK(s);
                        error = (*so->so_proto->pr_ctloutput)(PRCO_GETOPT, so,
-                           level, optname, mp);
+                           level, optname, &m);
                        NET_UNLOCK(s);
-                       return (error);
+                       if (error) {
+                               m_free(m);
+                               return (error);
+                       }
+                       *mp = m;
+                       return (0);
                } else
                        return (ENOPROTOOPT);
        } else {
@@ -1835,21 +1843,25 @@ sogetopt(struct socket *so, int level, i
                    }
 
                case SO_RTABLE:
-                       (void)m_free(m);
                        if (so->so_proto && so->so_proto->pr_domain &&
                            so->so_proto->pr_domain->dom_protosw &&
                            so->so_proto->pr_ctloutput) {
                                struct domain *dom = so->so_proto->pr_domain;
 
                                level = dom->dom_protosw->pr_protocol;
+                       
                                NET_LOCK(s);
                                error = (*so->so_proto->pr_ctloutput)
-                                   (PRCO_GETOPT, so, level, optname, mp);
+                                   (PRCO_GETOPT, so, level, optname, &m);
                                NET_UNLOCK(s);
-                               return (error);
+                               if (error) {
+                                       (void)m_free(m);
+                                       return (error);
+                               }
+                               break;
                        }
+                       (void)m_free(m);
                        return (ENOPROTOOPT);
-                       break;
 
 #ifdef SOCKET_SPLICE
                case SO_SPLICE:
@@ -1880,7 +1892,6 @@ sogetopt(struct socket *so, int level, i
                        }
                        (void)m_free(m);
                        return (EOPNOTSUPP);
-                       break;
 
                default:
                        (void)m_free(m);
Index: net/rtsock.c
===================================================================
RCS file: /cvs/src/sys/net/rtsock.c,v
retrieving revision 1.220
diff -u -p -r1.220 rtsock.c
--- net/rtsock.c        24 Jan 2017 00:17:14 -0000      1.220
+++ net/rtsock.c        27 Jan 2017 18:08:26 -0000
@@ -277,12 +277,12 @@ route_ctloutput(int op, struct socket *s
        case PRCO_GETOPT:
                switch (optname) {
                case ROUTE_MSGFILTER:
-                       *mp = m = m_get(M_WAIT, MT_SOOPTS);
+                       m = *mp;
                        m->m_len = sizeof(unsigned int);
                        *mtod(m, unsigned int *) = rop->msgfilter;
                        break;
                case ROUTE_TABLEFILTER:
-                       *mp = m = m_get(M_WAIT, MT_SOOPTS);
+                       m = *mp;
                        m->m_len = sizeof(unsigned int);
                        *mtod(m, unsigned int *) = rop->rtableid;
                        break;
Index: netinet/ip_mroute.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_mroute.c,v
retrieving revision 1.107
diff -u -p -r1.107 ip_mroute.c
--- netinet/ip_mroute.c 12 Jan 2017 08:22:42 -0000      1.107
+++ netinet/ip_mroute.c 27 Jan 2017 18:08:26 -0000
@@ -225,8 +225,6 @@ ip_mrouter_get(struct socket *so, int op
        if (so != ip_mrouter[inp->inp_rtableid])
                error = ENOPROTOOPT;
        else {
-               *mp = m_get(M_WAIT, MT_SOOPTS);
-
                switch (optname) {
                case MRT_VERSION:
                        error = get_version(*mp);
@@ -241,9 +239,6 @@ ip_mrouter_get(struct socket *so, int op
                        error = ENOPROTOOPT;
                        break;
                }
-
-               if (error)
-                       m_free(*mp);
        }
 
        return (error);
Index: netinet/raw_ip.c
===================================================================
RCS file: /cvs/src/sys/netinet/raw_ip.c,v
retrieving revision 1.93
diff -u -p -r1.93 raw_ip.c
--- netinet/raw_ip.c    25 Jan 2017 17:34:31 -0000      1.93
+++ netinet/raw_ip.c    27 Jan 2017 18:08:26 -0000
@@ -347,7 +347,6 @@ rip_ctloutput(int op, struct socket *so,
                        break;
 
                case PRCO_GETOPT:
-                       *mp = m_get(M_WAIT, M_SOOPTS);
                        (*mp)->m_len = sizeof(int);
                        *mtod(*mp, int *) = inp->inp_divertfl;
                        break;
Index: netinet/tcp_usrreq.c
===================================================================
RCS file: /cvs/src/sys/netinet/tcp_usrreq.c,v
retrieving revision 1.142
diff -u -p -r1.142 tcp_usrreq.c
--- netinet/tcp_usrreq.c        10 Jan 2017 09:01:18 -0000      1.142
+++ netinet/tcp_usrreq.c        27 Jan 2017 18:08:26 -0000
@@ -573,7 +573,7 @@ tcp_ctloutput(int op, struct socket *so,
                break;
 
        case PRCO_GETOPT:
-               *mp = m = m_get(M_WAIT, MT_SOOPTS);
+               m = *mp;
                m->m_len = sizeof(int);
 
                switch (optname) {
Index: netinet6/icmp6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/icmp6.c,v
retrieving revision 1.197
diff -u -p -r1.197 icmp6.c
--- netinet6/icmp6.c    19 Jan 2017 14:49:19 -0000      1.197
+++ netinet6/icmp6.c    27 Jan 2017 18:08:26 -0000
@@ -1853,7 +1853,7 @@ icmp6_ctloutput(int op, struct socket *s
                                error = EINVAL;
                                break;
                        }
-                       *mp = m = m_get(M_WAIT, MT_SOOPTS);
+                       m = *mp;
                        m->m_len = sizeof(struct icmp6_filter);
                        p = mtod(m, struct icmp6_filter *);
                        bcopy(in6p->inp_icmp6filt, p,
Index: netinet6/ip6_mroute.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_mroute.c,v
retrieving revision 1.107
diff -u -p -r1.107 ip6_mroute.c
--- netinet6/ip6_mroute.c       6 Jan 2017 10:02:57 -0000       1.107
+++ netinet6/ip6_mroute.c       27 Jan 2017 18:08:26 -0000
@@ -250,8 +250,6 @@ ip6_mrouter_get(int cmd, struct socket *
        if (so != ip6_mrouter)
                return (EPERM);
 
-       *mp = m_get(M_WAIT, MT_SOOPTS);
-
        switch (cmd) {
        default:
                return EOPNOTSUPP;
Index: netinet6/ip6_output.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_output.c,v
retrieving revision 1.222
diff -u -p -r1.222 ip6_output.c
--- netinet6/ip6_output.c       27 Jan 2017 02:55:36 -0000      1.222
+++ netinet6/ip6_output.c       27 Jan 2017 18:08:26 -0000
@@ -1475,7 +1475,7 @@ do { \
                                }
                                if (error)
                                        break;
-                               *mp = m = m_get(M_WAIT, MT_SOOPTS);
+                               m = *mp;
                                m->m_len = sizeof(int);
                                *mtod(m, int *) = optval;
                                break;
@@ -1552,12 +1552,11 @@ do { \
                        case IPV6_ESP_TRANS_LEVEL:
                        case IPV6_ESP_NETWORK_LEVEL:
                        case IPV6_IPCOMP_LEVEL:
-                               *mp = m = m_get(M_WAIT, MT_SOOPTS);
+                               m = *mp;
+                               m->m_len = sizeof(int); 
 #ifndef IPSEC
-                               m->m_len = sizeof(int);
                                *mtod(m, int *) = IPSEC_LEVEL_NONE;
 #else
-                               m->m_len = sizeof(int);
                                switch (optname) {
                                case IPV6_AUTH_LEVEL:
                                        optval = inp->inp_seclevel[SL_AUTH];
@@ -1581,12 +1580,12 @@ do { \
 #endif
                                break;
                        case SO_RTABLE:
-                               *mp = m = m_get(M_WAIT, MT_SOOPTS);
+                               m = *mp;
                                m->m_len = sizeof(u_int);
                                *mtod(m, u_int *) = optval;
                                break;
                        case IPV6_PIPEX:
-                               *mp = m = m_get(M_WAIT, MT_SOOPTS);
+                               m = *mp;
                                m->m_len = sizeof(int);
                                *mtod(m, int *) = optval;
                                break;
@@ -1653,7 +1652,7 @@ ip6_raw_ctloutput(int op, struct socket 
                        else
                                optval = inp->inp_cksum6;
 
-                       *mp = m = m_get(M_WAIT, MT_SOOPTS);
+                       m = *mp;
                        m->m_len = sizeof(int);
                        *mtod(m, int *) = optval;
                        break;
@@ -1682,7 +1681,6 @@ ip6_raw_ctloutput(int op, struct socket 
 void
 ip6_initpktopts(struct ip6_pktopts *opt)
 {
-
        bzero(opt, sizeof(*opt));
        opt->ip6po_hlim = -1;   /* -1 means default hop limit */
        opt->ip6po_tclass = -1; /* -1 means default traffic class */
@@ -1787,7 +1785,7 @@ ip6_getpcbopt(struct ip6_pktopts *pktopt
 
        if (optdatalen > MCLBYTES)
                return (EMSGSIZE); /* XXX */
-       *mp = m = m_get(M_WAIT, MT_SOOPTS);
+       m = *mp;
        if (optdatalen > MLEN)
                MCLGET(m, M_WAIT);
        m->m_len = optdatalen;
@@ -2173,10 +2171,7 @@ ip6_getmoptions(int optname, struct ip6_
 {
        u_int *hlim, *loop, *ifindex;
 
-       *mp = m_get(M_WAIT, MT_SOOPTS);
-
        switch (optname) {
-
        case IPV6_MULTICAST_IF:
                ifindex = mtod(*mp, u_int *);
                (*mp)->m_len = sizeof(u_int);
Index: netinet6/raw_ip6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/raw_ip6.c,v
retrieving revision 1.103
diff -u -p -r1.103 raw_ip6.c
--- netinet6/raw_ip6.c  23 Jan 2017 16:31:24 -0000      1.103
+++ netinet6/raw_ip6.c  27 Jan 2017 18:08:26 -0000
@@ -502,7 +502,6 @@ rip6_ctloutput(int op, struct socket *so
                                break;
 
                        case PRCO_GETOPT:
-                               *mp = m_get(M_WAIT, M_SOOPTS);
                                (*mp)->m_len = sizeof(int);
                                *mtod(*mp, int *) = inp->inp_divertfl;
                                break;

Reply via email to