From 987ac99098480d403b8aa922736c239a4aa6de1b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 28 May 2026 15:02:09 +1000 Subject: tcp_splice: Remove goto from forwarding loop The forwarding look in tcp_splice_forward() has a retry label that we goto in some cases. However, the only difference between a 'goto retry' and a 'continue' is that the 'continue' will reset the 'more' variable to 0. The fist goto retry only occurs if never_read is set, which can only be the case if we never changed 'more' in the first place, so is strictly equivalent to a continue. In the second case, 'more' can be set though. 'more' is set by a heuristic that if we're able to read most of a pipe's worth of data at once, there's probably more coming, so we should prepare the write-side for that. However, on a goto retry we have a new read side splice. If this time we *don't* get most of a pipe's worth of data, that suggests that contrary to expectations from the previous loop we have now temporarily run out of input data and so SPLICE_F_MORE is no longer a good guess for the next write side splice(). In other words, the second read-splice() gives us better data for the heuristic than keeping our guess from the first one, so resetting 'more' is valuable. So, we could replace both gotos with continues. But they're already at the end the loop body, so a continue is a no-op. Just remove them. That, in turn removes the need for the never_read variable. Signed-off-by: David Gibson Signed-off-by: Stefano Brivio --- tcp_splice.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/tcp_splice.c b/tcp_splice.c index 943dc21..8c8e3bb 100644 --- a/tcp_splice.c +++ b/tcp_splice.c @@ -476,13 +476,11 @@ static int tcp_splice_forward(struct ctx *c, { uint8_t lowat_set_flag = RCVLOWAT_SET(fromsidei); uint8_t lowat_act_flag = RCVLOWAT_ACT(fromsidei); - int never_read = 1; while (1) { ssize_t readlen, written; int more = 0; -retry: do readlen = splice(conn->s[fromsidei], NULL, conn->pipe[fromsidei][1], NULL, @@ -502,8 +500,6 @@ retry: if (!readlen) { conn_event(conn, FIN_RCVD(fromsidei)); } else if (readlen > 0) { - never_read = 0; - if (readlen >= (long)c->tcp.pipe_size * 90 / 100) more = SPLICE_F_MORE; @@ -546,13 +542,6 @@ retry: if (conn->events & FIN_RCVD(fromsidei) && !conn->pending[fromsidei]) break; - - if (never_read && written == (long)(c->tcp.pipe_size)) - goto retry; - - if (!never_read && written > 0 && - written < conn->pending[fromsidei]) - goto retry; } if (!conn->pending[fromsidei] && -- cgit v1.2.3