Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ksmbd: server: avoid busy polling in accept loop

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. During teardown, call shutdown() on the listening socket so that
accept() returns -EINVAL and the thread exits cleanly.

The socket release mutex is redundant because kthread_stop() blocks until
the listener thread returns, guaranteeing safe teardown ordering.

Also remove sk_rcvtimeo and sk_sndtimeo assignments, which only caused
accept() to return -EAGAIN prematurely.

Signed-off-by: Qingfang Deng <dqfext@gmail.com>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>

authored by

Qingfang Deng and committed by
Steve French
3316a8fc 5003ad71

+6 -35
+6 -35
fs/smb/server/transport_tcp.c
··· 22 22 struct socket *ksmbd_socket; 23 23 struct list_head entry; 24 24 char *name; 25 - struct mutex sock_release_lock; 26 25 int state; 27 26 }; 28 27 ··· 53 54 static inline void ksmbd_tcp_reuseaddr(struct socket *sock) 54 55 { 55 56 sock_set_reuseaddr(sock->sk); 56 - } 57 - 58 - static inline void ksmbd_tcp_rcv_timeout(struct socket *sock, s64 secs) 59 - { 60 - if (secs && secs < MAX_SCHEDULE_TIMEOUT / HZ - 1) 61 - WRITE_ONCE(sock->sk->sk_rcvtimeo, secs * HZ); 62 - else 63 - WRITE_ONCE(sock->sk->sk_rcvtimeo, MAX_SCHEDULE_TIMEOUT); 64 - } 65 - 66 - static inline void ksmbd_tcp_snd_timeout(struct socket *sock, s64 secs) 67 - { 68 - sock_set_sndtimeo(sock->sk, secs); 69 57 } 70 58 71 59 static struct tcp_transport *alloc_transport(struct socket *client_sk) ··· 222 236 unsigned int max_ip_conns; 223 237 224 238 while (!kthread_should_stop()) { 225 - mutex_lock(&iface->sock_release_lock); 226 239 if (!iface->ksmbd_socket) { 227 - mutex_unlock(&iface->sock_release_lock); 228 240 break; 229 241 } 230 - ret = kernel_accept(iface->ksmbd_socket, &client_sk, 231 - SOCK_NONBLOCK); 232 - mutex_unlock(&iface->sock_release_lock); 233 - if (ret) { 234 - if (ret == -EAGAIN) 235 - /* check for new connections every 100 msecs */ 236 - schedule_timeout_interruptible(HZ / 10); 242 + ret = kernel_accept(iface->ksmbd_socket, &client_sk, 0); 243 + if (ret == -EINVAL) 244 + break; 245 + if (ret) 237 246 continue; 238 - } 239 247 240 248 if (!server_conf.max_ip_connections) 241 249 goto skip_max_ip_conns_limit; ··· 438 458 if (!ksmbd_socket) 439 459 return; 440 460 441 - /* set zero to timeout */ 442 - ksmbd_tcp_rcv_timeout(ksmbd_socket, 0); 443 - ksmbd_tcp_snd_timeout(ksmbd_socket, 0); 444 - 445 461 ret = kernel_sock_shutdown(ksmbd_socket, SHUT_RDWR); 446 462 if (ret) 447 463 pr_err("Failed to shutdown socket: %d\n", ret); ··· 508 532 goto out_error; 509 533 } 510 534 511 - ksmbd_socket->sk->sk_rcvtimeo = KSMBD_TCP_RECV_TIMEOUT; 512 - ksmbd_socket->sk->sk_sndtimeo = KSMBD_TCP_SEND_TIMEOUT; 513 - 514 535 ret = kernel_listen(ksmbd_socket, KSMBD_SOCKET_BACKLOG); 515 536 if (ret) { 516 537 pr_err("Port listen() error: %d\n", ret); ··· 577 604 if (iface && iface->state == IFACE_STATE_CONFIGURED) { 578 605 ksmbd_debug(CONN, "netdev-down event: netdev(%s) is going down\n", 579 606 iface->name); 607 + kernel_sock_shutdown(iface->ksmbd_socket, SHUT_RDWR); 580 608 tcp_stop_kthread(iface->ksmbd_kthread); 581 609 iface->ksmbd_kthread = NULL; 582 - mutex_lock(&iface->sock_release_lock); 583 - tcp_destroy_socket(iface->ksmbd_socket); 610 + sock_release(iface->ksmbd_socket); 584 611 iface->ksmbd_socket = NULL; 585 - mutex_unlock(&iface->sock_release_lock); 586 612 587 613 iface->state = IFACE_STATE_DOWN; 588 614 break; ··· 644 672 iface->name = ifname; 645 673 iface->state = IFACE_STATE_DOWN; 646 674 list_add(&iface->entry, &iface_list); 647 - mutex_init(&iface->sock_release_lock); 648 675 return iface; 649 676 } 650 677