aboutgitcodebugslistschat
path: root/virtio.c
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2025-01-16 20:47:00 +0100
committerStefano Brivio <sbrivio@redhat.com>2025-01-16 21:15:33 +0100
commita8f4fc481ce3afbf48522a0af44d222d665b515e (patch)
treeecdac7c282ff7ffcafb81c8cfafa1c4d80591e29 /virtio.c
parentb8f573cdc222905c06f39625c0567da265a2e36e (diff)
downloadpasst-a8f4fc481ce3afbf48522a0af44d222d665b515e.tar
passt-a8f4fc481ce3afbf48522a0af44d222d665b515e.tar.gz
passt-a8f4fc481ce3afbf48522a0af44d222d665b515e.tar.bz2
passt-a8f4fc481ce3afbf48522a0af44d222d665b515e.tar.lz
passt-a8f4fc481ce3afbf48522a0af44d222d665b515e.tar.xz
passt-a8f4fc481ce3afbf48522a0af44d222d665b515e.tar.zst
passt-a8f4fc481ce3afbf48522a0af44d222d665b515e.zip
tcp: Mask EPOLLIN altogether if we're blocked waiting on an ACK from the guest
There are pretty much two cases of the (misnomer) STALLED: in one case, we could send more data to the guest if it becomes available, and in another case, we can't, because we filled the window. If, in this second case, we keep EPOLLIN enabled, but never read from the socket, we get short but CPU-annoying storms of EPOLLIN events, upon which we reschedule the ACK timeout handler, never read from the socket, go back to epoll_wait(), and so on: timerfd_settime(76, 0, {it_interval={tv_sec=0, tv_nsec=0}, it_value={tv_sec=2, tv_nsec=0}}, NULL) = 0 epoll_wait(3, [{events=EPOLLIN, data={u32=10497, u64=38654716161}}], 8, 1000) = 1 timerfd_settime(76, 0, {it_interval={tv_sec=0, tv_nsec=0}, it_value={tv_sec=2, tv_nsec=0}}, NULL) = 0 epoll_wait(3, [{events=EPOLLIN, data={u32=10497, u64=38654716161}}], 8, 1000) = 1 timerfd_settime(76, 0, {it_interval={tv_sec=0, tv_nsec=0}, it_value={tv_sec=2, tv_nsec=0}}, NULL) = 0 epoll_wait(3, [{events=EPOLLIN, data={u32=10497, u64=38654716161}}], 8, 1000) = 1 also known as: 29.1517: Flow 2 (TCP connection): timer expires in 2.000s 29.1517: Flow 2 (TCP connection): timer expires in 2.000s 29.1517: Flow 2 (TCP connection): timer expires in 2.000s which, for some reason, becomes very visible with muvm and aria2c downloading from a server nearby in parallel chunks. That's because EPOLLIN isn't cleared if we don't read from the socket, and even with EPOLLET, epoll_wait() will repeatedly wake us up until we actually read something. In this case, we don't want to subscribe to EPOLLIN at all: all we're waiting for is an ACK segment from the guest. Differentiate this case with a new connection flag, ACK_FROM_TAP_BLOCKS, which doesn't just indicate that we're waiting for an ACK from the guest (ACK_FROM_TAP_DUE), but also that we're blocked waiting for it. If this flag is set before we set STALLED, EPOLLIN will be masked while we set EPOLLET because of STALLED. Whenever we clear STALLED, we also clear this flag. This is definitely not elegant, but it's a minimal fix. We can probably simplify this at a later point by having a category of connection flags directly corresponding to epoll flags, and dropping STALLED altogether, or, perhaps, always using EPOLLET (but we need a mechanism to re-check sockets for pending data if we can't temporarily write to the guest). I suspect that this might also be implied in https://github.com/containers/podman/issues/23686, hence the Link: tag. It doesn't necessarily mean I'm fixing it (I can't reproduce that). Link: https://github.com/containers/podman/issues/23686 Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Diffstat (limited to 'virtio.c')
0 files changed, 0 insertions, 0 deletions