summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurence Rowe <laurencerowe@gmail.com>2026-04-02 23:49:18 +0300
committerJakub Kicinski <kuba@kernel.org>2026-04-07 04:29:01 +0300
commit98f28d8d6e5a5ed058dd37854c19e9b3bae72eff (patch)
tree7e5f15a43efa854a405bdcf30e9ee1c113f609e8
parentc8eee00c0fef5f709b9114be432d7b3afebb4c0a (diff)
downloadlinux-98f28d8d6e5a5ed058dd37854c19e9b3bae72eff.tar.xz
vsock: avoid timeout for non-blocking accept() with empty backlog
A common pattern in epoll network servers is to eagerly accept all pending connections from the non-blocking listening socket after epoll_wait indicates the socket is ready by calling accept in a loop until EAGAIN is returned indicating that the backlog is empty. Scheduling a timeout for a non-blocking accept with an empty backlog meant AF_VSOCK sockets used by epoll network servers incurred hundreds of microseconds of additional latency per accept loop compared to AF_INET or AF_UNIX sockets. Signed-off-by: Laurence Rowe <laurencerowe@gmail.com> Reviewed-by: Bobby Eshleman <bobbyeshleman@meta.com> Reviewed-by: Stefano Garzarella <sgarzare@redhat.com> Link: https://patch.msgid.link/20260402204918.130395-1-laurencerowe@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--net/vmw_vsock/af_vsock.c15
1 files changed, 6 insertions, 9 deletions
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index e4756604d50b..b8794ea0f01e 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -1864,10 +1864,10 @@ static int vsock_accept(struct socket *sock, struct socket *newsock,
* created upon connection establishment.
*/
timeout = sock_rcvtimeo(listener, arg->flags & O_NONBLOCK);
- prepare_to_wait(sk_sleep(listener), &wait, TASK_INTERRUPTIBLE);
while ((connected = vsock_dequeue_accept(listener)) == NULL &&
- listener->sk_err == 0) {
+ listener->sk_err == 0 && timeout != 0) {
+ prepare_to_wait(sk_sleep(listener), &wait, TASK_INTERRUPTIBLE);
release_sock(listener);
timeout = schedule_timeout(timeout);
finish_wait(sk_sleep(listener), &wait);
@@ -1876,17 +1876,14 @@ static int vsock_accept(struct socket *sock, struct socket *newsock,
if (signal_pending(current)) {
err = sock_intr_errno(timeout);
goto out;
- } else if (timeout == 0) {
- err = -EAGAIN;
- goto out;
}
-
- prepare_to_wait(sk_sleep(listener), &wait, TASK_INTERRUPTIBLE);
}
- finish_wait(sk_sleep(listener), &wait);
- if (listener->sk_err)
+ if (listener->sk_err) {
err = -listener->sk_err;
+ } else if (!connected) {
+ err = -EAGAIN;
+ }
if (connected) {
sk_acceptq_removed(listener);