diff options
| author | Stefan Metzmacher <metze@samba.org> | 2025-09-02 12:17:56 +0200 |
|---|---|---|
| committer | Steve French <stfrench@microsoft.com> | 2025-09-28 18:29:51 -0500 |
| commit | 1b128ec1c76dcf08b752b5f5268da813fea58a01 (patch) | |
| tree | 301c1f44dc2019f1a7d7880ed3a089a6819b63a8 | |
| parent | smb: client: let smbd_disconnect_rdma_connection() disable all work but disco... (diff) | |
| download | linux-1b128ec1c76dcf08b752b5f5268da813fea58a01.tar.gz linux-1b128ec1c76dcf08b752b5f5268da813fea58a01.zip | |
smb: client: let smbd_{destroy,disconnect_rdma_{work,connection}}() wake up all wait queues
This is important in order to let all waiters notice a broken connection.
We also go via smbd_disconnect_rdma_{work,connection}() for broken
connections.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Cc: linux-cifs@vger.kernel.org
Cc: samba-technical@lists.samba.org
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
| -rw-r--r-- | fs/smb/client/smbdirect.c | 52 |
1 files changed, 40 insertions, 12 deletions
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c index 155d69745adf..6d9c9e68c765 100644 --- a/fs/smb/client/smbdirect.c +++ b/fs/smb/client/smbdirect.c @@ -165,6 +165,21 @@ do { \ #define log_rdma_mr(level, fmt, args...) \ log_rdma(level, LOG_RDMA_MR, fmt, ##args) +static void smbd_disconnect_wake_up_all(struct smbdirect_socket *sc) +{ + /* + * Wake up all waiters in all wait queues + * in order to notice the broken connection. + */ + wake_up_all(&sc->status_wait); + wake_up_all(&sc->send_io.credits.wait_queue); + wake_up_all(&sc->send_io.pending.dec_wait_queue); + wake_up_all(&sc->send_io.pending.zero_wait_queue); + wake_up_all(&sc->recv_io.reassembly.wait_queue); + wake_up_all(&sc->mr_io.ready.wait_queue); + wake_up_all(&sc->mr_io.cleanup.wait_queue); +} + static void smbd_disconnect_rdma_work(struct work_struct *work) { struct smbdirect_socket *sc = @@ -216,6 +231,12 @@ static void smbd_disconnect_rdma_work(struct work_struct *work) case SMBDIRECT_SOCKET_DESTROYED: break; } + + /* + * Wake up all waiters in all wait queues + * in order to notice the broken connection. + */ + smbd_disconnect_wake_up_all(sc); } static void smbd_disconnect_rdma_connection(struct smbdirect_socket *sc) @@ -273,6 +294,12 @@ static void smbd_disconnect_rdma_connection(struct smbdirect_socket *sc) break; } + /* + * Wake up all waiters in all wait queues + * in order to notice the broken connection. + */ + smbd_disconnect_wake_up_all(sc); + queue_work(sc->workqueue, &sc->disconnect_work); } @@ -306,14 +333,14 @@ static int smbd_conn_upcall( log_rdma_event(ERR, "connecting failed event=%s\n", event_name); WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING); sc->status = SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED; - wake_up_all(&sc->status_wait); + smbd_disconnect_rdma_work(&sc->disconnect_work); break; case RDMA_CM_EVENT_ROUTE_ERROR: log_rdma_event(ERR, "connecting failed event=%s\n", event_name); WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING); sc->status = SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED; - wake_up_all(&sc->status_wait); + smbd_disconnect_rdma_work(&sc->disconnect_work); break; case RDMA_CM_EVENT_ESTABLISHED: @@ -408,7 +435,7 @@ static int smbd_conn_upcall( log_rdma_event(ERR, "connecting failed event=%s\n", event_name); WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING); sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_FAILED; - wake_up_all(&sc->status_wait); + smbd_disconnect_rdma_work(&sc->disconnect_work); break; case RDMA_CM_EVENT_DEVICE_REMOVAL: @@ -416,17 +443,10 @@ static int smbd_conn_upcall( /* This happens when we fail the negotiation */ if (sc->status == SMBDIRECT_SOCKET_NEGOTIATE_FAILED) { log_rdma_event(ERR, "event=%s during negotiation\n", event_name); - sc->status = SMBDIRECT_SOCKET_DISCONNECTED; - smbd_disconnect_rdma_work(&sc->disconnect_work); - wake_up_all(&sc->status_wait); - break; } sc->status = SMBDIRECT_SOCKET_DISCONNECTED; smbd_disconnect_rdma_work(&sc->disconnect_work); - wake_up_all(&sc->status_wait); - wake_up_all(&sc->recv_io.reassembly.wait_queue); - wake_up_all(&sc->send_io.credits.wait_queue); break; default: @@ -674,7 +694,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_NEGOTIATE_RUNNING); if (!negotiate_done) { sc->status = SMBDIRECT_SOCKET_NEGOTIATE_FAILED; - wake_up_all(&sc->status_wait); + smbd_disconnect_rdma_connection(sc); } else { sc->status = SMBDIRECT_SOCKET_CONNECTED; wake_up(&sc->status_wait); @@ -1569,6 +1589,15 @@ void smbd_destroy(struct TCP_Server_Info *server) sc->status == SMBDIRECT_SOCKET_DISCONNECTED); } + /* + * Wake up all waiters in all wait queues + * in order to notice the broken connection. + * + * Most likely this was already called via + * smbd_disconnect_rdma_work(), but call it again... + */ + smbd_disconnect_wake_up_all(sc); + log_rdma_event(INFO, "cancelling recv_io.posted.refill_work\n"); disable_work_sync(&sc->recv_io.posted.refill_work); @@ -1609,7 +1638,6 @@ void smbd_destroy(struct TCP_Server_Info *server) * path when sending data, and then release memory registrations. */ log_rdma_event(INFO, "freeing mr list\n"); - wake_up_all(&sc->mr_io.ready.wait_queue); while (atomic_read(&sc->mr_io.used.count)) { cifs_server_unlock(server); msleep(1000); |
