From 58dfba8a2d4eb6defc6e710196b053abdaf6cd79 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 8 Aug 2025 18:48:13 +0200 Subject: [PATCH] smb: client/smbdirect: replace SMBDIRECT_SOCKET_CONNECTING with more detailed states The process of reaching a functional connection represented by SMBDIRECT_SOCKET_CONNECTED, is more complex than using a single SMBDIRECT_SOCKET_CONNECTING state. This will allow us to remove a lot of special variables and completions in the following commits. Cc: Steve French Cc: Tom Talpey Cc: Long Li Acked-by: Namjae Jeon Cc: linux-cifs@vger.kernel.org Cc: samba-technical@lists.samba.org Signed-off-by: Stefan Metzmacher Signed-off-by: Steve French --- fs/smb/client/smbdirect.c | 73 ++++++++++++++++++++-- fs/smb/common/smbdirect/smbdirect_socket.h | 42 +++++++++++-- 2 files changed, 103 insertions(+), 12 deletions(-) diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c index 6480945c24592..e4abc1a9564ad 100644 --- a/fs/smb/client/smbdirect.c +++ b/fs/smb/client/smbdirect.c @@ -161,9 +161,36 @@ static void smbd_disconnect_rdma_work(struct work_struct *work) container_of(work, struct smbd_connection, disconnect_work); struct smbdirect_socket *sc = &info->socket; - if (sc->status == SMBDIRECT_SOCKET_CONNECTED) { + switch (sc->status) { + case SMBDIRECT_SOCKET_NEGOTIATE_NEEDED: + case SMBDIRECT_SOCKET_NEGOTIATE_RUNNING: + case SMBDIRECT_SOCKET_NEGOTIATE_FAILED: + case SMBDIRECT_SOCKET_CONNECTED: sc->status = SMBDIRECT_SOCKET_DISCONNECTING; rdma_disconnect(sc->rdma.cm_id); + break; + + case SMBDIRECT_SOCKET_CREATED: + case SMBDIRECT_SOCKET_RESOLVE_ADDR_NEEDED: + case SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING: + case SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED: + case SMBDIRECT_SOCKET_RESOLVE_ROUTE_NEEDED: + case SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING: + case SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED: + case SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED: + case SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING: + case SMBDIRECT_SOCKET_RDMA_CONNECT_FAILED: + /* + * rdma_connect() never reached + * RDMA_CM_EVENT_ESTABLISHED + */ + sc->status = SMBDIRECT_SOCKET_DISCONNECTED; + break; + + case SMBDIRECT_SOCKET_DISCONNECTING: + case SMBDIRECT_SOCKET_DISCONNECTED: + case SMBDIRECT_SOCKET_DESTROYED: + break; } } @@ -187,19 +214,31 @@ static int smbd_conn_upcall( switch (event->event) { case RDMA_CM_EVENT_ADDR_RESOLVED: + WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING); + sc->status = SMBDIRECT_SOCKET_RESOLVE_ROUTE_NEEDED; + info->ri_rc = 0; + complete(&info->ri_done); + break; + case RDMA_CM_EVENT_ROUTE_RESOLVED: + WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING); + sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED; info->ri_rc = 0; complete(&info->ri_done); break; case RDMA_CM_EVENT_ADDR_ERROR: 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; info->ri_rc = -EHOSTUNREACH; complete(&info->ri_done); 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; info->ri_rc = -ENETUNREACH; complete(&info->ri_done); break; @@ -285,7 +324,8 @@ static int smbd_conn_upcall( min_t(u8, info->responder_resources, peer_responder_resources); - sc->status = SMBDIRECT_SOCKET_CONNECTED; + WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING); + sc->status = SMBDIRECT_SOCKET_NEGOTIATE_NEEDED; wake_up_interruptible(&info->status_wait); break; @@ -293,7 +333,8 @@ static int smbd_conn_upcall( case RDMA_CM_EVENT_UNREACHABLE: case RDMA_CM_EVENT_REJECTED: log_rdma_event(ERR, "connecting failed event=%s\n", event_name); - sc->status = SMBDIRECT_SOCKET_DISCONNECTED; + WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING); + sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_FAILED; wake_up_interruptible(&info->status_wait); break; @@ -565,6 +606,12 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) info->negotiate_done = process_negotiation_response(response, wc->byte_len); put_receive_buffer(info, response); + WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_NEGOTIATE_RUNNING); + if (!info->negotiate_done) + sc->status = SMBDIRECT_SOCKET_NEGOTIATE_FAILED; + else + sc->status = SMBDIRECT_SOCKET_CONNECTED; + complete(&info->negotiate_completion); return; @@ -655,6 +702,7 @@ static struct rdma_cm_id *smbd_create_id( struct smbd_connection *info, struct sockaddr *dstaddr, int port) { + struct smbdirect_socket *sc = &info->socket; struct rdma_cm_id *id; int rc; __be16 *sport; @@ -677,6 +725,8 @@ static struct rdma_cm_id *smbd_create_id( init_completion(&info->ri_done); info->ri_rc = -ETIMEDOUT; + WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RESOLVE_ADDR_NEEDED); + sc->status = SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING; rc = rdma_resolve_addr(id, NULL, (struct sockaddr *)dstaddr, RDMA_RESOLVE_TIMEOUT); if (rc) { @@ -697,6 +747,8 @@ static struct rdma_cm_id *smbd_create_id( } info->ri_rc = -ETIMEDOUT; + WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RESOLVE_ROUTE_NEEDED); + sc->status = SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING; rc = rdma_resolve_route(id, RDMA_RESOLVE_TIMEOUT); if (rc) { log_rdma_event(ERR, "rdma_resolve_route() failed %i\n", rc); @@ -743,6 +795,9 @@ static int smbd_ia_open( struct smbdirect_socket *sc = &info->socket; int rc; + WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_CREATED); + sc->status = SMBDIRECT_SOCKET_RESOLVE_ADDR_NEEDED; + sc->rdma.cm_id = smbd_create_id(info, dstaddr, port); if (IS_ERR(sc->rdma.cm_id)) { rc = PTR_ERR(sc->rdma.cm_id); @@ -1184,6 +1239,9 @@ static int smbd_negotiate(struct smbd_connection *info) int rc; struct smbdirect_recv_io *response = get_receive_buffer(info); + WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_NEGOTIATE_NEEDED); + sc->status = SMBDIRECT_SOCKET_NEGOTIATE_RUNNING; + sc->recv_io.expected = SMBDIRECT_EXPECT_NEGOTIATE_REP; rc = smbd_post_recv(info, response); log_rdma_event(INFO, "smbd_post_recv rc=%d iov.addr=0x%llx iov.length=%u iov.lkey=0x%x\n", @@ -1643,7 +1701,7 @@ static struct smbd_connection *_smbd_get_connection( info->initiator_depth = 1; info->responder_resources = SMBD_CM_RESPONDER_RESOURCES; - sc->status = SMBDIRECT_SOCKET_CONNECTING; + sc->status = SMBDIRECT_SOCKET_CREATED; rc = smbd_ia_open(info, dstaddr, port); if (rc) { log_rdma_event(INFO, "smbd_ia_open rc=%d\n", rc); @@ -1755,6 +1813,9 @@ static struct smbd_connection *_smbd_get_connection( init_waitqueue_head(&info->status_wait); init_waitqueue_head(&sc->recv_io.reassembly.wait_queue); + + WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED); + sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING; rc = rdma_connect(sc->rdma.cm_id, &conn_param); if (rc) { log_rdma_event(ERR, "rdma_connect() failed with %i\n", rc); @@ -1763,10 +1824,10 @@ static struct smbd_connection *_smbd_get_connection( wait_event_interruptible_timeout( info->status_wait, - sc->status != SMBDIRECT_SOCKET_CONNECTING, + sc->status != SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING, msecs_to_jiffies(RDMA_RESOLVE_TIMEOUT)); - if (sc->status != SMBDIRECT_SOCKET_CONNECTED) { + if (sc->status != SMBDIRECT_SOCKET_NEGOTIATE_NEEDED) { log_rdma_event(ERR, "rdma_connect failed port=%d\n", port); goto rdma_connect_failed; } diff --git a/fs/smb/common/smbdirect/smbdirect_socket.h b/fs/smb/common/smbdirect/smbdirect_socket.h index 14f6e6d2035fb..ced8c9f20cf55 100644 --- a/fs/smb/common/smbdirect/smbdirect_socket.h +++ b/fs/smb/common/smbdirect/smbdirect_socket.h @@ -10,9 +10,19 @@ enum smbdirect_socket_status { SMBDIRECT_SOCKET_CREATED, - SMBDIRECT_SOCKET_CONNECTING, - SMBDIRECT_SOCKET_CONNECTED, + SMBDIRECT_SOCKET_RESOLVE_ADDR_NEEDED, + SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING, + SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED, + SMBDIRECT_SOCKET_RESOLVE_ROUTE_NEEDED, + SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING, + SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED, + SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED, + SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING, + SMBDIRECT_SOCKET_RDMA_CONNECT_FAILED, + SMBDIRECT_SOCKET_NEGOTIATE_NEEDED, + SMBDIRECT_SOCKET_NEGOTIATE_RUNNING, SMBDIRECT_SOCKET_NEGOTIATE_FAILED, + SMBDIRECT_SOCKET_CONNECTED, SMBDIRECT_SOCKET_DISCONNECTING, SMBDIRECT_SOCKET_DISCONNECTED, SMBDIRECT_SOCKET_DESTROYED @@ -24,12 +34,32 @@ const char *smbdirect_socket_status_string(enum smbdirect_socket_status status) switch (status) { case SMBDIRECT_SOCKET_CREATED: return "CREATED"; - case SMBDIRECT_SOCKET_CONNECTING: - return "CONNECTING"; - case SMBDIRECT_SOCKET_CONNECTED: - return "CONNECTED"; + case SMBDIRECT_SOCKET_RESOLVE_ADDR_NEEDED: + return "RESOLVE_ADDR_NEEDED"; + case SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING: + return "RESOLVE_ADDR_RUNNING"; + case SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED: + return "RESOLVE_ADDR_FAILED"; + case SMBDIRECT_SOCKET_RESOLVE_ROUTE_NEEDED: + return "RESOLVE_ROUTE_NEEDED"; + case SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING: + return "RESOLVE_ROUTE_RUNNING"; + case SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED: + return "RESOLVE_ROUTE_FAILED"; + case SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED: + return "RDMA_CONNECT_NEEDED"; + case SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING: + return "RDMA_CONNECT_RUNNING"; + case SMBDIRECT_SOCKET_RDMA_CONNECT_FAILED: + return "RDMA_CONNECT_FAILED"; + case SMBDIRECT_SOCKET_NEGOTIATE_NEEDED: + return "NEGOTIATE_NEEDED"; + case SMBDIRECT_SOCKET_NEGOTIATE_RUNNING: + return "NEGOTIATE_RUNNING"; case SMBDIRECT_SOCKET_NEGOTIATE_FAILED: return "NEGOTIATE_FAILED"; + case SMBDIRECT_SOCKET_CONNECTED: + return "CONNECTED"; case SMBDIRECT_SOCKET_DISCONNECTING: return "DISCONNECTING"; case SMBDIRECT_SOCKET_DISCONNECTED: -- 2.47.3