On Thu, Jul 04, 2019 at 10:47:22AM +0200, Claudio Jeker wrote:
> Would it be possible to use some #defined flags here instead of 1,2,3?
> Maybe use FREAD/FWRITE or define something new.

Makes code longer, but more readable.

ok?

bluhm

Index: sys/kern/uipc_socket.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.231
diff -u -p -r1.231 uipc_socket.c
--- sys/kern/uipc_socket.c      17 Dec 2018 16:46:59 -0000      1.231
+++ sys/kern/uipc_socket.c      4 Jul 2019 11:07:40 -0000
@@ -195,6 +195,8 @@ solisten(struct socket *so, int backlog)
        return (0);
 }

+#define SOSP_FREEING_READ      1
+#define SOSP_FREEING_WRITE     2
 void
 sofree(struct socket *so, int s)
 {
@@ -218,11 +220,20 @@ sofree(struct socket *so, int s)
        sigio_free(&so->so_sigio);
 #ifdef SOCKET_SPLICE
        if (so->so_sp) {
-               if (issplicedback(so))
-                       sounsplice(so->so_sp->ssp_soback, so,
-                           so->so_sp->ssp_soback != so);
-               if (isspliced(so))
-                       sounsplice(so, so->so_sp->ssp_socket, 0);
+               if (issplicedback(so)) {
+                       int freeing = SOSP_FREEING_WRITE;
+
+                       if (so->so_sp->ssp_soback == so)
+                               freeing |= SOSP_FREEING_READ;
+                       sounsplice(so->so_sp->ssp_soback, so, freeing);
+               }
+               if (isspliced(so)) {
+                       int freeing = SOSP_FREEING_READ;
+
+                       if (so == so->so_sp->ssp_socket)
+                               freeing |= SOSP_FREEING_WRITE;
+                       sounsplice(so, so->so_sp->ssp_socket, freeing);
+               }
        }
 #endif /* SOCKET_SPLICE */
        sbrelease(so, &so->so_snd);
@@ -1148,7 +1159,7 @@ sosplice(struct socket *so, int fd, off_
                        return (error);
                }
                if (so->so_sp->ssp_socket)
-                       sounsplice(so, so->so_sp->ssp_socket, 1);
+                       sounsplice(so, so->so_sp->ssp_socket, 0);
                sbunlock(so, &so->so_rcv);
                return (0);
        }
@@ -1227,7 +1238,7 @@ sosplice(struct socket *so, int fd, off_
 }

 void
-sounsplice(struct socket *so, struct socket *sosp, int wakeup)
+sounsplice(struct socket *so, struct socket *sosp, int freeing)
 {
        soassertlocked(so);

@@ -1236,8 +1247,11 @@ sounsplice(struct socket *so, struct soc
        sosp->so_snd.sb_flags &= ~SB_SPLICE;
        so->so_rcv.sb_flags &= ~SB_SPLICE;
        so->so_sp->ssp_socket = sosp->so_sp->ssp_soback = NULL;
-       if (wakeup && soreadable(so))
+       /* Do not wakeup a socket that is about to be freed. */
+       if ((freeing & SOSP_FREEING_READ) == 0 && soreadable(so))
                sorwakeup(so);
+       if ((freeing & SOSP_FREEING_WRITE) == 0 && sowriteable(sosp))
+               sowwakeup(sosp);
 }

 void
@@ -1249,7 +1263,7 @@ soidle(void *arg)
        s = solock(so);
        if (so->so_rcv.sb_flags & SB_SPLICE) {
                so->so_error = ETIMEDOUT;
-               sounsplice(so, so->so_sp->ssp_socket, 1);
+               sounsplice(so, so->so_sp->ssp_socket, 0);
        }
        sounlock(so, s);
 }
@@ -1574,7 +1588,7 @@ somove(struct socket *so, int wait)
                so->so_error = error;
        if (((so->so_state & SS_CANTRCVMORE) && so->so_rcv.sb_cc == 0) ||
            (sosp->so_state & SS_CANTSENDMORE) || maxreached || error) {
-               sounsplice(so, sosp, 1);
+               sounsplice(so, sosp, 0);
                return (0);
        }
        if (timerisset(&so->so_idletv))
@@ -1620,6 +1634,8 @@ sowwakeup(struct socket *so)
 #ifdef SOCKET_SPLICE
        if (so->so_snd.sb_flags & SB_SPLICE)
                task_add(sosplice_taskq, &so->so_sp->ssp_soback->so_splicetask);
+       if (issplicedback(so))
+               return;
 #endif
        sowakeup(so, &so->so_snd);
 }
Index: share/man/man9/sosplice.9
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/share/man/man9/sosplice.9,v
retrieving revision 1.9
diff -u -p -r1.9 sosplice.9
--- share/man/man9/sosplice.9   15 Aug 2018 12:10:49 -0000      1.9
+++ share/man/man9/sosplice.9   3 Jul 2019 21:42:34 -0000
@@ -206,10 +206,13 @@ will call
 to trigger the transfer when new data or buffer space is available.
 While socket splicing is active, any
 .Xr read 2
-from the source socket will block and the wakeup will not be delivered
-to the file descriptor.
-A read event or a socket error is signaled to userland after
-dissolving.
+from the source socket will block.
+Neither read nor write wakeups will be delivered to the file
+descriptors.
+After dissolving, a read event or a socket error is signaled to
+userland on the source socket.
+If space is available, a write event will be signaled on the drain
+socket.
 .Sh RETURN VALUES
 .Fn sosplice
 returns 0 on success and otherwise the error number.

Reply via email to