Like many places, tcp_splice_sock_handler() needs to handle EAGAIN
specially, in this case for both of its splice() calls. Unfortunately it
tests for EAGAIN some time after those calls. In between there has been
at least a flow_trace() which could have clobbered errno. Move the test on
errno closer to the relevant system calls to avoid this problem.
Signed-off-by: David Gibson
---
tcp_splice.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/tcp_splice.c b/tcp_splice.c
index 7c3b56f9..60455d64 100644
--- a/tcp_splice.c
+++ b/tcp_splice.c
@@ -526,13 +526,15 @@ retry:
c->tcp.pipe_size,
SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
while (readlen < 0 && errno == EINTR);
+
+ if (readlen < 0 && errno != EAGAIN)
+ goto close;
+
flow_trace(conn, "%zi from read-side call", readlen);
- if (readlen < 0) {
- if (errno != EAGAIN)
- goto close;
- } else if (!readlen) {
+
+ if (!readlen) {
eof = 1;
- } else {
+ } else if (readlen > 0) {
never_read = 0;
if (readlen >= (long)c->tcp.pipe_size * 90 / 100)
@@ -549,6 +551,9 @@ retry:
SPLICE_F_MOVE | more | SPLICE_F_NONBLOCK);
while (written < 0 && errno == EINTR);
+ if (written < 0 && errno != EAGAIN)
+ goto close;
+
flow_trace(conn, "%zi from write-side call (passed %zi)",
written, c->tcp.pipe_size);
@@ -580,9 +585,6 @@ retry:
conn->written[fromsidei] += written > 0 ? written : 0;
if (written < 0) {
- if (errno != EAGAIN)
- goto close;
-
if (conn->read[fromsidei] == conn->written[fromsidei])
break;
--
2.49.0