From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: passt.top; dkim=pass (2048-bit key; secure) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.a=rsa-sha256 header.s=202602 header.b=JC/QQt5P; dkim-atps=neutral Received: from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by passt.top (Postfix) with ESMTPS id 825435A0619 for ; Thu, 28 May 2026 07:02:24 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202602; t=1779944535; bh=lrwcc634DB3xH+8QBcNekNgOeCWQTM9BjVCOi7/EKkE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JC/QQt5Ps8y09FARwlnvrFhtvUBTLgK2e1T5I/lV+aHvy9gWtIw+GD+N9XrbA35xY IJFySBdiZKkM6KMTuHpKMHXWEumeNadtN7WpC6TAJ01y59x6BbIkKRl3JPdkXZUpCA 1WV8e8V6NtI/TX7Le/8KES2vjlSL6vN/R+Z3RwsjtUWhVXyIhkwVs/sddaXaz0znnP G/By7qvmTBAhsHXXDNQznGEsKz3tfnWdnMEss7+P7Z/gMst1qLZRLUSORaAeby/AQS 79LK8qCGM5nV/iImkO4YhP77e2R/FnXgIkwEBHKVYVcLPu8JRSthm28fhuGE5BxLPe vmVFUpIna2d7A== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4gQvVb0hRtz4wLv; Thu, 28 May 2026 15:02:15 +1000 (AEST) From: David Gibson To: passt-dev@passt.top, Stefano Brivio Subject: [PATCH 6/8] tcp_splice: Simplify / correct OUT_WAIT flag handling Date: Thu, 28 May 2026 15:02:11 +1000 Message-ID: <20260528050213.679685-7-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260528050213.679685-1-david@gibson.dropbear.id.au> References: <20260528050213.679685-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: PTE2LE6UH3JQLDLRBK5QHVYR7NHDY6GR X-Message-ID-Hash: PTE2LE6UH3JQLDLRBK5QHVYR7NHDY6GR X-MailFrom: dgibson@gandalf.ozlabs.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: David Gibson X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: We set the OUT_WAIT flag if we stop forwarding due to EAGAIN, but there's still data in the pipe. That ensures we wake up when the output socket has room to drain the pipe into. We clear the OUT_WAIT flag when we complete forwarding on an EPOLLOUT event, but that's not quite right. Even though it's called on an EPOLLOUT, tcp_splice_forward() could, in principle empty the pipe, but also read enough new data from the other side to fill it again. That would set OUT_WAIT internally, but it would be cleared after returning meaning we could miss a necessary wakeup. The condition on whether we need write side wakeups is actually fairly simple: we need them if and only if we return to the main loop with data in the pipe. Maintain that in a single place - right after we exit the forwarding loop in tcp_splice_forward(). Signed-off-by: David Gibson --- tcp_splice.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tcp_splice.c b/tcp_splice.c index 42902684..5f412584 100644 --- a/tcp_splice.c +++ b/tcp_splice.c @@ -531,19 +531,22 @@ static int tcp_splice_forward(struct ctx *c, conn->pending[fromsidei] += readlen > 0 ? readlen : 0; conn->pending[fromsidei] -= written > 0 ? written : 0; - if (written < 0) { - if (!conn->pending[fromsidei]) - break; - - conn_event(conn, OUT_WAIT(!fromsidei)); + if (written < 0) break; - } if (conn->events & FIN_RCVD(fromsidei) && !conn->pending[fromsidei]) break; } + /* We need write-side wakeups if and only if we have data in the pipe to + * drain. + */ + if (conn->pending[fromsidei]) + conn_event(conn, OUT_WAIT(!fromsidei)); + else + conn_event(conn, ~OUT_WAIT(!fromsidei)); + if ((conn->events & FIN_RCVD(fromsidei)) && !(conn->events & FIN_SENT(!fromsidei)) && !conn->pending[fromsidei]) { @@ -606,7 +609,6 @@ void tcp_splice_sock_handler(struct ctx *c, union epoll_ref ref, if (events & EPOLLOUT) { if (tcp_splice_forward(c, conn, !evsidei, now)) goto reset; - conn_event(conn, ~OUT_WAIT(evsidei)); } if (events & (EPOLLIN | EPOLLRDHUP)) { -- 2.54.0