[PATCH v2 037/127] smb: smbdirect: introduce smbdirect_connection_rdma_{established, event_handler}()
Stefan Metzmacher
metze at samba.org
Wed Oct 29 13:20:15 UTC 2025
This will be used by client and server in future,
it will be used after the rdma connection is established
in order to simplify the events happening on an established
connection.
We'll also have smbdirect_{connect,accept}_rdma_event_handler
functions which will be used before the rdma connection is
established.
Cc: Steve French <smfrench at gmail.com>
Cc: Tom Talpey <tom at talpey.com>
Cc: Long Li <longli at microsoft.com>
Cc: Namjae Jeon <linkinjeon at kernel.org>
Cc: linux-cifs at vger.kernel.org
Cc: samba-technical at lists.samba.org
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
.../common/smbdirect/smbdirect_connection.c | 88 +++++++++++++++++++
fs/smb/common/smbdirect/smbdirect_socket.h | 8 ++
2 files changed, 96 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index 6fe6c53e10ea..cd4f3e6fa5e2 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -128,6 +128,94 @@ static void smbdirect_connection_qp_event_handler(struct ib_event *event, void *
}
}
+static int smbdirect_connection_rdma_event_handler(struct rdma_cm_id *id,
+ struct rdma_cm_event *event)
+{
+ struct smbdirect_socket *sc = id->context;
+
+ /*
+ * cma_cm_event_handler() has
+ * lockdep_assert_held(&id_priv->handler_mutex);
+ *
+ * Mutexes are not allowed in interrupts,
+ * and we rely on not being in an interrupt here.
+ */
+ WARN_ON_ONCE(in_interrupt());
+
+ if (event->status || event->event != sc->rdma.expected_event) {
+ int ret = -ECONNRESET;
+
+ if (event->event == RDMA_CM_EVENT_DEVICE_REMOVAL)
+ ret = -ENETDOWN;
+ if (IS_ERR(SMBDIRECT_DEBUG_ERR_PTR(event->status)))
+ ret = event->status;
+
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "%s (first_error=%1pe, expected=%s) => event=%s status=%d => ret=%1pe\n",
+ smbdirect_socket_status_string(sc->status),
+ SMBDIRECT_DEBUG_ERR_PTR(sc->first_error),
+ rdma_event_msg(sc->rdma.expected_event),
+ rdma_event_msg(event->event),
+ event->status,
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+
+ /*
+ * If we get RDMA_CM_EVENT_DEVICE_REMOVAL, we should change to
+ * SMBDIRECT_SOCKET_DISCONNECTED, so that
+ * rdma_disconnect() is avoided later via
+ * smbdirect_connection_schedule_disconnect() =>
+ * smbdirect_connection_disconnect_work().
+ */
+ if (event->event == RDMA_CM_EVENT_DEVICE_REMOVAL)
+ sc->status = SMBDIRECT_SOCKET_DISCONNECTED;
+
+ smbdirect_connection_schedule_disconnect(sc, ret);
+ if (sc->ib.qp)
+ ib_drain_qp(sc->ib.qp);
+ return 0;
+ }
+
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
+ "%s (first_error=%1pe) event=%s\n",
+ smbdirect_socket_status_string(sc->status),
+ SMBDIRECT_DEBUG_ERR_PTR(sc->first_error),
+ rdma_event_msg(event->event));
+
+ switch (event->event) {
+ case RDMA_CM_EVENT_DISCONNECTED:
+ sc->status = SMBDIRECT_SOCKET_DISCONNECTED;
+ smbdirect_connection_schedule_disconnect(sc, -ECONNRESET);
+ if (sc->ib.qp)
+ ib_drain_qp(sc->ib.qp);
+ return 0;
+
+ default:
+ break;
+ }
+
+ /*
+ * This is an internal error, should be handled above via
+ * event->event != sc->rdma.expected_event already.
+ */
+ WARN_ON_ONCE(sc->rdma.expected_event != RDMA_CM_EVENT_DISCONNECTED);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+ return 0;
+}
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_connection_rdma_established(struct smbdirect_socket *sc)
+{
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
+ "rdma established: device: %.*s local: %pISpsfc remote: %pISpsfc\n",
+ IB_DEVICE_NAME_MAX,
+ sc->ib.dev->name,
+ &sc->rdma.cm_id->route.addr.src_addr,
+ &sc->rdma.cm_id->route.addr.dst_addr);
+
+ sc->rdma.cm_id->event_handler = smbdirect_connection_rdma_event_handler;
+ sc->rdma.expected_event = RDMA_CM_EVENT_DISCONNECTED;
+}
+
static u32 smbdirect_rdma_rw_send_wrs(struct ib_device *dev,
const struct ib_qp_init_attr *attr)
{
diff --git a/fs/smb/common/smbdirect/smbdirect_socket.h b/fs/smb/common/smbdirect/smbdirect_socket.h
index 795ce4b976ff..c930d7531965 100644
--- a/fs/smb/common/smbdirect/smbdirect_socket.h
+++ b/fs/smb/common/smbdirect/smbdirect_socket.h
@@ -111,6 +111,12 @@ struct smbdirect_socket {
/* RDMA related */
struct {
struct rdma_cm_id *cm_id;
+ /*
+ * The expected event in our current
+ * cm_id->event_handler, all other events
+ * are treated as an error.
+ */
+ enum rdma_cm_event_type expected_event;
/*
* This is for iWarp MPA v1
*/
@@ -485,6 +491,8 @@ static __always_inline void smbdirect_socket_init(struct smbdirect_socket *sc)
INIT_WORK(&sc->disconnect_work, __smbdirect_socket_disabled_work);
disable_work_sync(&sc->disconnect_work);
+ sc->rdma.expected_event = RDMA_CM_EVENT_INTERNAL;
+
sc->ib.poll_ctx = IB_POLL_UNBOUND_WORKQUEUE;
INIT_WORK(&sc->idle.immediate_work, __smbdirect_socket_disabled_work);
--
2.43.0
More information about the samba-technical
mailing list