]> www.infradead.org Git - users/dwmw2/linux.git/commit
net/smc: check sndbuf_space again after NOSPACE flag is set in smc_poll
authorGuangguan Wang <guangguan.wang@linux.alibaba.com>
Wed, 11 Dec 2024 09:21:17 +0000 (17:21 +0800)
committerDavid S. Miller <davem@davemloft.net>
Sun, 15 Dec 2024 12:34:59 +0000 (12:34 +0000)
commit679e9ddcf90dbdf98aaaa71a492454654b627bcb
treedb95e74a8d3f7189fcb46971758cf9a44093185f
parent2b33eb8f1b3e8c2f87cfdbc8cc117f6bdfabc6ec
net/smc: check sndbuf_space again after NOSPACE flag is set in smc_poll

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 check sndbuf_space again after NOSPACE flag is set to break the race.

Fixes: 8dce2786a290 ("net/smc: smc_poll improvements")
Signed-off-by: Guangguan Wang <guangguan.wang@linux.alibaba.com>
Suggested-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/smc/af_smc.c