When application sending data more than sndbuf_space, there have chances application will sleep in epoll_wait, and will never be wakeup again. This is caused by a race between smc_poll and smc_cdc_tx_handler. application tasklet smc_tx_sendmsg(len > sndbuf_space) | epoll_wait for EPOLL_OUT,timeout=0 | smc_poll | if (!smc->conn.sndbuf_space) | | smc_cdc_tx_handler | atomic_add sndbuf_space | smc_tx_sndbuf_nonfull | if (!test_bit SOCK_NOSPACE) | do not sk_write_space; set_bit SOCK_NOSPACE; | return mask=0; | Application will sleep in epoll_wait as smc_poll returns 0. And smc_cdc_tx_handler will not call sk_write_space because the SOCK_NOSPACE has not be set. If there is no inflight cdc msg, sk_write_space will not be called any more, and application will sleep in epoll_wait forever. So set SOCK_NOSPACE when send_remaining but no sndbuf_space left in smc_tx_sendmsg, to ensure call sk_write_space in smc_cdc_tx_handler even when the above race happens. Fixes: 6889b36da78a ("net/smc: don't wait for send buffer space when data was already sent") Signed-off-by: Guangguan Wang <guangguan.wang@xxxxxxxxxxxxxxxxx> Reviewed-by: Wen Gu <guwen@xxxxxxxxxxxxxxxxx> Reviewed-by: D. Wythe <alibuda@xxxxxxxxxxxxxxxxx> --- net/smc/smc_tx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/smc/smc_tx.c b/net/smc/smc_tx.c index 214ac3cbcf9a..60cfec8eb255 100644 --- a/net/smc/smc_tx.c +++ b/net/smc/smc_tx.c @@ -222,8 +222,11 @@ int smc_tx_sendmsg(struct smc_sock *smc, struct msghdr *msg, size_t len) conn->local_tx_ctrl.prod_flags.urg_data_pending = 1; if (!atomic_read(&conn->sndbuf_space) || conn->urg_tx_pend) { - if (send_done) + if (send_done) { + sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk); + set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); return send_done; + } rc = smc_tx_wait(smc, msg->msg_flags); if (rc) goto out_err; -- 2.24.3 (Apple Git-128)