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;