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.  I think that we still need to do it if we want
to unlock the syscalls.  But I'd argue that having something that work
and allow people working on the forwarding path to make progress is
good, even if it is a hack.  That said I'm open to better solutions.

Here's an updated diff that should fix all your previous comments and
those of millert@.  I also change the SOCKET_LOCK() macros into real
functions to stop polluting <sys/systm.h>.  It also find it easier to
follow the lock ordering between sockerbuffer and NET_LOCK().

Comments, oks?

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);                                        \

Reply via email to