The first one replaces malloc(9) related M_NOWAIT and M_WAITOK flags we
use with sblock() to wait for lock if not immediately available.

The second one proposed to use if the lock awaiting should be
uninterruptible. It affects on sblock() behaviour for this call, instead
of SB_NOINTR flag which globally changes sblock() behaviour for this
socket buffer.

The SBL_NOINTR flag should be used for SB_NOINTR use cases like within
sorflush(). With standalone sblock() the similar sblock() calls will be
expanded to more places, and the SB_NOINTR flag operations around
sblock() calls are unwanted. At least, they are inconsistent because
concurrent sblock() threads could override this flag and change locking
behaviour for each others. Currently, sorflush() doesn't clear SB_NOINTR
flag but this looks incorrect, because after sorflush() call the
soreceive() path for this socket becomes uninterruptible. This is not
visible, because the socket is not used after shutdown(2) for send and
receive data.

Please note, the existing SB_NOINTR flag logic kept as is.

Also, we don't expose M_WAITOK/M_NOWAIT flags passed to sblock(), so
this diff doesn't breaks ABI.

Index: sys/kern/uipc_socket.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.293
diff -u -p -r1.293 uipc_socket.c
--- sys/kern/uipc_socket.c      12 Dec 2022 08:30:22 -0000      1.293
+++ sys/kern/uipc_socket.c      21 Dec 2022 22:31:53 -0000
@@ -516,7 +516,7 @@ sodisconnect(struct socket *so)
 
 int m_getuio(struct mbuf **, int, long, struct uio *);
 
-#define        SBLOCKWAIT(f)   (((f) & MSG_DONTWAIT) ? M_NOWAIT : M_WAITOK)
+#define        SBLOCKWAIT(f)   (((f) & MSG_DONTWAIT) ? 0 : SBL_WAIT)
 /*
  * Send on a socket.
  * If send must go all at once and message is larger than
@@ -1209,9 +1209,8 @@ sorflush(struct socket *so)
        const struct protosw *pr = so->so_proto;
        int error;
 
-       sb->sb_flags |= SB_NOINTR;
-       error = sblock(so, sb, M_WAITOK);
-       /* with SB_NOINTR and M_WAITOK sblock() must not fail */
+       error = sblock(so, sb, SBL_WAIT | SBL_NOINTR);
+       /* with SBL_WAIT and SLB_NOINTR sblock() must not fail */
        KASSERT(error == 0);
        socantrcvmore(so);
        m = sb->sb_mb;
@@ -1275,7 +1274,7 @@ sosplice(struct socket *so, int fd, off_
        /* If no fd is given, unsplice by removing existing link. */
        if (fd < 0) {
                /* Lock receive buffer. */
-               if ((error = sblock(so, &so->so_rcv, M_WAITOK)) != 0) {
+               if ((error = sblock(so, &so->so_rcv, SBL_WAIT)) != 0) {
                        return (error);
                }
                if (so->so_sp->ssp_socket)
@@ -1308,10 +1307,10 @@ sosplice(struct socket *so, int fd, off_
        }
 
        /* Lock both receive and send buffer. */
-       if ((error = sblock(so, &so->so_rcv, M_WAITOK)) != 0) {
+       if ((error = sblock(so, &so->so_rcv, SBL_WAIT)) != 0) {
                goto frele;
        }
-       if ((error = sblock(so, &sosp->so_snd, M_WAITOK)) != 0) {
+       if ((error = sblock(so, &sosp->so_snd, SBL_WAIT)) != 0) {
                sbunlock(so, &so->so_rcv);
                goto frele;
        }
Index: sys/kern/uipc_socket2.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_socket2.c,v
retrieving revision 1.131
diff -u -p -r1.131 uipc_socket2.c
--- sys/kern/uipc_socket2.c     12 Dec 2022 08:30:22 -0000      1.131
+++ sys/kern/uipc_socket2.c     21 Dec 2022 22:31:54 -0000
@@ -494,9 +494,9 @@ sbwait(struct socket *so, struct sockbuf
 }
 
 int
-sblock(struct socket *so, struct sockbuf *sb, int wait)
+sblock(struct socket *so, struct sockbuf *sb, int flags)
 {
-       int error, prio = (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH;
+       int error, prio = PSOCK;
 
        soassertlocked(so);
 
@@ -504,8 +504,10 @@ sblock(struct socket *so, struct sockbuf
                sb->sb_flags |= SB_LOCK;
                return (0);
        }
-       if (wait & M_NOWAIT)
+       if ((flags & SBL_WAIT) == 0)
                return (EWOULDBLOCK);
+       if (!(flags & SBL_NOINTR || sb->sb_flags & SB_NOINTR))
+               prio |= PCATCH;
 
        while (sb->sb_flags & SB_LOCK) {
                sb->sb_flags |= SB_WANT;
Index: sys/sys/socketvar.h
===================================================================
RCS file: /cvs/src/sys/sys/socketvar.h,v
retrieving revision 1.114
diff -u -p -r1.114 socketvar.h
--- sys/sys/socketvar.h 12 Dec 2022 08:30:22 -0000      1.114
+++ sys/sys/socketvar.h 21 Dec 2022 22:31:54 -0000
@@ -265,6 +265,12 @@ sbfree(struct socket *so, struct sockbuf
 }
 
 /*
+ * Flags to sblock()
+ */
+#define SBL_WAIT       0x01    /* Wait if lock not immidiately available. */
+#define SBL_NOINTR     0x02    /* Enforce non-interruptible sleep. */
+
+/*
  * Set lock on sockbuf sb; sleep if lock is already held.
  * Unless SB_NOINTR is set on sockbuf, sleep is interruptible.
  * Returns error without lock if sleep is interrupted.

Reply via email to