On 07/02/17(Tue) 13:54, Martin Pieuchot wrote:
> Now that we found and fixed multiple deadlocks involving the NET_LOCK()
> and unix domain sockets, let's do as if it wasn't strictly necessary.
>
> The NET_LOCK() has been introduced to prevent the softnet thread to run
> while a userland process is pushing packets down into the Network Stack.
> This do not happen with PF_LOCAL sockets, so they simply don't need to
> grab the NET_LOCK().
>
> So this diff introduces a refreshed SOCKET_LOCK/SOCKET_UNLOCK set of
> macro that are currently doing nothing for PF_LOCAL sockets. Most of
> the code has been converted, except soclose() which is tricky due to
> sofree(9).
>
> The goal is then to use these macros to start un-KERNEL_LOCK()ing unix
> socket related syscalls.
>
> Tests and comments welcome.
Now with the AF check corrected, as found by tb@
Index: kern/sys_socket.c
===================================================================
RCS file: /cvs/src/sys/kern/sys_socket.c,v
retrieving revision 1.28
diff -u -p -r1.28 sys_socket.c
--- kern/sys_socket.c 31 Jan 2017 12:16:20 -0000 1.28
+++ kern/sys_socket.c 7 Feb 2017 14:26:19 -0000
@@ -38,6 +38,7 @@
#include <sys/proc.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
+#include <sys/domain.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/ioctl.h>
@@ -127,10 +128,10 @@ soo_ioctl(struct file *fp, u_long cmd, c
}
if (IOCGROUP(cmd) == 'r')
return (EOPNOTSUPP);
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
(struct mbuf *)cmd, (struct mbuf *)data, (struct mbuf *)NULL, p));
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
return (error);
}
@@ -187,10 +188,10 @@ soo_stat(struct file *fp, struct stat *u
ub->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
ub->st_uid = so->so_euid;
ub->st_gid = so->so_egid;
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
(void) ((*so->so_proto->pr_usrreq)(so, PRU_SENSE,
(struct mbuf *)ub, NULL, NULL, p));
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
return (0);
}
Index: kern/uipc_socket.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.176
diff -u -p -r1.176 uipc_socket.c
--- kern/uipc_socket.c 1 Feb 2017 20:59:47 -0000 1.176
+++ kern/uipc_socket.c 7 Feb 2017 14:26:04 -0000
@@ -135,16 +135,16 @@ socreate(int dom, struct socket **aso, i
so->so_egid = p->p_ucred->cr_gid;
so->so_cpid = p->p_p->ps_pid;
so->so_proto = prp;
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
error = (*prp->pr_usrreq)(so, PRU_ATTACH, NULL,
(struct mbuf *)(long)proto, NULL, p);
if (error) {
so->so_state |= SS_NOFDREF;
+ SOCKET_UNLOCK(so, s);
sofree(so);
- NET_UNLOCK(s);
return (error);
}
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
*aso = so;
return (0);
}
@@ -154,9 +154,9 @@ sobind(struct socket *so, struct mbuf *n
{
int s, error;
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
error = (*so->so_proto->pr_usrreq)(so, PRU_BIND, NULL, nam, NULL, p);
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
return (error);
}
@@ -171,11 +171,11 @@ solisten(struct socket *so, int backlog)
if (isspliced(so) || issplicedback(so))
return (EOPNOTSUPP);
#endif /* SOCKET_SPLICE */
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, NULL, NULL, NULL,
curproc);
if (error) {
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
return (error);
}
if (TAILQ_FIRST(&so->so_q) == NULL)
@@ -185,15 +185,13 @@ solisten(struct socket *so, int backlog)
if (backlog < sominconn)
backlog = sominconn;
so->so_qlimit = backlog;
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
return (0);
}
void
sofree(struct socket *so)
{
- NET_ASSERT_LOCKED();
-
if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
return;
if (so->so_head) {
@@ -294,7 +292,7 @@ soaccept(struct socket *so, struct mbuf
{
int error = 0;
- NET_ASSERT_LOCKED();
+ SOCKET_ASSERT_LOCKED(so);
if ((so->so_state & SS_NOFDREF) == 0)
panic("soaccept !NOFDREF: so %p, so_type %d", so, so->so_type);
@@ -315,7 +313,7 @@ soconnect(struct socket *so, struct mbuf
if (so->so_options & SO_ACCEPTCONN)
return (EOPNOTSUPP);
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
/*
* If protocol is connection-based, can only connect once.
* Otherwise, if connected, try to disconnect first.
@@ -329,7 +327,7 @@ soconnect(struct socket *so, struct mbuf
else
error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
NULL, nam, NULL, curproc);
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
return (error);
}
@@ -338,10 +336,10 @@ soconnect2(struct socket *so1, struct so
{
int s, error;
- NET_LOCK(s);
+ SOCKET_LOCK(so1, s);
error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2, NULL,
(struct mbuf *)so2, NULL, curproc);
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so1, s);
return (error);
}
@@ -350,7 +348,7 @@ sodisconnect(struct socket *so)
{
int error;
- NET_ASSERT_LOCKED();
+ SOCKET_ASSERT_LOCKED(so);
if ((so->so_state & SS_ISCONNECTED) == 0)
return (ENOTCONN);
@@ -418,14 +416,14 @@ sosend(struct socket *so, struct mbuf *a
(sizeof(struct fdpass) / sizeof(int)));
}
-#define snderr(errno) { error = errno; NET_UNLOCK(s); goto release; }
+#define snderr(errno) { error = errno; SOCKET_UNLOCK(so, s); goto
release; }
restart:
if ((error = sblock(&so->so_snd, SBLOCKWAIT(flags), NULL)) != 0)
goto out;
so->so_state |= SS_ISSENDING;
do {
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
if (so->so_state & SS_CANTSENDMORE)
snderr(EPIPE);
if (so->so_error) {
@@ -453,14 +451,14 @@ restart:
if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT))
snderr(EWOULDBLOCK);
sbunlock(&so->so_snd);
- error = sbwait(&so->so_snd);
+ error = sbwait(so, &so->so_snd);
so->so_state &= ~SS_ISSENDING;
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
if (error)
goto out;
goto restart;
}
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
space -= clen;
do {
if (uio == NULL) {
@@ -480,13 +478,13 @@ restart:
if (flags & MSG_EOR)
top->m_flags |= M_EOR;
}
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
if (resid == 0)
so->so_state &= ~SS_ISSENDING;
error = (*so->so_proto->pr_usrreq)(so,
(flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND,
top, addr, control, curproc);
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
clen = 0;
control = NULL;
top = NULL;
@@ -615,7 +613,7 @@ sbsync(struct sockbuf *sb, struct mbuf *
* followed by an optional mbuf or mbufs containing ancillary data,
* and then zero or more mbufs of data.
* In order to avoid blocking network for the entire time here, we release
- * the NET_LOCK() while doing the actual copy to user space.
+ * the SOCKET_LOCK() while doing the actual copy to user space.
* Although the sockbuf is locked, new data may still be appended,
* and thus we must maintain consistency of the sockbuf during that time.
*
@@ -649,10 +647,10 @@ soreceive(struct socket *so, struct mbuf
flags |= MSG_DONTWAIT;
if (flags & MSG_OOB) {
m = m_get(M_WAIT, MT_DATA);
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
error = (*pr->pr_usrreq)(so, PRU_RCVOOB, m,
(struct mbuf *)(long)(flags & MSG_PEEK), NULL, curproc);
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
if (error)
goto bad;
do {
@@ -670,7 +668,7 @@ bad:
restart:
if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags), NULL)) != 0)
return (error);
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
m = so->so_rcv.sb_mb;
#ifdef SOCKET_SPLICE
@@ -734,8 +732,8 @@ restart:
SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 1");
SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 1");
sbunlock(&so->so_rcv);
- error = sbwait(&so->so_rcv);
- NET_UNLOCK(s);
+ error = sbwait(so, &so->so_rcv);
+ SOCKET_UNLOCK(so, s);
if (error)
return (error);
goto restart;
@@ -801,11 +799,9 @@ dontblock:
if (pr->pr_domain->dom_externalize &&
mtod(cm, struct cmsghdr *)->cmsg_type ==
SCM_RIGHTS) {
- NET_UNLOCK(s);
error =
(*pr->pr_domain->dom_externalize)
(cm, controllen, flags);
- NET_LOCK(s);
}
*controlp = cm;
} else {
@@ -873,9 +869,9 @@ dontblock:
SBLASTRECORDCHK(&so->so_rcv, "soreceive uiomove");
SBLASTMBUFCHK(&so->so_rcv, "soreceive uiomove");
resid = uio->uio_resid;
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
uio_error = uiomove(mtod(m, caddr_t) + moff, len, uio);
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
if (uio_error)
uio->uio_resid = resid - len;
} else
@@ -954,10 +950,10 @@ dontblock:
break;
SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 2");
SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 2");
- error = sbwait(&so->so_rcv);
+ error = sbwait(so, &so->so_rcv);
if (error) {
sbunlock(&so->so_rcv);
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
return (0);
}
if ((m = so->so_rcv.sb_mb) != NULL)
@@ -993,7 +989,7 @@ dontblock:
if (orig_resid == uio->uio_resid && orig_resid &&
(flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {
sbunlock(&so->so_rcv);
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
goto restart;
}
@@ -1004,7 +1000,7 @@ dontblock:
*flagsp |= flags;
release:
sbunlock(&so->so_rcv);
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
return (error);
}
@@ -1014,7 +1010,7 @@ soshutdown(struct socket *so, int how)
struct protosw *pr = so->so_proto;
int s, error = 0;
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
switch (how) {
case SHUT_RD:
case SHUT_RDWR:
@@ -1030,7 +1026,7 @@ soshutdown(struct socket *so, int how)
error = EINVAL;
break;
}
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
return (error);
}
@@ -1043,7 +1039,8 @@ sorflush(struct socket *so)
struct sockbuf asb;
sb->sb_flags |= SB_NOINTR;
- (void) sblock(sb, M_WAITOK, &netlock);
+ sblock(sb, M_WAITOK,
+ (pr->pr_domain->dom_family != PF_LOCAL) ? &netlock : NULL);
socantrcvmore(so);
sbunlock(sb);
asb = *sb;
@@ -1094,10 +1091,10 @@ sosplice(struct socket *so, int fd, off_
if ((error = sblock(&so->so_rcv,
(so->so_state & SS_NBIO) ? M_NOWAIT : M_WAITOK, NULL)) != 0)
return (error);
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
if (so->so_sp->ssp_socket)
sounsplice(so, so->so_sp->ssp_socket, 1);
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
sbunlock(&so->so_rcv);
return (0);
}
@@ -1126,7 +1123,7 @@ sosplice(struct socket *so, int fd, off_
FRELE(fp, curproc);
return (error);
}
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
if (so->so_sp->ssp_socket || sosp->so_sp->ssp_soback) {
error = EBUSY;
@@ -1167,7 +1164,7 @@ sosplice(struct socket *so, int fd, off_
}
release:
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
sbunlock(&sosp->so_snd);
sbunlock(&so->so_rcv);
FRELE(fp, curproc);
@@ -1177,7 +1174,7 @@ sosplice(struct socket *so, int fd, off_
void
sounsplice(struct socket *so, struct socket *sosp, int wakeup)
{
- NET_ASSERT_LOCKED();
+ SOCKET_ASSERT_LOCKED(so);
task_del(sosplice_taskq, &so->so_splicetask);
timeout_del(&so->so_idleto);
@@ -1194,12 +1191,12 @@ soidle(void *arg)
struct socket *so = arg;
int s;
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
if (so->so_rcv.sb_flagsintr & SB_SPLICE) {
so->so_error = ETIMEDOUT;
sounsplice(so, so->so_sp->ssp_socket, 1);
}
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
}
void
@@ -1208,7 +1205,7 @@ sotask(void *arg)
struct socket *so = arg;
int s;
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
if (so->so_rcv.sb_flagsintr & SB_SPLICE) {
/*
* We may not sleep here as sofree() and unsplice() may be
@@ -1217,7 +1214,7 @@ sotask(void *arg)
*/
somove(so, M_DONTWAIT);
}
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
/* Avoid user land starvation. */
yield();
@@ -1239,7 +1236,7 @@ somove(struct socket *so, int wait)
int error = 0, maxreached = 0;
short state;
- NET_ASSERT_LOCKED();
+ SOCKET_ASSERT_LOCKED(so);
nextpkt:
if (so->so_error) {
@@ -1509,7 +1506,7 @@ somove(struct socket *so, int wait)
void
sorwakeup(struct socket *so)
{
- NET_ASSERT_LOCKED();
+ SOCKET_ASSERT_LOCKED(so);
#ifdef SOCKET_SPLICE
if (so->so_rcv.sb_flagsintr & SB_SPLICE) {
@@ -1541,7 +1538,7 @@ sorwakeup(struct socket *so)
void
sowwakeup(struct socket *so)
{
- NET_ASSERT_LOCKED();
+ SOCKET_ASSERT_LOCKED(so);
#ifdef SOCKET_SPLICE
if (so->so_snd.sb_flagsintr & SB_SPLICE)
@@ -1558,10 +1555,10 @@ sosetopt(struct socket *so, int level, i
if (level != SOL_SOCKET) {
if (so->so_proto && so->so_proto->pr_ctloutput) {
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
error = (*so->so_proto->pr_ctloutput)(PRCO_SETOPT, so,
level, optname, m0);
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
return (error);
}
error = ENOPROTOOPT;
@@ -1705,10 +1702,10 @@ sosetopt(struct socket *so, int level, i
struct domain *dom = so->so_proto->pr_domain;
level = dom->dom_protosw->pr_protocol;
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
error = (*so->so_proto->pr_ctloutput)
(PRCO_SETOPT, so, level, optname, m0);
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
return (error);
}
error = ENOPROTOOPT;
@@ -1737,10 +1734,10 @@ sosetopt(struct socket *so, int level, i
break;
}
if (error == 0 && so->so_proto && so->so_proto->pr_ctloutput) {
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
(*so->so_proto->pr_ctloutput)(PRCO_SETOPT, so,
level, optname, m0);
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
m = NULL; /* freed by protocol */
}
}
@@ -1761,10 +1758,10 @@ sogetopt(struct socket *so, int level, i
m = m_get(M_WAIT, MT_SOOPTS);
m->m_len = 0;
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
error = (*so->so_proto->pr_ctloutput)(PRCO_GETOPT, so,
level, optname, m);
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
if (error) {
m_free(m);
return (error);
@@ -1849,10 +1846,10 @@ sogetopt(struct socket *so, int level, i
struct domain *dom = so->so_proto->pr_domain;
level = dom->dom_protosw->pr_protocol;
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
error = (*so->so_proto->pr_ctloutput)
(PRCO_GETOPT, so, level, optname, m);
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
if (error) {
(void)m_free(m);
return (error);
Index: kern/uipc_socket2.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_socket2.c,v
retrieving revision 1.71
diff -u -p -r1.71 uipc_socket2.c
--- kern/uipc_socket2.c 25 Jan 2017 06:15:50 -0000 1.71
+++ kern/uipc_socket2.c 7 Feb 2017 14:22:57 -0000
@@ -38,6 +38,7 @@
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
+#include <sys/domain.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/signalvar.h>
@@ -147,7 +148,7 @@ sonewconn(struct socket *head, int conns
struct socket *so;
int soqueue = connstatus ? 1 : 0;
- NET_ASSERT_LOCKED();
+ SOCKET_ASSERT_LOCKED(head);
if (mclpools[0].pr_nout > mclpools[0].pr_hardlimit * 95 / 100)
return (NULL);
@@ -267,16 +268,25 @@ socantrcvmore(struct socket *so)
sorwakeup(so);
}
+int
+sosleep(struct socket *so, void *ident, int prio, const char *wmesg, int timo)
+{
+ if (so->so_proto->pr_protocol != PF_LOCAL)
+ return rwsleep(ident, &netlock, prio, wmesg, timo);
+ else
+ return tsleep(ident, prio, wmesg, timo);
+}
+
/*
* Wait for data to arrive at/drain from a socket buffer.
*/
int
-sbwait(struct sockbuf *sb)
+sbwait(struct socket *so, struct sockbuf *sb)
{
- NET_ASSERT_LOCKED();
+ SOCKET_ASSERT_LOCKED(so);
sb->sb_flagsintr |= SB_WAIT;
- return (rwsleep(&sb->sb_cc, &netlock,
+ return (sosleep(so, &sb->sb_cc,
(sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH, "netio",
sb->sb_timeo));
}
@@ -338,7 +348,7 @@ sbunlock(struct sockbuf *sb)
void
sowakeup(struct socket *so, struct sockbuf *sb)
{
- NET_ASSERT_LOCKED();
+ SOCKET_ASSERT_LOCKED(so);
selwakeup(&sb->sb_sel);
sb->sb_flagsintr &= ~SB_SEL;
Index: kern/uipc_syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_syscalls.c,v
retrieving revision 1.148
diff -u -p -r1.148 uipc_syscalls.c
--- kern/uipc_syscalls.c 26 Jan 2017 01:58:00 -0000 1.148
+++ kern/uipc_syscalls.c 7 Feb 2017 12:31:52 -0000
@@ -289,9 +289,9 @@ doaccept(struct proc *p, int sock, struc
}
nam = m_get(M_WAIT, MT_SONAME);
-
- NET_LOCK(s);
+
head = headfp->f_data;
+ SOCKET_LOCK(head, s);
if (isdnssocket(head) || (head->so_options & SO_ACCEPTCONN) == 0) {
error = EINVAL;
goto out;
@@ -308,8 +308,8 @@ doaccept(struct proc *p, int sock, struc
head->so_error = ECONNABORTED;
break;
}
- error = rwsleep(&head->so_timeo, &netlock, PSOCK | PCATCH,
- "netcon", 0);
+ error = sosleep(head, &head->so_timeo, PSOCK | PCATCH, "netcon",
+ 0);
if (error)
goto out;
}
@@ -346,7 +346,7 @@ doaccept(struct proc *p, int sock, struc
*retval = tmpfd;
}
out:
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(head, s);
m_freem(nam);
if (error) {
fdplock(fdp);
@@ -410,9 +410,9 @@ sys_connect(struct proc *p, void *v, reg
m_freem(nam);
return (EINPROGRESS);
}
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
- error = rwsleep(&so->so_timeo, &netlock, PSOCK | PCATCH,
+ error = sosleep(so, &so->so_timeo, PSOCK | PCATCH,
"netcon2", 0);
if (error) {
if (error == EINTR || error == ERESTART)
@@ -424,7 +424,7 @@ sys_connect(struct proc *p, void *v, reg
error = so->so_error;
so->so_error = 0;
}
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
bad:
if (!interrupted)
so->so_state &= ~SS_ISCONNECTING;
@@ -1051,9 +1051,9 @@ sys_getsockname(struct proc *p, void *v,
if (error)
goto bad;
m = m_getclr(M_WAIT, MT_SONAME);
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0, p);
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
if (error)
goto bad;
error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
@@ -1094,9 +1094,9 @@ sys_getpeername(struct proc *p, void *v,
if (error)
goto bad;
m = m_getclr(M_WAIT, MT_SONAME);
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0, p);
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
if (error)
goto bad;
error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
Index: kern/uipc_usrreq.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_usrreq.c,v
retrieving revision 1.113
diff -u -p -r1.113 uipc_usrreq.c
--- kern/uipc_usrreq.c 27 Jan 2017 20:31:42 -0000 1.113
+++ kern/uipc_usrreq.c 7 Feb 2017 12:39:08 -0000
@@ -124,6 +124,7 @@ uipc_usrreq(struct socket *so, int req,
switch (req) {
case PRU_ATTACH:
+ NET_ASSERT_UNLOCKED();
if (unp) {
error = EISCONN;
break;
@@ -136,25 +137,23 @@ uipc_usrreq(struct socket *so, int req,
break;
case PRU_BIND:
- /* XXXSMP breaks atomicity */
- rw_exit_write(&netlock);
+ NET_ASSERT_UNLOCKED();
error = unp_bind(unp, nam, p);
- rw_enter_write(&netlock);
break;
case PRU_LISTEN:
+ NET_ASSERT_UNLOCKED();
if (unp->unp_vnode == NULL)
error = EINVAL;
break;
case PRU_CONNECT:
- /* XXXSMP breaks atomicity */
- rw_exit_write(&netlock);
+ NET_ASSERT_UNLOCKED();
error = unp_connect(so, nam, p);
- rw_enter_write(&netlock);
break;
case PRU_CONNECT2:
+ NET_ASSERT_UNLOCKED();
error = unp_connect2(so, (struct socket *)nam);
break;
@@ -163,6 +162,7 @@ uipc_usrreq(struct socket *so, int req,
break;
case PRU_ACCEPT:
+ NET_ASSERT_UNLOCKED();
/*
* Pass back name of connected socket,
* if it was bound and we are still connected
@@ -172,11 +172,13 @@ uipc_usrreq(struct socket *so, int req,
break;
case PRU_SHUTDOWN:
+ NET_ASSERT_UNLOCKED();
socantsendmore(so);
unp_shutdown(unp);
break;
case PRU_RCVD:
+ NET_ASSERT_UNLOCKED();
switch (so->so_type) {
case SOCK_DGRAM:
@@ -207,6 +209,7 @@ uipc_usrreq(struct socket *so, int req,
break;
case PRU_SEND:
+ NET_ASSERT_UNLOCKED();
if (control && (error = unp_internalize(control, p)))
break;
switch (so->so_type) {
@@ -219,10 +222,7 @@ uipc_usrreq(struct socket *so, int req,
error = EISCONN;
break;
}
- /* XXXSMP breaks atomicity */
- rw_exit_write(&netlock);
error = unp_connect(so, nam, p);
- rw_enter_write(&netlock);
if (error)
break;
} else {
@@ -299,6 +299,8 @@ uipc_usrreq(struct socket *so, int req,
case PRU_SENSE: {
struct stat *sb = (struct stat *)m;
+ NET_ASSERT_UNLOCKED();
+
sb->st_blksize = so->so_snd.sb_hiwat;
sb->st_dev = NODEV;
if (unp->unp_ino == 0)
@@ -321,10 +323,12 @@ uipc_usrreq(struct socket *so, int req,
break;
case PRU_SOCKADDR:
+ NET_ASSERT_UNLOCKED();
uipc_setaddr(unp, nam);
break;
case PRU_PEERADDR:
+ NET_ASSERT_UNLOCKED();
uipc_setaddr(unp->unp_conn, nam);
break;
@@ -531,7 +535,7 @@ unp_connect(struct socket *so, struct mb
error = EPROTOTYPE;
goto bad;
}
- NET_LOCK(s);
+ SOCKET_LOCK(so, s);
if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
if ((so2->so_options & SO_ACCEPTCONN) == 0 ||
(so3 = sonewconn(so2, 0)) == 0) {
@@ -556,7 +560,7 @@ unp_connect(struct socket *so, struct mb
}
error = unp_connect2(so, so2);
unlock:
- NET_UNLOCK(s);
+ SOCKET_UNLOCK(so, s);
bad:
vput(vp);
return (error);
Index: sys/socketvar.h
===================================================================
RCS file: /cvs/src/sys/sys/socketvar.h,v
retrieving revision 1.67
diff -u -p -r1.67 socketvar.h
--- sys/socketvar.h 19 Dec 2016 08:36:50 -0000 1.67
+++ sys/socketvar.h 7 Feb 2017 12:22:16 -0000
@@ -278,7 +278,7 @@ void sbrelease(struct sockbuf *sb);
int sbcheckreserve(u_long cnt, u_long defcnt);
int sbchecklowmem(void);
int sbreserve(struct sockbuf *sb, u_long cc);
-int sbwait(struct sockbuf *sb);
+int sbwait(struct socket *, struct sockbuf *sb);
int sb_lock(struct sockbuf *sb);
void soinit(void);
int soabort(struct socket *so);
@@ -313,6 +313,7 @@ int sosend(struct socket *so, struct mbu
int sosetopt(struct socket *so, int level, int optname,
struct mbuf *m0);
int soshutdown(struct socket *so, int how);
+int sosleep(struct socket *, void *, int, const char *, int);
void sowakeup(struct socket *so, struct sockbuf *sb);
void sorwakeup(struct socket *);
void sowwakeup(struct socket *);
Index: sys/systm.h
===================================================================
RCS file: /cvs/src/sys/sys/systm.h,v
retrieving revision 1.123
diff -u -p -r1.123 systm.h
--- sys/systm.h 25 Jan 2017 06:15:50 -0000 1.123
+++ sys/systm.h 7 Feb 2017 14:22:30 -0000
@@ -301,7 +301,7 @@ do {
\
s = splsoftnet(); \
} while (0)
-#define NET_UNLOCK(s) \
+#define NET_UNLOCK(s)
\
do { \
splx(s); \
rw_exit_write(&netlock); \
@@ -318,6 +318,24 @@ do {
\
do { \
if (rw_status(&netlock) == RW_WRITE) \
splassert_fail(0, rw_status(&netlock), __func__); \
+} while (0)
+
+#define SOCKET_LOCK(so, s)
\
+do { \
+ if (so->so_proto->pr_domain->dom_family != PF_LOCAL) \
+ NET_LOCK(s); \
+} while (0)
+
+#define SOCKET_UNLOCK(so, s)
\
+do { \
+ if (so->so_proto->pr_domain->dom_family != PF_LOCAL) \
+ NET_UNLOCK(s); \
+} while (0)
+
+#define SOCKET_ASSERT_LOCKED(so)
\
+do { \
+ if (so->so_proto->pr_domain->dom_family != PF_LOCAL) \
+ NET_ASSERT_LOCKED(); \
} while (0)
__returns_twice int setjmp(label_t *);