On Mon, Feb 13, 2017 at 10:45:43AM +0100, Martin Pieuchot wrote:
> On 10/02/17(Fri) 15:21, Alexander Bluhm wrote:
> > The 42 looks like an evil hack.
> It is. I couldn't come to a better solution without refactoring the
> pr_usrreq interface.
The only problem I see is sofree(). In kern/uipc_socket.c sofree(so)
is called two times before unlock(s), so we cannot pass so to check
so->so_proto->pr_domain->dom_family.
There must be a better solution than 42, but this should not delay
this diff. Add a comment that we have to fix it later.
> I also change the SOCKET_LOCK() macros into real
> functions to stop polluting <sys/systm.h>.
I would prefer if NET_LOCK(s) and solock(so) would look similar.
So either s = netlock(); s = solock(so); or NET_LOCK(s); SOCKET_LOCK(so, s);
> Comments, oks?
I did run the regression tests. The same tests pass or fail with
and without this diff.
OK bluhm@
> 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 13 Feb 2017 09:28:51 -0000
> @@ -127,10 +127,10 @@ soo_ioctl(struct file *fp, u_long cmd, c
> }
> if (IOCGROUP(cmd) == 'r')
> return (EOPNOTSUPP);
> - NET_LOCK(s);
> + s = solock(so);
> error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
> (struct mbuf *)cmd, (struct mbuf *)data, (struct mbuf *)NULL, p));
> - NET_UNLOCK(s);
> + sounlock(s);
>
> return (error);
> }
> @@ -187,10 +187,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);
> + s = solock(so);
> (void) ((*so->so_proto->pr_usrreq)(so, PRU_SENSE,
> (struct mbuf *)ub, NULL, NULL, p));
> - NET_UNLOCK(s);
> + sounlock(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 13 Feb 2017 09:29:45 -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);
> + s = solock(so);
> error = (*prp->pr_usrreq)(so, PRU_ATTACH, NULL,
> (struct mbuf *)(long)proto, NULL, p);
> if (error) {
> so->so_state |= SS_NOFDREF;
> sofree(so);
> - NET_UNLOCK(s);
> + sounlock(s);
> return (error);
> }
> - NET_UNLOCK(s);
> + sounlock(s);
> *aso = so;
> return (0);
> }
> @@ -154,9 +154,9 @@ sobind(struct socket *so, struct mbuf *n
> {
> int s, error;
>
> - NET_LOCK(s);
> + s = solock(so);
> error = (*so->so_proto->pr_usrreq)(so, PRU_BIND, NULL, nam, NULL, p);
> - NET_UNLOCK(s);
> + sounlock(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);
> + s = solock(so);
> error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, NULL, NULL, NULL,
> curproc);
> if (error) {
> - NET_UNLOCK(s);
> + sounlock(s);
> return (error);
> }
> if (TAILQ_FIRST(&so->so_q) == NULL)
> @@ -185,14 +185,14 @@ solisten(struct socket *so, int backlog)
> if (backlog < sominconn)
> backlog = sominconn;
> so->so_qlimit = backlog;
> - NET_UNLOCK(s);
> + sounlock(s);
> return (0);
> }
>
> void
> sofree(struct socket *so)
> {
> - NET_ASSERT_LOCKED();
> + soassertlocked(so);
>
> if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
> return;
> @@ -232,7 +232,7 @@ soclose(struct socket *so)
> struct socket *so2;
> int s, error = 0;
>
> - NET_LOCK(s);
> + s = solock(so);
> if (so->so_options & SO_ACCEPTCONN) {
> while ((so2 = TAILQ_FIRST(&so->so_q0)) != NULL) {
> (void) soqremque(so2, 0);
> @@ -256,7 +256,7 @@ soclose(struct socket *so)
> (so->so_state & SS_NBIO))
> goto drop;
> while (so->so_state & SS_ISCONNECTED) {
> - error = rwsleep(&so->so_timeo, &netlock,
> + error = sosleep(so, &so->so_timeo,
> PSOCK | PCATCH, "netcls",
> so->so_linger * hz);
> if (error)
> @@ -276,14 +276,14 @@ discard:
> panic("soclose NOFDREF: so %p, so_type %d", so, so->so_type);
> so->so_state |= SS_NOFDREF;
> sofree(so);
> - NET_UNLOCK(s);
> + sounlock(s);
> return (error);
> }
>
> int
> soabort(struct socket *so)
> {
> - NET_ASSERT_LOCKED();
> + soassertlocked(so);
>
> return (*so->so_proto->pr_usrreq)(so, PRU_ABORT, NULL, NULL, NULL,
> curproc);
> @@ -294,7 +294,7 @@ soaccept(struct socket *so, struct mbuf
> {
> int error = 0;
>
> - NET_ASSERT_LOCKED();
> + soassertlocked(so);
>
> if ((so->so_state & SS_NOFDREF) == 0)
> panic("soaccept !NOFDREF: so %p, so_type %d", so, so->so_type);
> @@ -315,7 +315,7 @@ soconnect(struct socket *so, struct mbuf
>
> if (so->so_options & SO_ACCEPTCONN)
> return (EOPNOTSUPP);
> - NET_LOCK(s);
> + s = solock(so);
> /*
> * If protocol is connection-based, can only connect once.
> * Otherwise, if connected, try to disconnect first.
> @@ -329,7 +329,7 @@ soconnect(struct socket *so, struct mbuf
> else
> error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
> NULL, nam, NULL, curproc);
> - NET_UNLOCK(s);
> + sounlock(s);
> return (error);
> }
>
> @@ -338,10 +338,10 @@ soconnect2(struct socket *so1, struct so
> {
> int s, error;
>
> - NET_LOCK(s);
> + s = solock(so1);
> error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2, NULL,
> (struct mbuf *)so2, NULL, curproc);
> - NET_UNLOCK(s);
> + sounlock(s);
> return (error);
> }
>
> @@ -350,7 +350,7 @@ sodisconnect(struct socket *so)
> {
> int error;
>
> - NET_ASSERT_LOCKED();
> + soassertlocked(so);
>
> if ((so->so_state & SS_ISCONNECTED) == 0)
> return (ENOTCONN);
> @@ -418,14 +418,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; sounlock(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);
> + s = solock(so);
> if (so->so_state & SS_CANTSENDMORE)
> snderr(EPIPE);
> if (so->so_error) {
> @@ -453,14 +453,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);
> + sounlock(s);
> if (error)
> goto out;
> goto restart;
> }
> - NET_UNLOCK(s);
> + sounlock(s);
> space -= clen;
> do {
> if (uio == NULL) {
> @@ -480,13 +480,13 @@ restart:
> if (flags & MSG_EOR)
> top->m_flags |= M_EOR;
> }
> - NET_LOCK(s);
> + s = solock(so);
> 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);
> + sounlock(s);
> clen = 0;
> control = NULL;
> top = NULL;
> @@ -615,7 +615,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 solock() 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 +649,10 @@ soreceive(struct socket *so, struct mbuf
> flags |= MSG_DONTWAIT;
> if (flags & MSG_OOB) {
> m = m_get(M_WAIT, MT_DATA);
> - NET_LOCK(s);
> + s = solock(so);
> error = (*pr->pr_usrreq)(so, PRU_RCVOOB, m,
> (struct mbuf *)(long)(flags & MSG_PEEK), NULL, curproc);
> - NET_UNLOCK(s);
> + sounlock(s);
> if (error)
> goto bad;
> do {
> @@ -670,7 +670,7 @@ bad:
> restart:
> if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags), NULL)) != 0)
> return (error);
> - NET_LOCK(s);
> + s = solock(so);
>
> m = so->so_rcv.sb_mb;
> #ifdef SOCKET_SPLICE
> @@ -734,8 +734,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);
> + sounlock(s);
> if (error)
> return (error);
> goto restart;
> @@ -801,11 +801,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 +871,9 @@ dontblock:
> SBLASTRECORDCHK(&so->so_rcv, "soreceive uiomove");
> SBLASTMBUFCHK(&so->so_rcv, "soreceive uiomove");
> resid = uio->uio_resid;
> - NET_UNLOCK(s);
> + sounlock(s);
> uio_error = uiomove(mtod(m, caddr_t) + moff, len, uio);
> - NET_LOCK(s);
> + s = solock(so);
> if (uio_error)
> uio->uio_resid = resid - len;
> } else
> @@ -954,10 +952,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);
> + sounlock(s);
> return (0);
> }
> if ((m = so->so_rcv.sb_mb) != NULL)
> @@ -993,7 +991,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);
> + sounlock(s);
> goto restart;
> }
>
> @@ -1004,7 +1002,7 @@ dontblock:
> *flagsp |= flags;
> release:
> sbunlock(&so->so_rcv);
> - NET_UNLOCK(s);
> + sounlock(s);
> return (error);
> }
>
> @@ -1014,7 +1012,7 @@ soshutdown(struct socket *so, int how)
> struct protosw *pr = so->so_proto;
> int s, error = 0;
>
> - NET_LOCK(s);
> + s = solock(so);
> switch (how) {
> case SHUT_RD:
> case SHUT_RDWR:
> @@ -1030,7 +1028,7 @@ soshutdown(struct socket *so, int how)
> error = EINVAL;
> break;
> }
> - NET_UNLOCK(s);
> + sounlock(s);
>
> return (error);
> }
> @@ -1043,7 +1041,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 +1093,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);
> + s = solock(so);
> if (so->so_sp->ssp_socket)
> sounsplice(so, so->so_sp->ssp_socket, 1);
> - NET_UNLOCK(s);
> + sounlock(s);
> sbunlock(&so->so_rcv);
> return (0);
> }
> @@ -1126,7 +1125,7 @@ sosplice(struct socket *so, int fd, off_
> FRELE(fp, curproc);
> return (error);
> }
> - NET_LOCK(s);
> + s = solock(so);
>
> if (so->so_sp->ssp_socket || sosp->so_sp->ssp_soback) {
> error = EBUSY;
> @@ -1167,7 +1166,7 @@ sosplice(struct socket *so, int fd, off_
> }
>
> release:
> - NET_UNLOCK(s);
> + sounlock(s);
> sbunlock(&sosp->so_snd);
> sbunlock(&so->so_rcv);
> FRELE(fp, curproc);
> @@ -1177,7 +1176,7 @@ sosplice(struct socket *so, int fd, off_
> void
> sounsplice(struct socket *so, struct socket *sosp, int wakeup)
> {
> - NET_ASSERT_LOCKED();
> + soassertlocked(so);
>
> task_del(sosplice_taskq, &so->so_splicetask);
> timeout_del(&so->so_idleto);
> @@ -1194,12 +1193,12 @@ soidle(void *arg)
> struct socket *so = arg;
> int s;
>
> - NET_LOCK(s);
> + s = solock(so);
> if (so->so_rcv.sb_flagsintr & SB_SPLICE) {
> so->so_error = ETIMEDOUT;
> sounsplice(so, so->so_sp->ssp_socket, 1);
> }
> - NET_UNLOCK(s);
> + sounlock(s);
> }
>
> void
> @@ -1208,7 +1207,7 @@ sotask(void *arg)
> struct socket *so = arg;
> int s;
>
> - NET_LOCK(s);
> + s = solock(so);
> if (so->so_rcv.sb_flagsintr & SB_SPLICE) {
> /*
> * We may not sleep here as sofree() and unsplice() may be
> @@ -1217,7 +1216,7 @@ sotask(void *arg)
> */
> somove(so, M_DONTWAIT);
> }
> - NET_UNLOCK(s);
> + sounlock(s);
>
> /* Avoid user land starvation. */
> yield();
> @@ -1239,7 +1238,7 @@ somove(struct socket *so, int wait)
> int error = 0, maxreached = 0;
> short state;
>
> - NET_ASSERT_LOCKED();
> + soassertlocked(so);
>
> nextpkt:
> if (so->so_error) {
> @@ -1509,7 +1508,7 @@ somove(struct socket *so, int wait)
> void
> sorwakeup(struct socket *so)
> {
> - NET_ASSERT_LOCKED();
> + soassertlocked(so);
>
> #ifdef SOCKET_SPLICE
> if (so->so_rcv.sb_flagsintr & SB_SPLICE) {
> @@ -1541,7 +1540,7 @@ sorwakeup(struct socket *so)
> void
> sowwakeup(struct socket *so)
> {
> - NET_ASSERT_LOCKED();
> + soassertlocked(so);
>
> #ifdef SOCKET_SPLICE
> if (so->so_snd.sb_flagsintr & SB_SPLICE)
> @@ -1558,10 +1557,10 @@ sosetopt(struct socket *so, int level, i
>
> if (level != SOL_SOCKET) {
> if (so->so_proto && so->so_proto->pr_ctloutput) {
> - NET_LOCK(s);
> + s = solock(so);
> error = (*so->so_proto->pr_ctloutput)(PRCO_SETOPT, so,
> level, optname, m0);
> - NET_UNLOCK(s);
> + sounlock(s);
> return (error);
> }
> error = ENOPROTOOPT;
> @@ -1705,10 +1704,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);
> + s = solock(so);
> error = (*so->so_proto->pr_ctloutput)
> (PRCO_SETOPT, so, level, optname, m0);
> - NET_UNLOCK(s);
> + sounlock(s);
> return (error);
> }
> error = ENOPROTOOPT;
> @@ -1737,10 +1736,10 @@ sosetopt(struct socket *so, int level, i
> break;
> }
> if (error == 0 && so->so_proto && so->so_proto->pr_ctloutput) {
> - NET_LOCK(s);
> + s = solock(so);
> (*so->so_proto->pr_ctloutput)(PRCO_SETOPT, so,
> level, optname, m0);
> - NET_UNLOCK(s);
> + sounlock(s);
> m = NULL; /* freed by protocol */
> }
> }
> @@ -1761,10 +1760,10 @@ sogetopt(struct socket *so, int level, i
> m = m_get(M_WAIT, MT_SOOPTS);
> m->m_len = 0;
>
> - NET_LOCK(s);
> + s = solock(so);
> error = (*so->so_proto->pr_ctloutput)(PRCO_GETOPT, so,
> level, optname, m);
> - NET_UNLOCK(s);
> + sounlock(s);
> if (error) {
> m_free(m);
> return (error);
> @@ -1849,10 +1848,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);
> + s = solock(so);
> error = (*so->so_proto->pr_ctloutput)
> (PRCO_GETOPT, so, level, optname, m);
> - NET_UNLOCK(s);
> + sounlock(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 13 Feb 2017 09:29:25 -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();
> + soassertlocked(head);
>
> if (mclpools[0].pr_nout > mclpools[0].pr_hardlimit * 95 / 100)
> return (NULL);
> @@ -267,16 +268,52 @@ socantrcvmore(struct socket *so)
> sorwakeup(so);
> }
>
> +int
> +solock(struct socket *so)
> +{
> + int s;
> +
> + if (so->so_proto->pr_domain->dom_family != PF_LOCAL)
> + NET_LOCK(s);
> + else
> + s = -42;
> +
> + return (s);
> +}
> +
> +void
> +sounlock(int s)
> +{
> + if (s != -42)
> + NET_UNLOCK(s);
> +}
> +
> +void
> +soassertlocked(struct socket *so)
> +{
> + if (so->so_proto->pr_domain->dom_family != PF_LOCAL)
> + NET_ASSERT_LOCKED();
> +}
> +
> +int
> +sosleep(struct socket *so, void *ident, int prio, const char *wmesg, int
> timo)
> +{
> + if (so->so_proto->pr_domain->dom_family != 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();
> + soassertlocked(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 +375,7 @@ sbunlock(struct sockbuf *sb)
> void
> sowakeup(struct socket *so, struct sockbuf *sb)
> {
> - NET_ASSERT_LOCKED();
> + soassertlocked(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.149
> diff -u -p -r1.149 uipc_syscalls.c
> --- kern/uipc_syscalls.c 11 Feb 2017 19:51:06 -0000 1.149
> +++ kern/uipc_syscalls.c 13 Feb 2017 09:30:07 -0000
> @@ -285,9 +285,9 @@ doaccept(struct proc *p, int sock, struc
> }
>
> nam = m_get(M_WAIT, MT_SONAME);
> -
> - NET_LOCK(s);
> +
> head = headfp->f_data;
> + s = solock(head);
> if (isdnssocket(head) || (head->so_options & SO_ACCEPTCONN) == 0) {
> error = EINVAL;
> goto out;
> @@ -304,8 +304,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;
> }
> @@ -342,7 +342,7 @@ doaccept(struct proc *p, int sock, struc
> *retval = tmpfd;
> }
> out:
> - NET_UNLOCK(s);
> + sounlock(s);
> m_freem(nam);
> if (error) {
> fdplock(fdp);
> @@ -406,9 +406,9 @@ sys_connect(struct proc *p, void *v, reg
> m_freem(nam);
> return (EINPROGRESS);
> }
> - NET_LOCK(s);
> + s = solock(so);
> 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)
> @@ -420,7 +420,7 @@ sys_connect(struct proc *p, void *v, reg
> error = so->so_error;
> so->so_error = 0;
> }
> - NET_UNLOCK(s);
> + sounlock(s);
> bad:
> if (!interrupted)
> so->so_state &= ~SS_ISCONNECTING;
> @@ -1044,9 +1044,9 @@ sys_getsockname(struct proc *p, void *v,
> if (error)
> goto bad;
> m = m_getclr(M_WAIT, MT_SONAME);
> - NET_LOCK(s);
> + s = solock(so);
> error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0, p);
> - NET_UNLOCK(s);
> + sounlock(s);
> if (error)
> goto bad;
> error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
> @@ -1087,9 +1087,9 @@ sys_getpeername(struct proc *p, void *v,
> if (error)
> goto bad;
> m = m_getclr(M_WAIT, MT_SONAME);
> - NET_LOCK(s);
> + s = solock(so);
> error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0, p);
> - NET_UNLOCK(s);
> + sounlock(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.115
> diff -u -p -r1.115 uipc_usrreq.c
> --- kern/uipc_usrreq.c 9 Feb 2017 11:18:55 -0000 1.115
> +++ kern/uipc_usrreq.c 13 Feb 2017 09:27:32 -0000
> @@ -121,6 +121,9 @@ uipc_usrreq(struct socket *so, int req,
> error = EINVAL;
> goto release;
> }
> +
> + NET_ASSERT_UNLOCKED();
> +
> switch (req) {
>
> case PRU_ATTACH:
> @@ -132,17 +135,11 @@ uipc_usrreq(struct socket *so, int req,
> break;
>
> case PRU_DETACH:
> - /* XXXSMP breaks atomicity */
> - rw_exit_write(&netlock);
> unp_detach(unp);
> - rw_enter_write(&netlock);
> break;
>
> case PRU_BIND:
> - /* XXXSMP breaks atomicity */
> - rw_exit_write(&netlock);
> error = unp_bind(unp, nam, p);
> - rw_enter_write(&netlock);
> break;
>
> case PRU_LISTEN:
> @@ -151,10 +148,7 @@ uipc_usrreq(struct socket *so, int req,
> break;
>
> case PRU_CONNECT:
> - /* XXXSMP breaks atomicity */
> - rw_exit_write(&netlock);
> error = unp_connect(so, nam, p);
> - rw_enter_write(&netlock);
> break;
>
> case PRU_CONNECT2:
> @@ -222,10 +216,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 {
> @@ -398,8 +389,6 @@ unp_detach(struct unpcb *unp)
> {
> struct vnode *vp;
>
> - NET_ASSERT_UNLOCKED();
> -
> LIST_REMOVE(unp, unp_link);
> if (unp->unp_vnode) {
> unp->unp_vnode->v_socket = NULL;
> @@ -411,10 +400,7 @@ unp_detach(struct unpcb *unp)
> unp_disconnect(unp);
> while (!SLIST_EMPTY(&unp->unp_refs))
> unp_drop(SLIST_FIRST(&unp->unp_refs), ECONNRESET);
> - /* XXXSMP The assert is wrong */
> - rw_enter_write(&netlock);
> soisdisconnected(unp->unp_socket);
> - rw_exit_write(&netlock);
> unp->unp_socket->so_pcb = NULL;
> m_freem(unp->unp_addr);
> free(unp, M_PCB, sizeof *unp);
> @@ -505,9 +491,7 @@ unp_connect(struct socket *so, struct mb
> struct socket *so2, *so3;
> struct unpcb *unp, *unp2, *unp3;
> struct nameidata nd;
> - int error, s;
> -
> - NET_ASSERT_UNLOCKED();
> + int error;
>
> if (soun->sun_family != AF_UNIX)
> return (EAFNOSUPPORT);
> @@ -539,12 +523,11 @@ unp_connect(struct socket *so, struct mb
> error = EPROTOTYPE;
> goto bad;
> }
> - NET_LOCK(s);
> if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
> if ((so2->so_options & SO_ACCEPTCONN) == 0 ||
> (so3 = sonewconn(so2, 0)) == 0) {
> error = ECONNREFUSED;
> - goto unlock;
> + goto bad;
> }
> unp = sotounpcb(so);
> unp2 = sotounpcb(so2);
> @@ -563,8 +546,6 @@ unp_connect(struct socket *so, struct mb
> }
> }
> error = unp_connect2(so, so2);
> -unlock:
> - NET_UNLOCK(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 13 Feb 2017 09:29:09 -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);
> @@ -317,6 +317,11 @@ void sowakeup(struct socket *so, struct
> void sorwakeup(struct socket *);
> void sowwakeup(struct socket *);
> int sockargs(struct mbuf **, const void *, size_t, int);
> +
> +int sosleep(struct socket *, void *, int, const char *, int);
> +int solock(struct socket *);
> +void sounlock(int);
> +void soassertlocked(struct socket *);
>
> int sendit(struct proc *, int, struct msghdr *, int, register_t *);
> int recvit(struct proc *, int, struct msghdr *, caddr_t,
> 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 13 Feb 2017 09:14:22 -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); \