dtucker@ reported an interesting recursion [0]. His trace shows that
a thread executing unp_detach() MUST NOT be holding the NET_LOCK().

So here's a new version of my SOCKET_LOCK() diff that does exactly
that.  That means sofree(9) won't grab the NET_LOCK() for unix sockets
which makes uipc_usrreq() completely NET_LOCK() free.

Please test and report back.

[0] https://marc.info/?l=openbsd-misc&m=148661605114230&w=2

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   9 Feb 2017 11:21:44 -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(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(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  9 Feb 2017 11:21:44 -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;
                sofree(so);
-               NET_UNLOCK(s);
+               SOCKET_UNLOCK(s);
                return (error);
        }
-       NET_UNLOCK(s);
+       SOCKET_UNLOCK(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(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(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(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) {
@@ -232,7 +230,7 @@ soclose(struct socket *so)
        struct socket *so2;
        int s, error = 0;
 
-       NET_LOCK(s);
+       SOCKET_LOCK(so, s);
        if (so->so_options & SO_ACCEPTCONN) {
                while ((so2 = TAILQ_FIRST(&so->so_q0)) != NULL) {
                        (void) soqremque(so2, 0);
@@ -256,7 +254,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,7 +274,7 @@ discard:
                panic("soclose NOFDREF: so %p, so_type %d", so, so->so_type);
        so->so_state |= SS_NOFDREF;
        sofree(so);
-       NET_UNLOCK(s);
+       SOCKET_UNLOCK(s);
        return (error);
 }
 
@@ -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(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(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(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(s);
                        if (error)
                                goto out;
                        goto restart;
                }
-               NET_UNLOCK(s);
+               SOCKET_UNLOCK(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(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(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(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(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(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(s);
                goto restart;
        }
 
@@ -1004,7 +1000,7 @@ dontblock:
                *flagsp |= flags;
 release:
        sbunlock(&so->so_rcv);
-       NET_UNLOCK(s);
+       SOCKET_UNLOCK(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(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(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(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(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(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(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(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(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(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(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 9 Feb 2017 11:21:45 -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        9 Feb 2017 11:21:45 -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(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(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(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(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  9 Feb 2017 11:21:46 -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,12 @@ 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);
+               NET_ASSERT_UNLOCKED();
                error = unp_bind(unp, nam, p);
-               rw_enter_write(&netlock);
                break;
 
        case PRU_LISTEN:
@@ -151,10 +149,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 +217,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 {
@@ -397,9 +389,7 @@ void
 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 +401,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);
@@ -539,7 +526,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) {
@@ -564,7 +551,7 @@ unp_connect(struct socket *so, struct mb
        }
        error = unp_connect2(so, so2);
 unlock:
-       NET_UNLOCK(s);
+       SOCKET_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     9 Feb 2017 11:21:46 -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 9 Feb 2017 11:21:46 -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,27 @@ 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);                                            \
+       else                                                            \
+               s = -42;                                                \
+} while (0)
+
+#define        SOCKET_UNLOCK(s)                                                
\
+do {                                                                   \
+       if (s != -42)                                                   \
+               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 *);

Reply via email to