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.