diff options
author | Stefano Brivio <sbrivio@redhat.com> | 2025-02-16 08:16:33 +0100 |
---|---|---|
committer | Stefano Brivio <sbrivio@redhat.com> | 2025-02-17 08:27:30 +0100 |
commit | 667caa09c6d46d937b3076254176eded262b3eca (patch) | |
tree | fc8cfbf3de22a02a7055a1d6ec742d62721e78cf | |
parent | 7c33b1208632a9581d0ee7aabd1e0584a5d1fb20 (diff) | |
download | passt-667caa09c6d46d937b3076254176eded262b3eca.tar passt-667caa09c6d46d937b3076254176eded262b3eca.tar.gz passt-667caa09c6d46d937b3076254176eded262b3eca.tar.bz2 passt-667caa09c6d46d937b3076254176eded262b3eca.tar.lz passt-667caa09c6d46d937b3076254176eded262b3eca.tar.xz passt-667caa09c6d46d937b3076254176eded262b3eca.tar.zst passt-667caa09c6d46d937b3076254176eded262b3eca.zip |
tcp_splice: Don't wake up on input data if we can't write it anywhere
If we set the OUT_WAIT_* flag (waiting on EPOLLOUT) for a side of a
given flow, it means that we're blocked, waiting for the receiver to
actually receive data, with a full pipe.
In that case, if we keep EPOLLIN set for the socket on the other side
(our receiving side), we'll get into a loop such as:
41.0230: pasta: epoll event on connected spliced TCP socket 108 (events: 0x00000001)
41.0230: Flow 1 (TCP connection (spliced)): -1 from read-side call
41.0230: Flow 1 (TCP connection (spliced)): -1 from write-side call (passed 8192)
41.0230: Flow 1 (TCP connection (spliced)): event at tcp_splice_sock_handler:577
41.0230: pasta: epoll event on connected spliced TCP socket 108 (events: 0x00000001)
41.0230: Flow 1 (TCP connection (spliced)): -1 from read-side call
41.0230: Flow 1 (TCP connection (spliced)): -1 from write-side call (passed 8192)
41.0230: Flow 1 (TCP connection (spliced)): event at tcp_splice_sock_handler:577
leading to 100% CPU usage, of course.
Drop EPOLLIN on our receiving side as long when we're waiting for
output readiness on the other side.
Link: https://github.com/containers/podman/issues/23686#issuecomment-2661036584
Link: https://www.reddit.com/r/podman/comments/1iph50j/pasta_high_cpu_on_podman_rootless_container/
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
-rw-r--r-- | tcp_splice.c | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/tcp_splice.c b/tcp_splice.c index f1a9223..8a39a6f 100644 --- a/tcp_splice.c +++ b/tcp_splice.c @@ -131,8 +131,12 @@ static void tcp_splice_conn_epoll_events(uint16_t events, ev[1].events = EPOLLOUT; } - flow_foreach_sidei(sidei) - ev[sidei].events |= (events & OUT_WAIT(sidei)) ? EPOLLOUT : 0; + flow_foreach_sidei(sidei) { + if (events & OUT_WAIT(sidei)) { + ev[sidei].events |= EPOLLOUT; + ev[!sidei].events &= ~EPOLLIN; + } + } } /** |