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

net/smc: simplify wait when closing listen socket

Closing of a listen socket wakes up kernel_accept() of
smc_tcp_listen_worker(), and then has to wait till smc_tcp_listen_worker()
gives up the internal clcsock. The wait logic introduced with
commit 127f49705823 ("net/smc: release clcsock from tcp_listen_worker")
might wait longer than necessary. This patch implements the idea to
implement the wait just with flush_work(), and gets rid of the extra
smc_close_wait_listen_clcsock() function.

Fixes: 127f49705823 ("net/smc: release clcsock from tcp_listen_worker")
Reported-by: Hans Wippel <hwippel@linux.vnet.ibm.com>
Signed-off-by: Ursula Braun <ubraun@linux.vnet.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Ursula Braun and committed by
David S. Miller
3d502067 cf55612a

+3 -26
-4
net/smc/af_smc.c
··· 978 978 lsmc->clcsock = NULL; 979 979 } 980 980 release_sock(lsk); 981 - /* no more listening, wake up smc_close_wait_listen_clcsock and 982 - * accept 983 - */ 984 - lsk->sk_state_change(lsk); 985 981 sock_put(&lsmc->sk); /* sock_hold in smc_listen */ 986 982 } 987 983
+3 -22
net/smc/smc_close.c
··· 30 30 smc_close_non_accepted(sk); 31 31 } 32 32 33 - static void smc_close_wait_listen_clcsock(struct smc_sock *smc) 34 - { 35 - DEFINE_WAIT_FUNC(wait, woken_wake_function); 36 - struct sock *sk = &smc->sk; 37 - signed long timeout; 38 - 39 - timeout = SMC_CLOSE_WAIT_LISTEN_CLCSOCK_TIME; 40 - add_wait_queue(sk_sleep(sk), &wait); 41 - do { 42 - release_sock(sk); 43 - if (smc->clcsock) 44 - timeout = wait_woken(&wait, TASK_UNINTERRUPTIBLE, 45 - timeout); 46 - sched_annotate_sleep(); 47 - lock_sock(sk); 48 - if (!smc->clcsock) 49 - break; 50 - } while (timeout); 51 - remove_wait_queue(sk_sleep(sk), &wait); 52 - } 53 - 54 33 /* wait for sndbuf data being transmitted */ 55 34 static void smc_close_stream_wait(struct smc_sock *smc, long timeout) 56 35 { ··· 183 204 rc = kernel_sock_shutdown(smc->clcsock, SHUT_RDWR); 184 205 /* wake up kernel_accept of smc_tcp_listen_worker */ 185 206 smc->clcsock->sk->sk_data_ready(smc->clcsock->sk); 186 - smc_close_wait_listen_clcsock(smc); 187 207 } 188 208 smc_close_cleanup_listen(sk); 209 + release_sock(sk); 210 + flush_work(&smc->tcp_listen_work); 211 + lock_sock(sk); 189 212 break; 190 213 case SMC_ACTIVE: 191 214 smc_close_stream_wait(smc, timeout);