smb: server: only turn into SMBDIRECT_SOCKET_CONNECTED when negotiation is done

From SMBDIRECT_SOCKET_CREATED we now go via the following
stages:

1. SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED
   This indicated rdma_accept needs to be called

2. SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING
   This waits for RDMA_CM_EVENT_ESTABLISHED to
   arrive

3. SMBDIRECT_SOCKET_NEGOTIATE_NEEDED
   This waits for the negotiate request to
   arrive

4. SMBDIRECT_SOCKET_NEGOTIATE_RUNNING
   This indicates the negotiate request
   arrived and needs to be processed

5. SMBDIRECT_SOCKET_CONNECTED
   The connection is ready to use

This avoids the extra 'bool negotiation_requested'
and makes the steps more clear.

In future we may want to add trace points when
changing the states, which would be useful for
debugging.

Cc: Namjae Jeon <linkinjeon@kernel.org>
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: linux-cifs@vger.kernel.org
Cc: samba-technical@lists.samba.org
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
Stefan Metzmacher
2025-08-08 12:46:25 +02:00
committed by Steve French
parent c82a53211a
commit e2d5e516c6

View File

@@ -113,8 +113,6 @@ struct smb_direct_transport {
struct work_struct send_immediate_work;
struct work_struct disconnect_work;
bool negotiation_requested;
bool legacy_iwarp;
u8 initiator_depth;
u8 responder_resources;
@@ -255,19 +253,53 @@ static void smb_direct_disconnect_rdma_work(struct work_struct *work)
disconnect_work);
struct smbdirect_socket *sc = &t->socket;
if (sc->status == SMBDIRECT_SOCKET_CONNECTED) {
/*
* make sure this and other work is not queued again
* but here we don't block and avoid
* disable[_delayed]_work_sync()
*/
disable_work(&t->disconnect_work);
disable_work(&t->post_recv_credits_work);
disable_work(&t->send_immediate_work);
switch (sc->status) {
case SMBDIRECT_SOCKET_NEGOTIATE_NEEDED:
case SMBDIRECT_SOCKET_NEGOTIATE_RUNNING:
case SMBDIRECT_SOCKET_NEGOTIATE_FAILED:
case SMBDIRECT_SOCKET_CONNECTED:
case SMBDIRECT_SOCKET_ERROR:
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_accept() 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;
}
}
static void
smb_direct_disconnect_rdma_connection(struct smb_direct_transport *t)
{
struct smbdirect_socket *sc = &t->socket;
if (sc->status == SMBDIRECT_SOCKET_CONNECTED)
queue_work(smb_direct_wq, &t->disconnect_work);
queue_work(smb_direct_wq, &t->disconnect_work);
}
static void smb_direct_send_immediate_work(struct work_struct *work)
@@ -512,9 +544,9 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
smb_direct_disconnect_rdma_connection(t);
return;
}
t->negotiation_requested = true;
sc->recv_io.reassembly.full_packet_received = true;
sc->status = SMBDIRECT_SOCKET_CONNECTED;
WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_NEGOTIATE_NEEDED);
sc->status = SMBDIRECT_SOCKET_NEGOTIATE_RUNNING;
enqueue_reassembly(t, recvmsg, 0);
wake_up(&sc->status_wait);
return;
@@ -1546,7 +1578,8 @@ static int smb_direct_cm_handler(struct rdma_cm_id *cm_id,
switch (event->event) {
case RDMA_CM_EVENT_ESTABLISHED: {
sc->status = SMBDIRECT_SOCKET_CONNECTED;
WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING);
sc->status = SMBDIRECT_SOCKET_NEGOTIATE_NEEDED;
wake_up(&sc->status_wait);
break;
}
@@ -1555,6 +1588,7 @@ static int smb_direct_cm_handler(struct rdma_cm_id *cm_id,
ib_drain_qp(sc->ib.qp);
sc->status = SMBDIRECT_SOCKET_DISCONNECTED;
smb_direct_disconnect_rdma_work(&sc->disconnect_work);
wake_up_all(&sc->status_wait);
wake_up_all(&sc->recv_io.reassembly.wait_queue);
wake_up_all(&t->wait_send_credits);
@@ -1611,6 +1645,8 @@ static int smb_direct_send_negotiate_response(struct smb_direct_transport *t,
resp->min_version = SMB_DIRECT_VERSION_LE;
resp->max_version = SMB_DIRECT_VERSION_LE;
resp->status = STATUS_NOT_SUPPORTED;
sc->status = SMBDIRECT_SOCKET_NEGOTIATE_FAILED;
} else {
resp->status = STATUS_SUCCESS;
resp->min_version = SMB_DIRECT_VERSION_LE;
@@ -1627,6 +1663,7 @@ static int smb_direct_send_negotiate_response(struct smb_direct_transport *t,
cpu_to_le32(sp->max_fragmented_recv_size);
sc->recv_io.expected = SMBDIRECT_EXPECT_DATA_TRANSFER;
sc->status = SMBDIRECT_SOCKET_CONNECTED;
}
sendmsg->sge[0].addr = ib_dma_map_single(sc->ib.dev,
@@ -1682,6 +1719,8 @@ static int smb_direct_accept_client(struct smb_direct_transport *t)
conn_param.rnr_retry_count = SMB_DIRECT_CM_RNR_RETRY;
conn_param.flow_control = 0;
WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED);
sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING;
ret = rdma_accept(sc->rdma.cm_id, &conn_param);
if (ret) {
pr_err("error at rdma_accept: %d\n", ret);
@@ -1696,6 +1735,9 @@ static int smb_direct_prepare_negotiation(struct smb_direct_transport *t)
int ret;
struct smbdirect_recv_io *recvmsg;
WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_CREATED);
sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED;
sc->recv_io.expected = SMBDIRECT_EXPECT_NEGOTIATE_REQ;
recvmsg = get_free_recvmsg(t);
@@ -1708,7 +1750,6 @@ static int smb_direct_prepare_negotiation(struct smb_direct_transport *t)
goto out_err;
}
t->negotiation_requested = false;
ret = smb_direct_accept_client(t);
if (ret) {
pr_err("Can't accept client\n");
@@ -1994,12 +2035,25 @@ static int smb_direct_prepare(struct ksmbd_transport *t)
struct smbdirect_negotiate_req *req;
int ret;
/*
* We are waiting to pass the following states:
*
* SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED
* SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING
* SMBDIRECT_SOCKET_NEGOTIATE_NEEDED
*
* To finally get to SMBDIRECT_SOCKET_NEGOTIATE_RUNNING
* in order to continue below.
*
* Everything else is unexpected and an error.
*/
ksmbd_debug(RDMA, "Waiting for SMB_DIRECT negotiate request\n");
ret = wait_event_interruptible_timeout(sc->status_wait,
st->negotiation_requested ||
sc->status == SMBDIRECT_SOCKET_DISCONNECTED,
SMB_DIRECT_NEGOTIATE_TIMEOUT * HZ);
if (ret <= 0 || sc->status == SMBDIRECT_SOCKET_DISCONNECTED)
sc->status != SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED &&
sc->status != SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING &&
sc->status != SMBDIRECT_SOCKET_NEGOTIATE_NEEDED,
SMB_DIRECT_NEGOTIATE_TIMEOUT * HZ);
if (ret <= 0 || sc->status != SMBDIRECT_SOCKET_NEGOTIATE_RUNNING)
return ret < 0 ? ret : -ETIMEDOUT;
recvmsg = get_first_reassembly(st);