[PATCH v4 143/145] smb: server: make use of smbdirect_socket_{listen, accept}()
Stefan Metzmacher
metze at samba.org
Tue Nov 25 17:56:29 UTC 2025
We no longer need the custom rdma listener.
The code logic is very similar to transport_tcp.c now
using a kernel thread that loops over smbdirect_socket_accept().
This is the first step in the direction of using IPPROTO_SMBDIRECT
sockets in future.
Cc: Namjae Jeon <linkinjeon at kernel.org>
Cc: Steve French <smfrench at gmail.com>
Cc: Tom Talpey <tom at talpey.com>
Cc: linux-cifs at vger.kernel.org
Cc: samba-technical at lists.samba.org
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
fs/smb/server/transport_rdma.c | 229 +++++++++++++++++----------------
1 file changed, 116 insertions(+), 113 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 15559227ad69..54cf4456a4e9 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -75,7 +75,9 @@ struct smb_direct_device {
};
static struct smb_direct_listener {
- struct rdma_cm_id *cm_id;
+ struct task_struct *thread;
+
+ struct smbdirect_socket *socket;
} smb_direct_listener;
struct smb_direct_transport {
@@ -169,46 +171,15 @@ unsigned int get_smbd_max_read_write_size(struct ksmbd_transport *kt)
return sp->max_read_write_size;
}
-static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
+static struct smb_direct_transport *alloc_transport(struct smbdirect_socket *sc)
{
struct smb_direct_transport *t;
- struct smbdirect_socket *sc;
- struct smbdirect_socket_parameters init_params = {};
- struct smbdirect_socket_parameters *sp;
struct ksmbd_conn *conn;
- int ret;
-
- /*
- * Create the initial parameters
- */
- sp = &init_params;
- sp->negotiate_timeout_msec = SMB_DIRECT_NEGOTIATE_TIMEOUT * 1000;
- sp->initiator_depth = SMB_DIRECT_CM_INITIATOR_DEPTH;
- sp->responder_resources = 1;
- sp->recv_credit_max = smb_direct_receive_credit_max;
- sp->send_credit_target = smb_direct_send_credit_target;
- sp->max_send_size = smb_direct_max_send_size;
- sp->max_fragmented_recv_size = smb_direct_max_fragmented_recv_size;
- sp->max_recv_size = smb_direct_max_receive_size;
- sp->max_read_write_size = smb_direct_max_read_write_size;
- sp->keepalive_interval_msec = SMB_DIRECT_KEEPALIVE_SEND_INTERVAL * 1000;
- sp->keepalive_timeout_msec = SMB_DIRECT_KEEPALIVE_RECV_TIMEOUT * 1000;
t = kzalloc(sizeof(*t), KSMBD_DEFAULT_GFP);
if (!t)
return NULL;
- ret = smbdirect_socket_create_accepting(cm_id, &sc);
- if (ret)
- goto socket_create_failed;
- smbdirect_socket_set_logging(sc, NULL,
- smb_direct_logging_needed,
- smb_direct_logging_vaprintf);
- ret = smbdirect_socket_set_initial_parameters(sc, sp);
- if (ret)
- goto set_params_failed;
- ret = smbdirect_socket_set_kernel_settings(sc, IB_POLL_WORKQUEUE, KSMBD_DEFAULT_GFP);
- if (ret)
- goto set_settings_failed;
+ t->socket = sc;
conn = ksmbd_conn_alloc();
if (!conn)
@@ -222,14 +193,9 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
KSMBD_TRANS(t)->conn = conn;
KSMBD_TRANS(t)->ops = &ksmbd_smb_direct_transport_ops;
- t->socket = sc;
return t;
conn_alloc_failed:
-set_settings_failed:
-set_params_failed:
- smbdirect_socket_release(sc);
-socket_create_failed:
kfree(t);
return NULL;
}
@@ -326,47 +292,17 @@ static void smb_direct_shutdown(struct ksmbd_transport *t)
smbdirect_socket_shutdown(sc);
}
-static int smb_direct_prepare(struct ksmbd_transport *t)
-{
- struct smb_direct_transport *st = SMBD_TRANS(t);
- struct smbdirect_socket *sc = st->socket;
- int ret;
-
- ksmbd_debug(RDMA, "SMB_DIRECT Waiting for connection\n");
- ret = smbdirect_connection_wait_for_connected(sc);
- if (ret) {
- ksmbd_debug(RDMA, "SMB_DIRECT connection failed %d => %s\n",
- ret, errname(ret));
- return ret;
- }
-
- ksmbd_debug(RDMA, "SMB_DIRECT connection ready\n");
- return 0;
-}
-
-static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id,
- struct rdma_cm_event *event)
+static int smb_direct_new_connection(struct smbdirect_socket *client_sc)
{
struct smb_direct_transport *t;
- struct smbdirect_socket *sc;
struct task_struct *handler;
int ret;
- if (!smbdirect_frwr_is_supported(&new_cm_id->device->attrs)) {
- ksmbd_debug(RDMA,
- "Fast Registration Work Requests is not supported. device capabilities=%llx\n",
- new_cm_id->device->attrs.device_cap_flags);
- return -EPROTONOSUPPORT;
- }
-
- t = alloc_transport(new_cm_id);
- if (!t)
+ t = alloc_transport(client_sc);
+ if (!t) {
+ smbdirect_socket_release(client_sc);
return -ENOMEM;
- sc = t->socket;
-
- ret = smbdirect_accept_connect_request(sc, &event->param.conn);
- if (ret)
- goto out_err;
+ }
handler = kthread_run(ksmbd_conn_handler_loop,
KSMBD_TRANS(t)->conn, "ksmbd:r%u",
@@ -383,64 +319,134 @@ static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id,
return ret;
}
-static int smb_direct_listen_handler(struct rdma_cm_id *cm_id,
- struct rdma_cm_event *event)
+static int smb_direct_listener_kthread_fn(void *p)
{
- switch (event->event) {
- case RDMA_CM_EVENT_CONNECT_REQUEST: {
- int ret = smb_direct_handle_connect_request(cm_id, event);
+ struct smb_direct_listener *listener = (struct smb_direct_listener *)p;
+ struct smbdirect_socket *client_sc = NULL;
- if (ret) {
- pr_err("Can't create transport: %d\n", ret);
- return ret;
- }
+ while (!kthread_should_stop()) {
+ struct proto_accept_arg arg = { .err = -EINVAL, };
+ long timeo = MAX_SCHEDULE_TIMEOUT;
- ksmbd_debug(RDMA, "Received connection request. cm_id=%p\n",
- cm_id);
- break;
- }
- default:
- pr_err("Unexpected listen event. cm_id=%p, event=%s (%d)\n",
- cm_id, rdma_event_msg(event->event), event->event);
- break;
+ if (!listener->socket)
+ break;
+ client_sc = smbdirect_socket_accept(listener->socket, timeo, &arg);
+ if (!client_sc && arg.err == -EINVAL)
+ break;
+ if (!client_sc)
+ continue;
+
+ ksmbd_debug(CONN, "connect success: accepted new connection\n");
+ smb_direct_new_connection(client_sc);
}
+
+ ksmbd_debug(CONN, "releasing socket\n");
return 0;
}
-static int smb_direct_listen(int port)
+static void smb_direct_listener_destroy(struct smb_direct_listener *listener)
{
int ret;
- struct rdma_cm_id *cm_id;
+
+ if (listener->socket)
+ smbdirect_socket_shutdown(listener->socket);
+
+ if (listener->thread) {
+ ret = kthread_stop(listener->thread);
+ if (ret)
+ pr_err("failed to stop forker thread\n");
+ listener->thread = NULL;
+ }
+
+ if (listener->socket) {
+ smbdirect_socket_release(listener->socket);
+ listener->socket = NULL;
+ }
+}
+
+static int smb_direct_listen(int port)
+{
+ struct net *net = current->nsproxy->net_ns;
+ struct task_struct *kthread;
struct sockaddr_in sin = {
.sin_family = AF_INET,
.sin_addr.s_addr = htonl(INADDR_ANY),
.sin_port = htons(port),
};
+ struct smbdirect_socket_parameters init_params = {};
+ struct smbdirect_socket_parameters *sp;
+ struct smbdirect_socket *sc;
+ int ret;
- cm_id = rdma_create_id(&init_net, smb_direct_listen_handler,
- &smb_direct_listener, RDMA_PS_TCP, IB_QPT_RC);
- if (IS_ERR(cm_id)) {
- pr_err("Can't create cm id: %ld\n", PTR_ERR(cm_id));
- return PTR_ERR(cm_id);
+ ret = smbdirect_socket_create_kern(net, &sc);
+ if (ret) {
+ pr_err("smbdirect_socket_create_kern() failed: %d %s\n",
+ ret, errname(ret));
+ return ret;
}
- ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin);
+ /*
+ * Create the initial parameters
+ */
+ sp = &init_params;
+ sp->negotiate_timeout_msec = SMB_DIRECT_NEGOTIATE_TIMEOUT * 1000;
+ sp->initiator_depth = SMB_DIRECT_CM_INITIATOR_DEPTH;
+ sp->responder_resources = 1;
+ sp->recv_credit_max = smb_direct_receive_credit_max;
+ sp->send_credit_target = smb_direct_send_credit_target;
+ sp->max_send_size = smb_direct_max_send_size;
+ sp->max_fragmented_recv_size = smb_direct_max_fragmented_recv_size;
+ sp->max_recv_size = smb_direct_max_receive_size;
+ sp->max_read_write_size = smb_direct_max_read_write_size;
+ sp->keepalive_interval_msec = SMB_DIRECT_KEEPALIVE_SEND_INTERVAL * 1000;
+ sp->keepalive_timeout_msec = SMB_DIRECT_KEEPALIVE_RECV_TIMEOUT * 1000;
+
+ smbdirect_socket_set_logging(sc, NULL,
+ smb_direct_logging_needed,
+ smb_direct_logging_vaprintf);
+ ret = smbdirect_socket_set_initial_parameters(sc, sp);
+ if (ret) {
+ pr_err("Failed smbdirect_socket_set_initial_parameters(): %d %s\n",
+ ret, errname(ret));
+ goto err;
+ }
+ ret = smbdirect_socket_set_kernel_settings(sc, IB_POLL_WORKQUEUE, KSMBD_DEFAULT_GFP);
if (ret) {
- pr_err("Can't bind: %d\n", ret);
+ pr_err("Failed smbdirect_socket_set_kernel_settings(): %d %s\n",
+ ret, errname(ret));
goto err;
}
- smb_direct_listener.cm_id = cm_id;
+ ret = smbdirect_socket_bind(sc, (struct sockaddr *)&sin);
+ if (ret) {
+ pr_err("smbdirect_socket_bind() failed: %d %s\n",
+ ret, errname(ret));
+ goto err;
+ }
- ret = rdma_listen(cm_id, 10);
+ ret = smbdirect_socket_listen(sc, 10);
if (ret) {
- pr_err("Can't listen: %d\n", ret);
+ pr_err("Port[%d] smbdirect_socket_listen() failed: %d %s\n",
+ port, ret, errname(ret));
goto err;
}
+
+ smb_direct_listener.socket = sc;
+
+ kthread = kthread_run(smb_direct_listener_kthread_fn,
+ &smb_direct_listener,
+ "ksmbd-smbdirect-listener");
+ if (IS_ERR(kthread)) {
+ ret = PTR_ERR(kthread);
+ pr_err("Can't start ksmbd listen kthread: %d %s\n",
+ ret, errname(ret));
+ goto err;
+ }
+
+ smb_direct_listener.thread = kthread;
return 0;
err:
- smb_direct_listener.cm_id = NULL;
- rdma_destroy_id(cm_id);
+ smb_direct_listener_destroy(&smb_direct_listener);
return ret;
}
@@ -494,7 +500,8 @@ int ksmbd_rdma_init(void)
{
int ret;
- smb_direct_listener.cm_id = NULL;
+ smb_direct_listener.socket = NULL;
+ smb_direct_listener.thread = NULL;
ret = ib_register_client(&smb_direct_ib_client);
if (ret) {
@@ -508,20 +515,17 @@ int ksmbd_rdma_init(void)
return ret;
}
- ksmbd_debug(RDMA, "init RDMA listener. cm_id=%p\n",
- smb_direct_listener.cm_id);
+ ksmbd_debug(RDMA, "init RDMA listener\n");
return 0;
}
void ksmbd_rdma_stop_listening(void)
{
- if (!smb_direct_listener.cm_id)
+ if (!smb_direct_listener.socket)
return;
ib_unregister_client(&smb_direct_ib_client);
- rdma_destroy_id(smb_direct_listener.cm_id);
-
- smb_direct_listener.cm_id = NULL;
+ smb_direct_listener_destroy(&smb_direct_listener);
}
static bool ksmbd_find_rdma_capable_netdev(struct net_device *netdev)
@@ -589,7 +593,6 @@ bool ksmbd_rdma_capable_netdev(struct net_device *netdev)
}
static const struct ksmbd_transport_ops ksmbd_smb_direct_transport_ops = {
- .prepare = smb_direct_prepare,
.disconnect = smb_direct_disconnect,
.shutdown = smb_direct_shutdown,
.writev = smb_direct_writev,
--
2.43.0
More information about the samba-technical
mailing list