Re: [PATCH] ksmbd: server: avoid busy polling in accept loop

From: Stefan Metzmacher
Date: Tue Nov 11 2025 - 02:23:08 EST


Am 11.11.25 um 07:55 schrieb Stefan Metzmacher:
Am 30.10.25 um 07:47 schrieb Qingfang Deng:
The ksmbd listener thread was using busy waiting on a listening socket by
calling kernel_accept() with SOCK_NONBLOCK and retrying every 100ms on
-EAGAIN. Since this thread is dedicated to accepting new connections,
there is no need for non-blocking mode.

Switch to a blocking accept() call instead, allowing the thread to sleep
until a new connection arrives. This avoids unnecessary wakeups and CPU
usage.

Also remove:
   - TCP_NODELAY, which has no effect on a listening socket.
   - sk_rcvtimeo and sk_sndtimeo assignments, which only caused accept()
     to return -EAGAIN prematurely.

Aren't these inherited to the accepted sockets?
So we need to apply them to the accepted sockets now
instead of dropping them completely?

Actually the timeouts are added to the client connection,
but not the TCP_NODELAY.

But looking at it more detailed I'm wondering if this might
introduce a deadlock.

We have this in the accepting thread:

while (!kthread_should_stop()) {
mutex_lock(&iface->sock_release_lock);
if (!iface->ksmbd_socket) {
mutex_unlock(&iface->sock_release_lock);
break;
}
ret = kernel_accept(iface->ksmbd_socket, &client_sk, 0);
mutex_unlock(&iface->sock_release_lock);
if (ret)
continue;


And in the stopping code this:

case NETDEV_DOWN:
iface = ksmbd_find_netdev_name_iface_list(netdev->name);
if (iface && iface->state == IFACE_STATE_CONFIGURED) {
ksmbd_debug(CONN, "netdev-down event: netdev(%s) is going down\n",
iface->name);
tcp_stop_kthread(iface->ksmbd_kthread);
iface->ksmbd_kthread = NULL;
mutex_lock(&iface->sock_release_lock);
tcp_destroy_socket(iface->ksmbd_socket);
iface->ksmbd_socket = NULL;
mutex_unlock(&iface->sock_release_lock);

iface->state = IFACE_STATE_DOWN;
break;
}



I guess that now kernel_accept() call waits forever holding iface->sock_release_lock
and tcp_stop_kthread(iface->ksmbd_kthread); doesn't have any impact anymore
as we may never reach kthread_should_stop() anymore.

We may want to do a kernel_sock_shutdown(ksmbd_socket, SHUT_RDWR) after
tcp_stop_kthread(iface->ksmbd_kthread); but before mutex_lock(&iface->sock_release_lock);
so that kernel_accept() hopefully returns directly.
And we only call sock_release(ksmbd_socket); under the iface->sock_release_lock mutex.

metze