• Tony Lu's avatar
    net/smc: Ensure the active closing peer first closes clcsock · 606a63c9
    Tony Lu authored
    The side that actively closed socket, it's clcsock doesn't enter
    TIME_WAIT state, but the passive side does it. It should show the same
    behavior as TCP sockets.
    
    Consider this, when client actively closes the socket, the clcsock in
    server enters TIME_WAIT state, which means the address is occupied and
    won't be reused before TIME_WAIT dismissing. If we restarted server, the
    service would be unavailable for a long time.
    
    To solve this issue, shutdown the clcsock in [A], perform the TCP active
    close progress first, before the passive closed side closing it. So that
    the actively closed side enters TIME_WAIT, not the passive one.
    
    Client                                            |  Server
    close() // client actively close                  |
      smc_release()                                   |
          smc_close_active() // PEERCLOSEWAIT1        |
              smc_close_final() // abort or closed = 1|
                  smc_cdc_get_slot_and_msg_send()     |
              [A]                                     |
                                                      |smc_cdc_msg_recv_action() // ACTIVE
                                                      |  queue_work(smc_close_wq, &conn->close_work)
                                                      |    smc_close_passive_work() // PROCESSABORT or APPCLOSEWAIT1
                                                      |      smc_close_passive_abort_received() // only in abort
                                                      |
                                                      |close() // server recv zero, close
                                                      |  smc_release() // PROCESSABORT or APPCLOSEWAIT1
                                                      |    smc_close_active()
                                                      |      smc_close_abort() or smc_close_final() // CLOSED
                                                      |        smc_cdc_get_slot_and_msg_send() // abort or closed = 1
    smc_cdc_msg_recv_action()                         |    smc_clcsock_release()
      queue_work(smc_close_wq, &conn->close_work)     |      sock_release(tcp) // actively close clc, enter TIME_WAIT
        smc_close_passive_work() // PEERCLOSEWAIT1    |    smc_conn_free()
          smc_close_passive_abort_received() // CLOSED|
          smc_conn_free()                             |
          smc_clcsock_release()                       |
            sock_release(tcp) // passive close clc    |
    
    Link: https://www.spinics.net/lists/netdev/msg780407.html
    Fixes: b38d7324 ("smc: socket closing and linkgroup cleanup")
    Signed-off-by: default avatarTony Lu <tonylu@linux.alibaba.com>
    Reviewed-by: default avatarWen Gu <guwen@linux.alibaba.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    606a63c9
smc_close.c 12.4 KB