* [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko
@ 2025-10-29 13:19 Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 001/127] smb: smbdirect: let smbdirect.h include #include <linux/types.h> Stefan Metzmacher
` (127 more replies)
0 siblings, 128 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:19 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
David Howells
Hi,
this is the move use common functions in an smbdirect.ko.
It can also be found in my for-6.19/fs-smb-20251029-v2 branch,
at commit ca69115a279fbe0455c1b48d283072520e257d45:
git fetch https://git.samba.org/metze/linux/wip.git for-6.19/fs-smb-20251029-v2
https://git.samba.org/?p=metze/linux/wip.git;a=shortlog;h=refs/heads/for-6.19/fs-smb-20251029-v2
It is based on origin/master and smfrench-smb3-kernel/ksmbd-for-next
at commit e53642b87a4f4b03a8d7e5f8507fc3cd0c595ea6
Plus the patches from
https://lore.kernel.org/linux-cifs/20251027065102.12104-1-linkinjeon@kernel.org/
ksmbd: detect RDMA capable lower devices when bridge and vlan netdev is used
ksmbd: detect RDMA capable netdevs include IPoIB
and
https://lore.kernel.org/linux-cifs/20251028174347.1800568-1-metze@samba.org/
smb: client: call smbd_destroy() in the same splace as
kernel_sock_shutdown()/sock_release()
The end goal is still to go via the socket layer in order
to provide smbdirect support to userspace, so that Samba
can use if as client and server. But that will be done on
top of this patchset.
The patchset starts with the introduction of
a logging infrastructure that allows us to have
common code, but still do logging with cifs.ko
and ksmbd.ko specific functions.
Then it introduces smbdirect_all_c_files.c, which
is only temporary. It is included in the client and
server and will itself include more files with
common functions in the following patches.
This makes it possible to do the transition in
small steps. At the end this will be removed again,
while removing the file itself will be done in a later
patchset.
Then we have a series of patches introducing
common functions, most of them are copies
of the existing functions, just with a new name
and some reformatting. But the core logic is
mostly unchanged.
Then we have new functions related to async
connect and accept handling.
Followed by preparing some functions as public
and some as private, so that we have the
Kbuild logic for smbdirect.ko, which is
still disabled at that point.
Then we have small steps in the client in order
to make use of the new functions. At the end
is only uses smbdirect.ko and its exported functions.
Then we have small steps in the server in order
to make use of the new functions. At the end
is only uses smbdirect.ko and its exported functions.
Every patch compiles on its own and passes
grep -v 'Fixes: 0626e6641f6b ' | \
scripts/checkpatch.pl --quiet --codespell \
--ignore=FILE_PATH_CHANGES,EXPORT_SYMBOL,COMPLEX_MACRO
I've tested these tests at the end of the
patchset with siw and rxe:
cifs/001
generic/001
generic/002
generic/005
generic/006
generic/007
generic/008
generic/011
generic/024
generic/028
generic/029
generic/030
generic/033
generic/036
generic/069
generic/071
generic/080
generic/084
generic/086
generic/095
generic/098
generic/103
generic/124
generic/130
generic/132
generic/135
generic/141
generic/198
generic/207
generic/210
generic/212
generic/214
generic/215
generic/221
generic/228
generic/236
generic/246
generic/248
generic/249
generic/257
generic/258
generic/308
generic/309
generic/313
generic/315
generic/339
generic/340
generic/344
generic/345
generic/346
generic/354
generic/360
generic/390
generic/391
generic/393
generic/394
generic/406
generic/412
Can we get this into for-next-next?
David, if you rebase on this, you should be able to use
smbdirect_connection_send_iter() directly in smbd_send() and
remove the iov_iter_advance(iter, 4); before calling smbd_send().
smb_extract_bvecq_to_rdma() should be added as
smbdirect_map_sges_from_bvecq() into smbdirect_map_sges_from_iter().
From there I'll work on the changes to introduce IPPROTO_SMBDIRECT.
Stefan Metzmacher (127):
smb: smbdirect: let smbdirect.h include #include <linux/types.h>
smb: smbdirect: introduce SMBDIRECT_DEBUG_ERR_PTR() helper
smb: smbdirect: introduce smbdirect_socket.logging infrastructure
smb: smbdirect: introduce smbdirect_all_c_files.c
smb: smbdirect: introduce smbdirect_internal.h
smb: client: include smbdirect_all_c_files.c
smb: server: include smbdirect_all_c_files.c
smb: smbdirect: introduce smbdirect_connection.c with the first helper
function
smb: smbdirect: introduce smbdirect_socket_set_logging()
smb: smbdirect: introduce smbd_disconnect_wake_up_all()
smb: smbdirect: introduce smbdirect_connection_disconnect_work()
smb: smbdirect: introduce smbdirect_connection_schedule_disconnect()
smb: smbdirect: introduce smbdirect_connection_{get,put}_recv_io()
smb: smbdirect: introduce
smbdirect_connection_reassembly_{append,first}_recv_io()
smb: smbdirect: introduce smbdirect_connection_idle_timer_work()
smb: smbdirect: set SMBDIRECT_KEEPALIVE_NONE before
disable_delayed_work(&sc->idle.timer_work);
smb: smbdirect: introduce smbdirect_frwr_is_supported()
smb: smbdirect: introduce smbdirect_socket.{send,recv}_io.mem.gfp_mask
smb: smbdirect: introduce smbdirect_connection_{alloc,free}_send_io()
smb: smbdirect: introduce smbdirect_connection_send_io_done()
smb: smbdirect: introduce
smbdirect_connection_{create,destroy}_mem_pools()
smb: smbdirect: introduce smbdirect_map_sges_from_iter() and helper
functions
smb: smbdirect: introduce smbdirect_connection_qp_event_handler()
smb: smbdirect: introduce
smbdirect_connection_negotiate_rdma_resources()
smb: smbdirect: introduce smbdirect_connection_{create,destroy}_qp()
smb: smbdirect: introduce smbdirect_connection_post_recv_io()
smb: smbdirect: introduce smbdirect_connection_recv_io_refill_work()
smb: smbdirect: split out smbdirect_connection_recv_io_refill()
smb: smbdirect: introduce smbdirect_get_buf_page_count()
smb: smbdirect: introduce smbdirect_connection_wait_for_credits()
smb: smbdirect: introduce smbdirect_mr.c with client mr code
smb: smbdirect: introduce smbdirect_rw.c with server rw code
smb: smbdirect: define SMBDIRECT_MIN_{RECEIVE,FRAGMENTED}_SIZE
smb: smbdirect: define SMBDIRECT_RDMA_CM_[RNR_]RETRY
smb: smbdirect: introduce smbdirect_connection_recv_io_done()
smb: smbdirect: introduce smbdirect_connection_destroy[_sync]()
smb: smbdirect: introduce
smbdirect_connection_rdma_{established,event_handler}()
smb: smbdirect: introduce smbdirect_connection_recvmsg()
smb: smbdirect: introduce smbdirect_connection_grant_recv_credits()
smb: smbdirect: introduce smbdirect_connection_request_keep_alive()
smb: smbdirect: introduce smbdirect_connection_send_iter() and related
functions
smb: smbdirect: introduce smbdirect_connection_send_immediate_work()
smb: smbdirect: introduce smbdirect_connection_negotiation_done()
smb: smbdirect: introduce smbdirect_mr_io_fill_buffer_descriptor()
smb: smbdirect: introduce
smbdirect_connection_legacy_debug_proc_show()
smb: smbdirect: introduce smbdirect_connection_wait_for_connected()
smb: smbdirect: introduce smbdirect_connection_is_connected()
smb: smbdirect: introduce smbdirect_socket_shutdown()
smb: smbdirect: introduce smbdirect_socket_init_{new,accepting}() and
helpers
smb: smbdirect: introduce smbdirect_connect[_sync]()
smb: smbdirect: introduce smbdirect_accept_connect_request()
smb: smbdirect: introduce smbdirect_socket_create_{kern,accepting}()
and smbdirect_socket_release()
smb: smbdirect: let smbdirect_internal.h define pr_fmt without
SMBDIRECT_USE_INLINE_C_FILES
smb: smbdirect: introduce smbdirect_public.h with prototypes
smb: smbdirect: introduce smbdirect_private.h with prototypes
smb: smbdirect: introduce the basic smbdirect.ko
smb: client: make use of smbdirect_socket_prepare_create()
smb: client: make use of smbdirect_socket_set_logging()
smb: client: make use of smbdirect_connection_wake_up_all()
smb: client: make use of smbdirect_connection_disconnect_work()
smb: client: make use of smbdirect_connection_schedule_disconnect()
smb: client: make use of smbdirect_connection_{get,put}_recv_io()
smb: client: make use of
smbdirect_connection_reassembly_{append,first}_recv_io()
smb: client: make use of smbdirect_connection_idle_timer_work()
smb: client: make use of smbdirect_frwr_is_supported()
smb: client: make use of smbdirect_connection_{alloc,free}_send_io()
smb: client: make use of smbdirect_connection_send_io_done()
smb: client: make use of
smbdirect_connection_{create,destroy}_mem_pools()
smb: client: make use of smbdirect_map_sges_from_iter()
smb: client: make use of smbdirect_connection_qp_event_handler()
smb: client: make use of
smbdirect_connection_negotiate_rdma_resources()
smb: client: make use of smbdirect_connection_{create,destroy}_qp()
smb: client: initialize recv_io->cqe.done = recv_done just once
smb: client: make use of smbdirect_connection_post_recv_io()
smb: client: make use of smbdirect_connection_recv_io_refill_work()
smb: client: make use of functions from smbdirect_mr.c
smb: client: make use of smbdirect_connection_destroy_sync()
smb: client: make use of smbdirect_connection_recvmsg()
smb: client: let smbd_post_send() make use of request->wr
smb: client: make use of smbdirect_connection_grant_recv_credits()
smb: client: make use of smbdirect_connection_request_keep_alive()
smb: client: change smbd_post_send_empty() to void return
smb: client: let smbd_post_send_iter() get remaining_length and return
data_length
smb: client: let smbd_post_send_full_iter() get remaining_length and
return data_length
smb: client: make use of
smbdirect_connection_send_{single_iter,immediate_work}()
smb: client: introduce and use smbd_mr_fill_buffer_descriptor()
smb: client: introduce and use smbd_debug_proc_show()
smb: client: make use of smbdirect_socket_init_new() and
smbdirect_connect_sync()
smb: client: make use of
smbdirect_socket_create_kern()/smbdirect_socket_release()
smb: client: only use public smbdirect functions
smb: client: make use of smbdirect.ko
smb: server: make use of smbdirect_socket_prepare_create()
smb: server: make use of smbdirect_socket_set_logging()
smb: server: make use of smbdirect_connection_wake_up_all()
smb: server: make use of smbdirect_connection_disconnect_work()
smb: server: make use of smbdirect_connection_schedule_disconnect()
smb: server: make use of smbdirect_connection_{get,put}_recv_io()
smb: server: make use of
smbdirect_connection_reassembly_{append,first}_recv_io()
smb: server: make use of smbdirect_connection_idle_timer_work()
smb: server: make use of smbdirect_frwr_is_supported()
smb: server: make use of smbdirect_connection_{alloc,free}_send_io()
smb: server: make use of smbdirect_connection_send_io_done()
smb: server: make use of
smbdirect_connection_{create,destroy}_mem_pools()
smb: server: make use of smbdirect_map_sges_from_iter()
smb: server: make use of smbdirect_connection_qp_event_handler()
smb: server: make use of
smbdirect_connection_negotiate_rdma_resources()
smb: server: make use of smbdirect_connection_{create,destroy}_qp()
smb: server: initialize recv_io->cqe.done = recv_done just once
smb: server: make use of smbdirect_connection_post_recv_io()
smb: server: make use of smbdirect_connection_recv_io_refill[_work]()
smb: server: make use of smbdirect_get_buf_page_count()
smb: server: make use of smbdirect_connection_wait_for_credits()
smb: server: make use of functions from smbdirect_rw.c
smb: server: make use of smbdirect_connection_destroy_sync()
smb: server: make use of smbdirect_connection_recvmsg()
smb: server: make use of smbdirect_connection_grant_recv_credits()
smb: server: make use of smbdirect_connection_request_keep_alive()
smb: server: move iov_iter_kvec() out of smb_direct_post_send_data()
smb: server: inline smb_direct_create_header() into
smb_direct_post_send_data()
smb: server: let smbdirect_map_sges_from_iter() truncate the message
boundary
smb: server: split out smb_direct_send_iter() out of
smb_direct_writev()
smb: server: let smb_direct_post_send_data() return data_length
smb: server: make use of smbdirect_connection_send_iter() and related
functions
smb: server: make use of
smbdirect_{socket_init_accepting,connection_wait_for_connected}()
smb: server: make use of
smbdirect_socket_create_accepting()/smbdirect_socket_release()
smb: server: only use public smbdirect functions
smb: server: make use of smbdirect.ko
fs/smb/Kconfig | 2 +
fs/smb/client/Kconfig | 3 +-
fs/smb/client/cifs_debug.c | 67 +-
fs/smb/client/smb2pdu.c | 9 +-
fs/smb/client/smbdirect.c | 2813 +----------------
fs/smb/client/smbdirect.h | 20 +-
fs/smb/common/Makefile | 1 +
fs/smb/common/smbdirect/Kconfig | 9 +
fs/smb/common/smbdirect/Makefile | 15 +
fs/smb/common/smbdirect/smbdirect.h | 2 +
fs/smb/common/smbdirect/smbdirect_accept.c | 596 ++++
.../common/smbdirect/smbdirect_all_c_files.c | 23 +
fs/smb/common/smbdirect/smbdirect_connect.c | 797 +++++
.../common/smbdirect/smbdirect_connection.c | 2631 +++++++++++++++
fs/smb/common/smbdirect/smbdirect_debug.c | 89 +
fs/smb/common/smbdirect/smbdirect_internal.h | 20 +
fs/smb/common/smbdirect/smbdirect_main.c | 24 +
fs/smb/common/smbdirect/smbdirect_mr.c | 565 ++++
fs/smb/common/smbdirect/smbdirect_pdu.h | 4 +
fs/smb/common/smbdirect/smbdirect_private.h | 92 +
fs/smb/common/smbdirect/smbdirect_public.h | 154 +
fs/smb/common/smbdirect/smbdirect_rw.c | 254 ++
fs/smb/common/smbdirect/smbdirect_socket.h | 206 +-
fs/smb/server/Kconfig | 4 +-
fs/smb/server/smb2pdu.c | 1 -
fs/smb/server/transport_rdma.c | 2399 +-------------
fs/smb/server/transport_rdma.h | 2 +
27 files changed, 5823 insertions(+), 4979 deletions(-)
create mode 100644 fs/smb/common/smbdirect/Kconfig
create mode 100644 fs/smb/common/smbdirect/Makefile
create mode 100644 fs/smb/common/smbdirect/smbdirect_accept.c
create mode 100644 fs/smb/common/smbdirect/smbdirect_all_c_files.c
create mode 100644 fs/smb/common/smbdirect/smbdirect_connect.c
create mode 100644 fs/smb/common/smbdirect/smbdirect_connection.c
create mode 100644 fs/smb/common/smbdirect/smbdirect_debug.c
create mode 100644 fs/smb/common/smbdirect/smbdirect_internal.h
create mode 100644 fs/smb/common/smbdirect/smbdirect_main.c
create mode 100644 fs/smb/common/smbdirect/smbdirect_mr.c
create mode 100644 fs/smb/common/smbdirect/smbdirect_private.h
create mode 100644 fs/smb/common/smbdirect/smbdirect_public.h
create mode 100644 fs/smb/common/smbdirect/smbdirect_rw.c
--
2.43.0
^ permalink raw reply [flat|nested] 130+ messages in thread
* [PATCH v2 001/127] smb: smbdirect: let smbdirect.h include #include <linux/types.h>
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
@ 2025-10-29 13:19 ` Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 002/127] smb: smbdirect: introduce SMBDIRECT_DEBUG_ERR_PTR() helper Stefan Metzmacher
` (126 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:19 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This will make it easier to use.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/common/smbdirect/smbdirect.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect.h b/fs/smb/common/smbdirect/smbdirect.h
index 05cc6a9d0ccd..821a34c4cc47 100644
--- a/fs/smb/common/smbdirect/smbdirect.h
+++ b/fs/smb/common/smbdirect/smbdirect.h
@@ -7,6 +7,8 @@
#ifndef __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_H__
#define __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_H__
+#include <linux/types.h>
+
/* SMB-DIRECT buffer descriptor V1 structure [MS-SMBD] 2.2.3.1 */
struct smbdirect_buffer_descriptor_v1 {
__le64 offset;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 002/127] smb: smbdirect: introduce SMBDIRECT_DEBUG_ERR_PTR() helper
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 001/127] smb: smbdirect: let smbdirect.h include #include <linux/types.h> Stefan Metzmacher
@ 2025-10-29 13:19 ` Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 003/127] smb: smbdirect: introduce smbdirect_socket.logging infrastructure Stefan Metzmacher
` (125 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:19 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This can be used like this:
int err = somefunc();
pr_warn("err=%1pe\n", SMBDIRECT_DEBUG_ERR_PTR(err));
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/common/smbdirect/smbdirect_socket.h | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_socket.h b/fs/smb/common/smbdirect/smbdirect_socket.h
index ee5a90d691c8..611986827a5e 100644
--- a/fs/smb/common/smbdirect/smbdirect_socket.h
+++ b/fs/smb/common/smbdirect/smbdirect_socket.h
@@ -74,6 +74,19 @@ const char *smbdirect_socket_status_string(enum smbdirect_socket_status status)
return "<unknown>";
}
+/*
+ * This can be used with %1pe to print errors as strings or '0'
+ * And it avoids warnings like: warn: passing zero to 'ERR_PTR'
+ * from smatch -p=kernel --pedantic
+ */
+static __always_inline
+const void * __must_check SMBDIRECT_DEBUG_ERR_PTR(long error)
+{
+ if (error == 0)
+ return NULL;
+ return ERR_PTR(error);
+}
+
enum smbdirect_keepalive_status {
SMBDIRECT_KEEPALIVE_NONE,
SMBDIRECT_KEEPALIVE_PENDING,
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 003/127] smb: smbdirect: introduce smbdirect_socket.logging infrastructure
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 001/127] smb: smbdirect: let smbdirect.h include #include <linux/types.h> Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 002/127] smb: smbdirect: introduce SMBDIRECT_DEBUG_ERR_PTR() helper Stefan Metzmacher
@ 2025-10-29 13:19 ` Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 004/127] smb: smbdirect: introduce smbdirect_all_c_files.c Stefan Metzmacher
` (124 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:19 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This will be used by client and server in order to keep controlling
the logging when we move to shared functions.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/common/smbdirect/smbdirect_socket.h | 125 +++++++++++++++++++++
1 file changed, 125 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_socket.h b/fs/smb/common/smbdirect/smbdirect_socket.h
index 611986827a5e..65b21b65596f 100644
--- a/fs/smb/common/smbdirect/smbdirect_socket.h
+++ b/fs/smb/common/smbdirect/smbdirect_socket.h
@@ -330,6 +330,35 @@ struct smbdirect_socket {
u64 dequeue_reassembly_queue;
u64 send_empty;
} statistics;
+
+ struct {
+#define SMBDIRECT_LOG_ERR 0x0
+#define SMBDIRECT_LOG_INFO 0x1
+
+#define SMBDIRECT_LOG_OUTGOING 0x1
+#define SMBDIRECT_LOG_INCOMING 0x2
+#define SMBDIRECT_LOG_READ 0x4
+#define SMBDIRECT_LOG_WRITE 0x8
+#define SMBDIRECT_LOG_RDMA_SEND 0x10
+#define SMBDIRECT_LOG_RDMA_RECV 0x20
+#define SMBDIRECT_LOG_KEEP_ALIVE 0x40
+#define SMBDIRECT_LOG_RDMA_EVENT 0x80
+#define SMBDIRECT_LOG_RDMA_MR 0x100
+#define SMBDIRECT_LOG_RDMA_RW 0x200
+#define SMBDIRECT_LOG_NEGOTIATE 0x400
+ void *private_ptr;
+ bool (*needed)(struct smbdirect_socket *sc,
+ void *private_ptr,
+ unsigned int lvl,
+ unsigned int cls);
+ void (*vaprintf)(struct smbdirect_socket *sc,
+ const char *func,
+ unsigned int line,
+ void *private_ptr,
+ unsigned int lvl,
+ unsigned int cls,
+ struct va_format *vaf);
+ } logging;
};
static void __smbdirect_socket_disabled_work(struct work_struct *work)
@@ -340,6 +369,98 @@ static void __smbdirect_socket_disabled_work(struct work_struct *work)
WARN_ON_ONCE(1);
}
+static bool __smbdirect_log_needed(struct smbdirect_socket *sc,
+ void *private_ptr,
+ unsigned int lvl,
+ unsigned int cls)
+{
+ /*
+ * Should never be called, the caller should
+ * set it's own functions.
+ */
+ WARN_ON_ONCE(1);
+ return false;
+}
+
+static void __smbdirect_log_vaprintf(struct smbdirect_socket *sc,
+ const char *func,
+ unsigned int line,
+ void *private_ptr,
+ unsigned int lvl,
+ unsigned int cls,
+ struct va_format *vaf)
+{
+ /*
+ * Should never be called, the caller should
+ * set it's own functions.
+ */
+ WARN_ON_ONCE(1);
+}
+
+__printf(6, 7)
+static void __smbdirect_log_printf(struct smbdirect_socket *sc,
+ const char *func,
+ unsigned int line,
+ unsigned int lvl,
+ unsigned int cls,
+ const char *fmt,
+ ...);
+__maybe_unused
+static void __smbdirect_log_printf(struct smbdirect_socket *sc,
+ const char *func,
+ unsigned int line,
+ unsigned int lvl,
+ unsigned int cls,
+ const char *fmt,
+ ...)
+{
+ struct va_format vaf;
+ va_list args;
+
+ va_start(args, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ sc->logging.vaprintf(sc,
+ func,
+ line,
+ sc->logging.private_ptr,
+ lvl,
+ cls,
+ &vaf);
+ va_end(args);
+}
+
+#define __smbdirect_log_generic(sc, lvl, cls, fmt, args...) do { \
+ if (sc->logging.needed(sc, sc->logging.private_ptr, lvl, cls)) { \
+ __smbdirect_log_printf(sc, __func__, __LINE__, lvl, cls, fmt, ##args); \
+ } \
+} while (0)
+
+#define smbdirect_log_outgoing(sc, lvl, fmt, args...) \
+ __smbdirect_log_generic(sc, lvl, SMBDIRECT_LOG_OUTGOING, fmt, ##args)
+#define smbdirect_log_incoming(sc, lvl, fmt, args...) \
+ __smbdirect_log_generic(sc, lvl, SMBDIRECT_LOG_INCOMING, fmt, ##args)
+#define smbdirect_log_read(sc, lvl, fmt, args...) \
+ __smbdirect_log_generic(sc, lvl, SMBDIRECT_LOG_READ, fmt, ##args)
+#define smbdirect_log_write(sc, lvl, fmt, args...) \
+ __smbdirect_log_generic(sc, lvl, SMBDIRECT_LOG_WRITE, fmt, ##args)
+#define smbdirect_log_rdma_send(sc, lvl, fmt, args...) \
+ __smbdirect_log_generic(sc, lvl, SMBDIRECT_LOG_RDMA_SEND, fmt, ##args)
+#define smbdirect_log_rdma_recv(sc, lvl, fmt, args...) \
+ __smbdirect_log_generic(sc, lvl, SMBDIRECT_LOG_RDMA_RECV, fmt, ##args)
+#define smbdirect_log_keep_alive(sc, lvl, fmt, args...) \
+ __smbdirect_log_generic(sc, lvl, SMBDIRECT_LOG_KEEP_ALIVE, fmt, ##args)
+#define smbdirect_log_rdma_event(sc, lvl, fmt, args...) \
+ __smbdirect_log_generic(sc, lvl, SMBDIRECT_LOG_RDMA_EVENT, fmt, ##args)
+#define smbdirect_log_rdma_mr(sc, lvl, fmt, args...) \
+ __smbdirect_log_generic(sc, lvl, SMBDIRECT_LOG_RDMA_MR, fmt, ##args)
+#define smbdirect_log_rdma_rw(sc, lvl, fmt, args...) \
+ __smbdirect_log_generic(sc, lvl, SMBDIRECT_LOG_RDMA_RW, fmt, ##args)
+#define smbdirect_log_negotiate(sc, lvl, fmt, args...) \
+ __smbdirect_log_generic(sc, lvl, SMBDIRECT_LOG_NEGOTIATE, fmt, ##args)
+
static __always_inline void smbdirect_socket_init(struct smbdirect_socket *sc)
{
/*
@@ -392,6 +513,10 @@ static __always_inline void smbdirect_socket_init(struct smbdirect_socket *sc)
INIT_WORK(&sc->mr_io.recovery_work, __smbdirect_socket_disabled_work);
disable_work_sync(&sc->mr_io.recovery_work);
init_waitqueue_head(&sc->mr_io.cleanup.wait_queue);
+
+ sc->logging.private_ptr = NULL;
+ sc->logging.needed = __smbdirect_log_needed;
+ sc->logging.vaprintf = __smbdirect_log_vaprintf;
}
struct smbdirect_send_io {
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 004/127] smb: smbdirect: introduce smbdirect_all_c_files.c
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (2 preceding siblings ...)
2025-10-29 13:19 ` [PATCH v2 003/127] smb: smbdirect: introduce smbdirect_socket.logging infrastructure Stefan Metzmacher
@ 2025-10-29 13:19 ` Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 005/127] smb: smbdirect: introduce smbdirect_internal.h Stefan Metzmacher
` (123 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:19 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This is a very basic start in order to introduce
common functions, which will be shared by client and server.
As a start smbdirect_all_c_files.c will be included in
fs/smb/client/smbdirect.c and fs/smb/server/transport_rdma.c
in order to allow tiny steps in the direction of moving to
a few exported functions from an smbdirect.ko.
Step by step this will include individual c files
with the real functions.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/common/smbdirect/smbdirect_all_c_files.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100644 fs/smb/common/smbdirect/smbdirect_all_c_files.c
diff --git a/fs/smb/common/smbdirect/smbdirect_all_c_files.c b/fs/smb/common/smbdirect/smbdirect_all_c_files.c
new file mode 100644
index 000000000000..610556fb7931
--- /dev/null
+++ b/fs/smb/common/smbdirect/smbdirect_all_c_files.c
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2025, Stefan Metzmacher
+ */
+
+/*
+ * This is a temporary solution in order
+ * to include the common smbdirect functions
+ * into .c files in order to make a transformation
+ * in tiny bisectable steps possible.
+ *
+ * It will be replaced by a smbdirect.ko with
+ * exported public functions at the end.
+ */
+#ifndef SMBDIRECT_USE_INLINE_C_FILES
+#error SMBDIRECT_USE_INLINE_C_FILES define needed
+#endif
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 005/127] smb: smbdirect: introduce smbdirect_internal.h
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (3 preceding siblings ...)
2025-10-29 13:19 ` [PATCH v2 004/127] smb: smbdirect: introduce smbdirect_all_c_files.c Stefan Metzmacher
@ 2025-10-29 13:19 ` Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 006/127] smb: client: include smbdirect_all_c_files.c Stefan Metzmacher
` (122 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:19 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This will be included by individual .c files as first
header.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/common/smbdirect/smbdirect_internal.h | 14 ++++++++++++++
1 file changed, 14 insertions(+)
create mode 100644 fs/smb/common/smbdirect/smbdirect_internal.h
diff --git a/fs/smb/common/smbdirect/smbdirect_internal.h b/fs/smb/common/smbdirect/smbdirect_internal.h
new file mode 100644
index 000000000000..0727b9fee879
--- /dev/null
+++ b/fs/smb/common/smbdirect/smbdirect_internal.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2025, Stefan Metzmacher
+ */
+
+#ifndef __FS_SMB_COMMON_SMBDIRECT_INTERNAL_H__
+#define __FS_SMB_COMMON_SMBDIRECT_INTERNAL_H__
+
+#include <linux/errname.h>
+#include "smbdirect.h"
+#include "smbdirect_pdu.h"
+#include "smbdirect_socket.h"
+
+#endif /* __FS_SMB_COMMON_SMBDIRECT_INTERNAL_H__ */
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 006/127] smb: client: include smbdirect_all_c_files.c
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (4 preceding siblings ...)
2025-10-29 13:19 ` [PATCH v2 005/127] smb: smbdirect: introduce smbdirect_internal.h Stefan Metzmacher
@ 2025-10-29 13:19 ` Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 007/127] smb: server: " Stefan Metzmacher
` (121 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:19 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This is the first tiny step in order to use common functions in future.
Once we have all functions in common we'll move to an smbdirect.ko
that exports public functions instead of including the .c file.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 85a4c55b61b8..5ae22c8dea81 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -4,6 +4,9 @@
*
* Author(s): Long Li <longli@microsoft.com>
*/
+
+#define SMBDIRECT_USE_INLINE_C_FILES 1
+
#include <linux/module.h>
#include <linux/highmem.h>
#include <linux/folio_queue.h>
@@ -142,6 +145,14 @@ module_param(smbd_logging_level, uint, 0644);
MODULE_PARM_DESC(smbd_logging_level,
"Logging level for SMBD transport, 0 (default): error, 1: info");
+/*
+ * This is a temporary solution until all code
+ * is moved to smbdirect_all_c_files.c and we
+ * have an smbdirect.ko that exports the required
+ * functions.
+ */
+#include "../common/smbdirect/smbdirect_all_c_files.c"
+
#define log_rdma(level, class, fmt, args...) \
do { \
if (level <= smbd_logging_level || class & smbd_logging_class) \
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 007/127] smb: server: include smbdirect_all_c_files.c
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (5 preceding siblings ...)
2025-10-29 13:19 ` [PATCH v2 006/127] smb: client: include smbdirect_all_c_files.c Stefan Metzmacher
@ 2025-10-29 13:19 ` Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 008/127] smb: smbdirect: introduce smbdirect_connection.c with the first helper function Stefan Metzmacher
` (120 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:19 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Namjae Jeon, Steve French, Tom Talpey, Steve French
This is the first tiny step in order to use common functions in future.
Once we have all functions in common we'll move to an smbdirect.ko
that exports public functions instead of including the .c file.
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>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/smb/server/transport_rdma.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 5d3b48e77012..9bf023b797ad 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -9,6 +9,8 @@
#define SUBMOD_NAME "smb_direct"
+#define SMBDIRECT_USE_INLINE_C_FILES 1
+
#include <linux/kthread.h>
#include <linux/list.h>
#include <linux/mempool.h>
@@ -28,6 +30,14 @@
#include "../common/smbdirect/smbdirect_socket.h"
#include "transport_rdma.h"
+/*
+ * This is a temporary solution until all code
+ * is moved to smbdirect_all_c_files.c and we
+ * have an smbdirect.ko that exports the required
+ * functions.
+ */
+#include "../common/smbdirect/smbdirect_all_c_files.c"
+
#define SMB_DIRECT_PORT_IWARP 5445
#define SMB_DIRECT_PORT_INFINIBAND 445
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 008/127] smb: smbdirect: introduce smbdirect_connection.c with the first helper function
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (6 preceding siblings ...)
2025-10-29 13:19 ` [PATCH v2 007/127] smb: server: " Stefan Metzmacher
@ 2025-10-29 13:19 ` Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 009/127] smb: smbdirect: introduce smbdirect_socket_set_logging() Stefan Metzmacher
` (119 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:19 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This is a very basic start in order to introduce smbdirect_connection.c
with common functions, which will be shared by client and server.
Over time smbdirect_connection.c will get more and more functions
which will be included in fs/smb/client/smbdirect.c and
fs/smb/server/transport_rdma.c via
fs/smb/common/smbdirect/smbdirect_all_c_files.c
in order to allow tiny steps in the direction of moving to
a few exported functions from an smbdirect.ko.
That's why __maybe_unused is added for now it will
be removed at the end of the road to common code.
Note the Copyright (C) 2017, Microsoft Corporation is added
as a lot of functions from fs/smb/client/smbdirect.c will
be moved into this file soon and I don't want to forget
about adding it.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_all_c_files.c | 1 +
.../common/smbdirect/smbdirect_connection.c | 26 +++++++++++++++++++
2 files changed, 27 insertions(+)
create mode 100644 fs/smb/common/smbdirect/smbdirect_connection.c
diff --git a/fs/smb/common/smbdirect/smbdirect_all_c_files.c b/fs/smb/common/smbdirect/smbdirect_all_c_files.c
index 610556fb7931..ba92f0813932 100644
--- a/fs/smb/common/smbdirect/smbdirect_all_c_files.c
+++ b/fs/smb/common/smbdirect/smbdirect_all_c_files.c
@@ -15,3 +15,4 @@
#ifndef SMBDIRECT_USE_INLINE_C_FILES
#error SMBDIRECT_USE_INLINE_C_FILES define needed
#endif
+#include "smbdirect_connection.c"
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
new file mode 100644
index 000000000000..ca6508705be8
--- /dev/null
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2017, Microsoft Corporation.
+ * Copyright (c) 2025, Stefan Metzmacher
+ */
+
+#include "smbdirect_internal.h"
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_socket_prepare_create(struct smbdirect_socket *sc,
+ const struct smbdirect_socket_parameters *sp,
+ struct workqueue_struct *workqueue)
+{
+ smbdirect_socket_init(sc);
+
+ /*
+ * Make a copy of the callers parameters
+ * from here we only work on the copy
+ */
+ sc->parameters = *sp;
+
+ /*
+ * Remember the callers workqueue
+ */
+ sc->workqueue = workqueue;
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 009/127] smb: smbdirect: introduce smbdirect_socket_set_logging()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (7 preceding siblings ...)
2025-10-29 13:19 ` [PATCH v2 008/127] smb: smbdirect: introduce smbdirect_connection.c with the first helper function Stefan Metzmacher
@ 2025-10-29 13:19 ` Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 010/127] smb: smbdirect: introduce smbd_disconnect_wake_up_all() Stefan Metzmacher
` (118 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:19 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This will be used by client and server in order to setup
their own logging functions.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 20 +++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index ca6508705be8..f7fc4b1732c4 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -24,3 +24,23 @@ static void smbdirect_socket_prepare_create(struct smbdirect_socket *sc,
*/
sc->workqueue = workqueue;
}
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_socket_set_logging(struct smbdirect_socket *sc,
+ void *private_ptr,
+ bool (*needed)(struct smbdirect_socket *sc,
+ void *private_ptr,
+ unsigned int lvl,
+ unsigned int cls),
+ void (*vaprintf)(struct smbdirect_socket *sc,
+ const char *func,
+ unsigned int line,
+ void *private_ptr,
+ unsigned int lvl,
+ unsigned int cls,
+ struct va_format *vaf))
+{
+ sc->logging.private_ptr = private_ptr;
+ sc->logging.needed = needed;
+ sc->logging.vaprintf = vaprintf;
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 010/127] smb: smbdirect: introduce smbd_disconnect_wake_up_all()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (8 preceding siblings ...)
2025-10-29 13:19 ` [PATCH v2 009/127] smb: smbdirect: introduce smbdirect_socket_set_logging() Stefan Metzmacher
@ 2025-10-29 13:19 ` Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 011/127] smb: smbdirect: introduce smbdirect_connection_disconnect_work() Stefan Metzmacher
` (117 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:19 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This is a superset of smbd_disconnect_wake_up_all() in the client
and smb_direct_disconnect_wake_up_all() in the server and will
replace them.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/common/smbdirect/smbdirect_connection.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index f7fc4b1732c4..654719f4388a 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -44,3 +44,21 @@ static void smbdirect_socket_set_logging(struct smbdirect_socket *sc,
sc->logging.needed = needed;
sc->logging.vaprintf = vaprintf;
}
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_connection_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.lcredits.wait_queue);
+ 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->rw_io.credits.wait_queue);
+ wake_up_all(&sc->mr_io.ready.wait_queue);
+ wake_up_all(&sc->mr_io.cleanup.wait_queue);
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 011/127] smb: smbdirect: introduce smbdirect_connection_disconnect_work()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (9 preceding siblings ...)
2025-10-29 13:19 ` [PATCH v2 010/127] smb: smbdirect: introduce smbd_disconnect_wake_up_all() Stefan Metzmacher
@ 2025-10-29 13:19 ` Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 012/127] smb: smbdirect: introduce smbdirect_connection_schedule_disconnect() Stefan Metzmacher
` (116 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:19 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This is basically a copy of smbd_disconnect_rdma_work() and
smb_direct_disconnect_rdma_work() and will replace them in the
next steps.
It also makes sure it's never used in an interrupt, which is
not expected anyway...
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 68 +++++++++++++++++++
1 file changed, 68 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index 654719f4388a..ebf47baa5d25 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -6,6 +6,8 @@
#include "smbdirect_internal.h"
+static void smbdirect_connection_disconnect_work(struct work_struct *work);
+
__maybe_unused /* this is temporary while this file is included in orders */
static void smbdirect_socket_prepare_create(struct smbdirect_socket *sc,
const struct smbdirect_socket_parameters *sp,
@@ -23,6 +25,8 @@ static void smbdirect_socket_prepare_create(struct smbdirect_socket *sc,
* Remember the callers workqueue
*/
sc->workqueue = workqueue;
+
+ INIT_WORK(&sc->disconnect_work, smbdirect_connection_disconnect_work);
}
__maybe_unused /* this is temporary while this file is included in orders */
@@ -62,3 +66,67 @@ static void smbdirect_connection_wake_up_all(struct smbdirect_socket *sc)
wake_up_all(&sc->mr_io.ready.wait_queue);
wake_up_all(&sc->mr_io.cleanup.wait_queue);
}
+
+static void smbdirect_connection_disconnect_work(struct work_struct *work)
+{
+ struct smbdirect_socket *sc =
+ container_of(work, struct smbdirect_socket, disconnect_work);
+
+ /*
+ * This should not never be called in an interrupt!
+ */
+ WARN_ON_ONCE(in_interrupt());
+
+ /*
+ * make sure this and other work is not queued again
+ * but here we don't block and avoid
+ * disable[_delayed]_work_sync()
+ */
+ disable_work(&sc->disconnect_work);
+ disable_work(&sc->recv_io.posted.refill_work);
+ disable_work(&sc->mr_io.recovery_work);
+ disable_work(&sc->idle.immediate_work);
+ disable_delayed_work(&sc->idle.timer_work);
+
+ if (sc->first_error == 0)
+ sc->first_error = -ECONNABORTED;
+
+ 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,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;
+ }
+
+ /*
+ * Wake up all waiters in all wait queues
+ * in order to notice the broken connection.
+ */
+ smbdirect_connection_wake_up_all(sc);
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 012/127] smb: smbdirect: introduce smbdirect_connection_schedule_disconnect()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (10 preceding siblings ...)
2025-10-29 13:19 ` [PATCH v2 011/127] smb: smbdirect: introduce smbdirect_connection_disconnect_work() Stefan Metzmacher
@ 2025-10-29 13:19 ` Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 013/127] smb: smbdirect: introduce smbdirect_connection_{get,put}_recv_io() Stefan Metzmacher
` (115 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:19 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This is a copy of smbd_disconnect_rdma_connection() and
smb_direct_disconnect_rdma_connection(). It will replace
them in the next steps.
The only difference is that it gets an explicit error passed
in instead of hardcoding -ECONNABORTED.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 70 +++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index ebf47baa5d25..f96355043e16 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -6,6 +6,8 @@
#include "smbdirect_internal.h"
+static void smbdirect_connection_schedule_disconnect(struct smbdirect_socket *sc,
+ int error);
static void smbdirect_connection_disconnect_work(struct work_struct *work);
__maybe_unused /* this is temporary while this file is included in orders */
@@ -67,6 +69,74 @@ static void smbdirect_connection_wake_up_all(struct smbdirect_socket *sc)
wake_up_all(&sc->mr_io.cleanup.wait_queue);
}
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_connection_schedule_disconnect(struct smbdirect_socket *sc,
+ int error)
+{
+ /*
+ * make sure other work (than disconnect_work)
+ * is not queued again but here we don't block and avoid
+ * disable[_delayed]_work_sync()
+ */
+ disable_work(&sc->recv_io.posted.refill_work);
+ disable_work(&sc->mr_io.recovery_work);
+ disable_work(&sc->idle.immediate_work);
+ disable_delayed_work(&sc->idle.timer_work);
+
+ if (sc->first_error == 0)
+ sc->first_error = error;
+ if (sc->first_error == 0)
+ sc->first_error = -ECONNABORTED;
+
+ switch (sc->status) {
+ case SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED:
+ case SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED:
+ case SMBDIRECT_SOCKET_RDMA_CONNECT_FAILED:
+ case SMBDIRECT_SOCKET_NEGOTIATE_FAILED:
+ case SMBDIRECT_SOCKET_ERROR:
+ case SMBDIRECT_SOCKET_DISCONNECTING:
+ case SMBDIRECT_SOCKET_DISCONNECTED:
+ case SMBDIRECT_SOCKET_DESTROYED:
+ /*
+ * Keep the current error status
+ */
+ break;
+
+ case SMBDIRECT_SOCKET_RESOLVE_ADDR_NEEDED:
+ case SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING:
+ sc->status = SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED;
+ break;
+
+ case SMBDIRECT_SOCKET_RESOLVE_ROUTE_NEEDED:
+ case SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING:
+ sc->status = SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED;
+ break;
+
+ case SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED:
+ case SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING:
+ sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_FAILED;
+ break;
+
+ case SMBDIRECT_SOCKET_NEGOTIATE_NEEDED:
+ case SMBDIRECT_SOCKET_NEGOTIATE_RUNNING:
+ sc->status = SMBDIRECT_SOCKET_NEGOTIATE_FAILED;
+ break;
+
+ case SMBDIRECT_SOCKET_CREATED:
+ case SMBDIRECT_SOCKET_CONNECTED:
+ sc->status = SMBDIRECT_SOCKET_ERROR;
+ break;
+ }
+
+ /*
+ * Wake up all waiters in all wait queues
+ * in order to notice the broken connection.
+ */
+ smbdirect_connection_wake_up_all(sc);
+
+ queue_work(sc->workqueue, &sc->disconnect_work);
+}
+
static void smbdirect_connection_disconnect_work(struct work_struct *work)
{
struct smbdirect_socket *sc =
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 013/127] smb: smbdirect: introduce smbdirect_connection_{get,put}_recv_io()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (11 preceding siblings ...)
2025-10-29 13:19 ` [PATCH v2 012/127] smb: smbdirect: introduce smbdirect_connection_schedule_disconnect() Stefan Metzmacher
@ 2025-10-29 13:19 ` Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 014/127] smb: smbdirect: introduce smbdirect_connection_reassembly_{append,first}_recv_io() Stefan Metzmacher
` (114 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:19 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
These are basically copies of {get,put}_receive_buffer() in the client
and they are very similar to {get_free,put}_recvmsg() in the server.
The only difference to {get_free,put}_recvmsg() is the
updating of the sc->statistics.*.
In addition smbdirect_connection_get_recv_io() uses
list_first_entry_or_null() in order to simplify the code.
And smbdirect_connection_put_recv_io() uses msg->socket instead
of an explicit argument.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 41 +++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index f96355043e16..dc0a5cea67bf 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -69,6 +69,47 @@ static void smbdirect_connection_wake_up_all(struct smbdirect_socket *sc)
wake_up_all(&sc->mr_io.cleanup.wait_queue);
}
+__maybe_unused /* this is temporary while this file is included in orders */
+static struct smbdirect_recv_io *smbdirect_connection_get_recv_io(struct smbdirect_socket *sc)
+{
+ struct smbdirect_recv_io *msg = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&sc->recv_io.free.lock, flags);
+ msg = list_first_entry_or_null(&sc->recv_io.free.list,
+ struct smbdirect_recv_io,
+ list);
+ if (likely(msg)) {
+ list_del(&msg->list);
+ sc->statistics.get_receive_buffer++;
+ }
+ spin_unlock_irqrestore(&sc->recv_io.free.lock, flags);
+
+ return msg;
+}
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_connection_put_recv_io(struct smbdirect_recv_io *msg)
+{
+ struct smbdirect_socket *sc = msg->socket;
+ unsigned long flags;
+
+ if (likely(msg->sge.length != 0)) {
+ ib_dma_unmap_single(sc->ib.dev,
+ msg->sge.addr,
+ msg->sge.length,
+ DMA_FROM_DEVICE);
+ msg->sge.length = 0;
+ }
+
+ spin_lock_irqsave(&sc->recv_io.free.lock, flags);
+ list_add_tail(&msg->list, &sc->recv_io.free.list);
+ sc->statistics.put_receive_buffer++;
+ spin_unlock_irqrestore(&sc->recv_io.free.lock, flags);
+
+ queue_work(sc->workqueue, &sc->recv_io.posted.refill_work);
+}
+
__maybe_unused /* this is temporary while this file is included in orders */
static void smbdirect_connection_schedule_disconnect(struct smbdirect_socket *sc,
int error)
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 014/127] smb: smbdirect: introduce smbdirect_connection_reassembly_{append,first}_recv_io()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (12 preceding siblings ...)
2025-10-29 13:19 ` [PATCH v2 013/127] smb: smbdirect: introduce smbdirect_connection_{get,put}_recv_io() Stefan Metzmacher
@ 2025-10-29 13:19 ` Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 015/127] smb: smbdirect: introduce smbdirect_connection_idle_timer_work() Stefan Metzmacher
` (113 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:19 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
These are basically copies of enqueue_reassembly() and
[_]get_first_reassembly() of both client and server. The only difference
is that enqueue_reassembly() of the server does not have:
sc->statistics.enqueue_reassembly_queue++
Also smbdirect_connection_reassembly_first_recv_io() makes use of
list_first_entry_or_null() in order to simplify the code.
In the next commits they will replace the existing functions.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 35 +++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index dc0a5cea67bf..27f8545ee30d 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -110,6 +110,41 @@ static void smbdirect_connection_put_recv_io(struct smbdirect_recv_io *msg)
queue_work(sc->workqueue, &sc->recv_io.posted.refill_work);
}
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_connection_reassembly_append_recv_io(struct smbdirect_socket *sc,
+ struct smbdirect_recv_io *msg,
+ u32 data_length)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags);
+ list_add_tail(&msg->list, &sc->recv_io.reassembly.list);
+ sc->recv_io.reassembly.queue_length++;
+ /*
+ * Make sure reassembly_data_length is updated after list and
+ * reassembly_queue_length are updated. On the dequeue side
+ * reassembly_data_length is checked without a lock to determine
+ * if reassembly_queue_length and list is up to date
+ */
+ virt_wmb();
+ sc->recv_io.reassembly.data_length += data_length;
+ spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags);
+ sc->statistics.enqueue_reassembly_queue++;
+}
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static struct smbdirect_recv_io *
+smbdirect_connection_reassembly_first_recv_io(struct smbdirect_socket *sc)
+{
+ struct smbdirect_recv_io *msg;
+
+ msg = list_first_entry_or_null(&sc->recv_io.reassembly.list,
+ struct smbdirect_recv_io,
+ list);
+
+ return msg;
+}
+
__maybe_unused /* this is temporary while this file is included in orders */
static void smbdirect_connection_schedule_disconnect(struct smbdirect_socket *sc,
int error)
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 015/127] smb: smbdirect: introduce smbdirect_connection_idle_timer_work()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (13 preceding siblings ...)
2025-10-29 13:19 ` [PATCH v2 014/127] smb: smbdirect: introduce smbdirect_connection_reassembly_{append,first}_recv_io() Stefan Metzmacher
@ 2025-10-29 13:19 ` Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 016/127] smb: smbdirect: set SMBDIRECT_KEEPALIVE_NONE before disable_delayed_work(&sc->idle.timer_work); Stefan Metzmacher
` (112 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:19 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This is basically a copy of idle_connection_timer() in the client
and smb_direct_idle_connection_timer() in the server.
The only difference is that the server does not have logging.
Currently the callers set their own timer function after
smbdirect_socket_prepare_create(), but that will change
in the next steps...
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 34 +++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index 27f8545ee30d..79be89a3946e 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -9,6 +9,7 @@
static void smbdirect_connection_schedule_disconnect(struct smbdirect_socket *sc,
int error);
static void smbdirect_connection_disconnect_work(struct work_struct *work);
+static void smbdirect_connection_idle_timer_work(struct work_struct *work);
__maybe_unused /* this is temporary while this file is included in orders */
static void smbdirect_socket_prepare_create(struct smbdirect_socket *sc,
@@ -29,6 +30,8 @@ static void smbdirect_socket_prepare_create(struct smbdirect_socket *sc,
sc->workqueue = workqueue;
INIT_WORK(&sc->disconnect_work, smbdirect_connection_disconnect_work);
+
+ INIT_DELAYED_WORK(&sc->idle.timer_work, smbdirect_connection_idle_timer_work);
}
__maybe_unused /* this is temporary while this file is included in orders */
@@ -276,3 +279,34 @@ static void smbdirect_connection_disconnect_work(struct work_struct *work)
*/
smbdirect_connection_wake_up_all(sc);
}
+
+static void smbdirect_connection_idle_timer_work(struct work_struct *work)
+{
+ struct smbdirect_socket *sc =
+ container_of(work, struct smbdirect_socket, idle.timer_work.work);
+ const struct smbdirect_socket_parameters *sp = &sc->parameters;
+
+ if (sc->idle.keepalive != SMBDIRECT_KEEPALIVE_NONE) {
+ smbdirect_log_keep_alive(sc, SMBDIRECT_LOG_ERR,
+ "%s => timeout sc->idle.keepalive=%s\n",
+ smbdirect_socket_status_string(sc->status),
+ sc->idle.keepalive == SMBDIRECT_KEEPALIVE_SENT ?
+ "SENT" : "PENDING");
+ smbdirect_connection_schedule_disconnect(sc, -ETIMEDOUT);
+ return;
+ }
+
+ if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
+ return;
+
+ /*
+ * Now use the keepalive timeout (instead of keepalive interval)
+ * in order to wait for a response
+ */
+ sc->idle.keepalive = SMBDIRECT_KEEPALIVE_PENDING;
+ mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
+ msecs_to_jiffies(sp->keepalive_timeout_msec));
+ smbdirect_log_keep_alive(sc, SMBDIRECT_LOG_INFO,
+ "schedule send of empty idle message\n");
+ queue_work(sc->workqueue, &sc->idle.immediate_work);
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 016/127] smb: smbdirect: set SMBDIRECT_KEEPALIVE_NONE before disable_delayed_work(&sc->idle.timer_work);
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (14 preceding siblings ...)
2025-10-29 13:19 ` [PATCH v2 015/127] smb: smbdirect: introduce smbdirect_connection_idle_timer_work() Stefan Metzmacher
@ 2025-10-29 13:19 ` Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 017/127] smb: smbdirect: introduce smbdirect_frwr_is_supported() Stefan Metzmacher
` (111 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:19 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This avoids a potential confusing log message from
smbdirect_connection_idle_timer_work() if it's already running.
This is a very small race windows and not really needed, but it feels
better when reading the code.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/common/smbdirect/smbdirect_connection.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index 79be89a3946e..8d00a456c513 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -160,6 +160,7 @@ static void smbdirect_connection_schedule_disconnect(struct smbdirect_socket *sc
disable_work(&sc->recv_io.posted.refill_work);
disable_work(&sc->mr_io.recovery_work);
disable_work(&sc->idle.immediate_work);
+ sc->idle.keepalive = SMBDIRECT_KEEPALIVE_NONE;
disable_delayed_work(&sc->idle.timer_work);
if (sc->first_error == 0)
@@ -235,6 +236,7 @@ static void smbdirect_connection_disconnect_work(struct work_struct *work)
disable_work(&sc->recv_io.posted.refill_work);
disable_work(&sc->mr_io.recovery_work);
disable_work(&sc->idle.immediate_work);
+ sc->idle.keepalive = SMBDIRECT_KEEPALIVE_NONE;
disable_delayed_work(&sc->idle.timer_work);
if (sc->first_error == 0)
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 017/127] smb: smbdirect: introduce smbdirect_frwr_is_supported()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (15 preceding siblings ...)
2025-10-29 13:19 ` [PATCH v2 016/127] smb: smbdirect: set SMBDIRECT_KEEPALIVE_NONE before disable_delayed_work(&sc->idle.timer_work); Stefan Metzmacher
@ 2025-10-29 13:19 ` Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 018/127] smb: smbdirect: introduce smbdirect_socket.{send,recv}_io.mem.gfp_mask Stefan Metzmacher
` (110 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:19 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This will replace frwr_is_supported() on the client and
rdma_frwr_is_supported() on the server.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/common/smbdirect/smbdirect_connection.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index 8d00a456c513..e90aa3b72b44 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -11,6 +11,22 @@ static void smbdirect_connection_schedule_disconnect(struct smbdirect_socket *sc
static void smbdirect_connection_disconnect_work(struct work_struct *work);
static void smbdirect_connection_idle_timer_work(struct work_struct *work);
+__maybe_unused /* this is temporary while this file is included in orders */
+static bool smbdirect_frwr_is_supported(const struct ib_device_attr *attrs)
+{
+ /*
+ * Test if FRWR (Fast Registration Work Requests) is supported on the
+ * device This implementation requires FRWR on RDMA read/write return
+ * value: true if it is supported
+ */
+
+ if (!(attrs->device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS))
+ return false;
+ if (attrs->max_fast_reg_page_list_len == 0)
+ return false;
+ return true;
+}
+
__maybe_unused /* this is temporary while this file is included in orders */
static void smbdirect_socket_prepare_create(struct smbdirect_socket *sc,
const struct smbdirect_socket_parameters *sp,
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 018/127] smb: smbdirect: introduce smbdirect_socket.{send,recv}_io.mem.gfp_mask
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (16 preceding siblings ...)
2025-10-29 13:19 ` [PATCH v2 017/127] smb: smbdirect: introduce smbdirect_frwr_is_supported() Stefan Metzmacher
@ 2025-10-29 13:19 ` Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 019/127] smb: smbdirect: introduce smbdirect_connection_{alloc,free}_send_io() Stefan Metzmacher
` (109 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:19 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This will allow common code to be split out while still using the
gfp_mask currently used.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/common/smbdirect/smbdirect_socket.h | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/fs/smb/common/smbdirect/smbdirect_socket.h b/fs/smb/common/smbdirect/smbdirect_socket.h
index 65b21b65596f..a25bf92cfff7 100644
--- a/fs/smb/common/smbdirect/smbdirect_socket.h
+++ b/fs/smb/common/smbdirect/smbdirect_socket.h
@@ -150,8 +150,9 @@ struct smbdirect_socket {
* smbdirect_send_io buffers
*/
struct {
- struct kmem_cache *cache;
- mempool_t *pool;
+ struct kmem_cache *cache;
+ mempool_t *pool;
+ gfp_t gfp_mask;
} mem;
/*
@@ -204,8 +205,9 @@ struct smbdirect_socket {
* smbdirect_recv_io buffers
*/
struct {
- struct kmem_cache *cache;
- mempool_t *pool;
+ struct kmem_cache *cache;
+ mempool_t *pool;
+ gfp_t gfp_mask;
} mem;
/*
@@ -479,6 +481,8 @@ static __always_inline void smbdirect_socket_init(struct smbdirect_socket *sc)
INIT_DELAYED_WORK(&sc->idle.timer_work, __smbdirect_socket_disabled_work);
disable_delayed_work_sync(&sc->idle.timer_work);
+ sc->send_io.mem.gfp_mask = GFP_KERNEL;
+
atomic_set(&sc->send_io.lcredits.count, 0);
init_waitqueue_head(&sc->send_io.lcredits.wait_queue);
@@ -489,6 +493,8 @@ static __always_inline void smbdirect_socket_init(struct smbdirect_socket *sc)
init_waitqueue_head(&sc->send_io.pending.dec_wait_queue);
init_waitqueue_head(&sc->send_io.pending.zero_wait_queue);
+ sc->recv_io.mem.gfp_mask = GFP_KERNEL;
+
INIT_LIST_HEAD(&sc->recv_io.free.list);
spin_lock_init(&sc->recv_io.free.lock);
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 019/127] smb: smbdirect: introduce smbdirect_connection_{alloc,free}_send_io()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (17 preceding siblings ...)
2025-10-29 13:19 ` [PATCH v2 018/127] smb: smbdirect: introduce smbdirect_socket.{send,recv}_io.mem.gfp_mask Stefan Metzmacher
@ 2025-10-29 13:19 ` Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 020/127] smb: smbdirect: introduce smbdirect_connection_send_io_done() Stefan Metzmacher
` (108 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:19 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
These are more or less copies of smb_direct_{alloc,free}_sendmsg()
in the server.
The only difference is that we use ib_dma_unmap_page() for all sges,
this simplifies the logic and doesn't matter as
ib_dma_unmap_single() and ib_dma_unmap_page() both operate
on dma_addr_t and dma_unmap_single_attrs() is just an
alias for dma_unmap_page_attrs().
We already have in inconsistency like that in the client
code where we use ib_dma_unmap_single(), while we mapped
using ib_dma_map_page().
The new functions will replace the existing once in the next commits and
will also be used in the client.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 47 +++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index e90aa3b72b44..e5e8432f88e6 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -88,6 +88,53 @@ static void smbdirect_connection_wake_up_all(struct smbdirect_socket *sc)
wake_up_all(&sc->mr_io.cleanup.wait_queue);
}
+__maybe_unused /* this is temporary while this file is included in orders */
+static struct smbdirect_send_io *smbdirect_connection_alloc_send_io(struct smbdirect_socket *sc)
+{
+ struct smbdirect_send_io *msg;
+
+ msg = mempool_alloc(sc->send_io.mem.pool, sc->send_io.mem.gfp_mask);
+ if (!msg)
+ return ERR_PTR(-ENOMEM);
+ msg->socket = sc;
+ INIT_LIST_HEAD(&msg->sibling_list);
+ msg->num_sge = 0;
+
+ return msg;
+}
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_connection_free_send_io(struct smbdirect_send_io *msg)
+{
+ struct smbdirect_socket *sc = msg->socket;
+ size_t i;
+
+ /*
+ * The list needs to be empty!
+ * The caller should take care of it.
+ */
+ WARN_ON_ONCE(!list_empty(&msg->sibling_list));
+
+ /*
+ * Note we call ib_dma_unmap_page(), even if some sges are mapped using
+ * ib_dma_map_single().
+ *
+ * The difference between _single() and _page() only matters for the
+ * ib_dma_map_*() case.
+ *
+ * For the ib_dma_unmap_*() case it does not matter as both take the
+ * dma_addr_t and dma_unmap_single_attrs() is just an alias to
+ * dma_unmap_page_attrs().
+ */
+ for (i = 0; i < msg->num_sge; i++)
+ ib_dma_unmap_page(sc->ib.dev,
+ msg->sge[i].addr,
+ msg->sge[i].length,
+ DMA_TO_DEVICE);
+
+ mempool_free(msg, sc->send_io.mem.pool);
+}
+
__maybe_unused /* this is temporary while this file is included in orders */
static struct smbdirect_recv_io *smbdirect_connection_get_recv_io(struct smbdirect_socket *sc)
{
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 020/127] smb: smbdirect: introduce smbdirect_connection_send_io_done()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (18 preceding siblings ...)
2025-10-29 13:19 ` [PATCH v2 019/127] smb: smbdirect: introduce smbdirect_connection_{alloc,free}_send_io() Stefan Metzmacher
@ 2025-10-29 13:19 ` Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 021/127] smb: smbdirect: introduce smbdirect_connection_{create,destroy}_mem_pools() Stefan Metzmacher
` (107 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:19 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This is a combination of send_done() of client and server.
It will replace both...
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 43 +++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index e5e8432f88e6..05a68991587c 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -375,3 +375,46 @@ static void smbdirect_connection_idle_timer_work(struct work_struct *work)
"schedule send of empty idle message\n");
queue_work(sc->workqueue, &sc->idle.immediate_work);
}
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_connection_send_io_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+ struct smbdirect_send_io *msg =
+ container_of(wc->wr_cqe, struct smbdirect_send_io, cqe);
+ struct smbdirect_socket *sc = msg->socket;
+ struct smbdirect_send_io *sibling, *next;
+ int lcredits = 0;
+
+ smbdirect_log_rdma_send(sc, SMBDIRECT_LOG_INFO,
+ "smbdirect_send_io completed. status='%s (%d)', opcode=%d\n",
+ ib_wc_status_msg(wc->status), wc->status, wc->opcode);
+
+ /*
+ * Free possible siblings and then the main send_io
+ */
+ list_for_each_entry_safe(sibling, next, &msg->sibling_list, sibling_list) {
+ list_del_init(&sibling->sibling_list);
+ smbdirect_connection_free_send_io(sibling);
+ lcredits += 1;
+ }
+ /* Note this frees wc->wr_cqe, but not wc */
+ smbdirect_connection_free_send_io(msg);
+ lcredits += 1;
+
+ if (unlikely(wc->status != IB_WC_SUCCESS || WARN_ON_ONCE(wc->opcode != IB_WC_SEND))) {
+ if (wc->status != IB_WC_WR_FLUSH_ERR)
+ smbdirect_log_rdma_send(sc, SMBDIRECT_LOG_ERR,
+ "wc->status=%s (%d) wc->opcode=%d\n",
+ ib_wc_status_msg(wc->status), wc->status, wc->opcode);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+ return;
+ }
+
+ atomic_add(lcredits, &sc->send_io.lcredits.count);
+ wake_up(&sc->send_io.lcredits.wait_queue);
+
+ if (atomic_dec_and_test(&sc->send_io.pending.count))
+ wake_up(&sc->send_io.pending.zero_wait_queue);
+
+ wake_up(&sc->send_io.pending.dec_wait_queue);
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 021/127] smb: smbdirect: introduce smbdirect_connection_{create,destroy}_mem_pools()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (19 preceding siblings ...)
2025-10-29 13:19 ` [PATCH v2 020/127] smb: smbdirect: introduce smbdirect_connection_send_io_done() Stefan Metzmacher
@ 2025-10-29 13:19 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 022/127] smb: smbdirect: introduce smbdirect_map_sges_from_iter() and helper functions Stefan Metzmacher
` (106 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:19 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This is based on smb_direct_{create,destroy}_pools() in the server.
But it doesn't use smbdirect_connection_get_recv_io() on cleanup,
instead it uses list_for_each_entry_safe()...
It also keep some logic to allow userspace access to
smbdirect_recv_io payload, which is needed for the client
code. But it exposes the whole payload including the
smbdirect_data_transfer header as documentation says
data_offset = 0 and data_length != 0 would be valid,
while the existing client code requires data_offset >= 24.
This should replace the related server functions and also
be used on the client.
It also abstracts recv_io.mem.gfp_mask in order to
allow server to keep using __GFP_RETRY_MAYFAIL.
It also uses struct kmem_cache_args consistently
as that's the currently preferred version of
kmem_cache_create(). And it makes use of the
mempool_create_slab_pool() helper.
And it uses list_add_tail() just to let me feel
better when looking at the code...
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 107 ++++++++++++++++++
1 file changed, 107 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index 05a68991587c..dedc47916e0e 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -88,6 +88,113 @@ static void smbdirect_connection_wake_up_all(struct smbdirect_socket *sc)
wake_up_all(&sc->mr_io.cleanup.wait_queue);
}
+static void smbdirect_connection_destroy_mem_pools(struct smbdirect_socket *sc);
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static int smbdirect_connection_create_mem_pools(struct smbdirect_socket *sc)
+{
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+ char name[80];
+ size_t i;
+
+ /*
+ * We use sizeof(struct smbdirect_negotiate_resp) for the
+ * payload size as it is larger as
+ * sizeof(struct smbdirect_data_transfer).
+ *
+ * This will fit client and server usage for now.
+ */
+ snprintf(name, sizeof(name), "smbdirect_send_io_cache_%p", sc);
+ struct kmem_cache_args send_io_args = {
+ .align = __alignof__(struct smbdirect_send_io),
+ };
+ sc->send_io.mem.cache = kmem_cache_create(name,
+ sizeof(struct smbdirect_send_io) +
+ sizeof(struct smbdirect_negotiate_resp),
+ &send_io_args,
+ SLAB_HWCACHE_ALIGN);
+ if (!sc->send_io.mem.cache)
+ goto err;
+
+ sc->send_io.mem.pool = mempool_create_slab_pool(sp->send_credit_target,
+ sc->send_io.mem.cache);
+ if (!sc->send_io.mem.pool)
+ goto err;
+
+ /*
+ * A payload size of sp->max_recv_size should fit
+ * any message.
+ *
+ * For smbdirect_data_transfer messages the whole
+ * buffer might be exposed to userspace
+ * (currently on the client side...)
+ * The documentation says data_offset = 0 would be
+ * strange but valid.
+ */
+ snprintf(name, sizeof(name), "smbdirect_recv_io_cache_%p", sc);
+ struct kmem_cache_args recv_io_args = {
+ .align = __alignof__(struct smbdirect_recv_io),
+ .useroffset = sizeof(struct smbdirect_recv_io),
+ .usersize = sp->max_recv_size,
+ };
+ sc->recv_io.mem.cache = kmem_cache_create(name,
+ sizeof(struct smbdirect_recv_io) +
+ sp->max_recv_size,
+ &recv_io_args,
+ SLAB_HWCACHE_ALIGN);
+ if (!sc->recv_io.mem.cache)
+ goto err;
+
+ sc->recv_io.mem.pool = mempool_create_slab_pool(sp->recv_credit_max,
+ sc->recv_io.mem.cache);
+ if (!sc->recv_io.mem.pool)
+ goto err;
+
+ for (i = 0; i < sp->recv_credit_max; i++) {
+ struct smbdirect_recv_io *recv_io;
+
+ recv_io = mempool_alloc(sc->recv_io.mem.pool,
+ sc->recv_io.mem.gfp_mask);
+ if (!recv_io)
+ goto err;
+ recv_io->socket = sc;
+ recv_io->sge.length = 0;
+ list_add_tail(&recv_io->list, &sc->recv_io.free.list);
+ }
+
+ return 0;
+err:
+ smbdirect_connection_destroy_mem_pools(sc);
+ return -ENOMEM;
+}
+
+static void smbdirect_connection_destroy_mem_pools(struct smbdirect_socket *sc)
+{
+ struct smbdirect_recv_io *recv_io, *next_io;
+
+ list_for_each_entry_safe(recv_io, next_io, &sc->recv_io.free.list, list) {
+ list_del(&recv_io->list);
+ mempool_free(recv_io, sc->recv_io.mem.pool);
+ }
+
+ /*
+ * Note mempool_destroy() and kmem_cache_destroy()
+ * work fine with a NULL pointer
+ */
+
+ mempool_destroy(sc->recv_io.mem.pool);
+ sc->recv_io.mem.pool = NULL;
+
+ kmem_cache_destroy(sc->recv_io.mem.cache);
+ sc->recv_io.mem.cache = NULL;
+
+ mempool_destroy(sc->send_io.mem.pool);
+ sc->send_io.mem.pool = NULL;
+
+ kmem_cache_destroy(sc->send_io.mem.cache);
+ sc->send_io.mem.cache = NULL;
+}
+
__maybe_unused /* this is temporary while this file is included in orders */
static struct smbdirect_send_io *smbdirect_connection_alloc_send_io(struct smbdirect_socket *sc)
{
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 022/127] smb: smbdirect: introduce smbdirect_map_sges_from_iter() and helper functions
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (20 preceding siblings ...)
2025-10-29 13:19 ` [PATCH v2 021/127] smb: smbdirect: introduce smbdirect_connection_{create,destroy}_mem_pools() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 023/127] smb: smbdirect: introduce smbdirect_connection_qp_event_handler() Stefan Metzmacher
` (105 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
David Howells, Steve French
These are basically copies of smb_extract_iter_to_rdma() and its helpers
in the client, which will be replaced in the next steps.
The goal is to use them also in the server, which will simplify a lot.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: Namjae Jeon <linkinjeon@kernel.org>
Cc: David Howells <dhowells@redhat.com>
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>
---
.../common/smbdirect/smbdirect_connection.c | 255 ++++++++++++++++++
1 file changed, 255 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index dedc47916e0e..1113a7e9d575 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -5,6 +5,19 @@
*/
#include "smbdirect_internal.h"
+#include <linux/folio_queue.h>
+
+struct smbdirect_map_sges {
+ struct ib_sge *sge;
+ size_t num_sge;
+ size_t max_sge;
+ struct ib_device *device;
+ u32 local_dma_lkey;
+ enum dma_data_direction direction;
+};
+
+static ssize_t smbdirect_map_sges_from_iter(struct iov_iter *iter, size_t len,
+ struct smbdirect_map_sges *state);
static void smbdirect_connection_schedule_disconnect(struct smbdirect_socket *sc,
int error);
@@ -525,3 +538,245 @@ static void smbdirect_connection_send_io_done(struct ib_cq *cq, struct ib_wc *wc
wake_up(&sc->send_io.pending.dec_wait_queue);
}
+
+static bool smbdirect_map_sges_single_page(struct smbdirect_map_sges *state,
+ struct page *page, size_t off, size_t len)
+{
+ struct ib_sge *sge;
+ u64 addr;
+
+ if (state->num_sge >= state->max_sge)
+ return false;
+
+ addr = ib_dma_map_page(state->device, page,
+ off, len, state->direction);
+ if (ib_dma_mapping_error(state->device, addr))
+ return false;
+
+ sge = &state->sge[state->num_sge++];
+ sge->addr = addr;
+ sge->length = len;
+ sge->lkey = state->local_dma_lkey;
+
+ return true;
+}
+
+/*
+ * Extract page fragments from a BVEC-class iterator and add them to an ib_sge
+ * list. The pages are not pinned.
+ */
+static ssize_t smbdirect_map_sges_from_bvec(struct iov_iter *iter,
+ struct smbdirect_map_sges *state,
+ ssize_t maxsize)
+{
+ const struct bio_vec *bv = iter->bvec;
+ unsigned long start = iter->iov_offset;
+ unsigned int i;
+ ssize_t ret = 0;
+
+ for (i = 0; i < iter->nr_segs; i++) {
+ size_t off, len;
+ bool ok;
+
+ len = bv[i].bv_len;
+ if (start >= len) {
+ start -= len;
+ continue;
+ }
+
+ len = min_t(size_t, maxsize, len - start);
+ off = bv[i].bv_offset + start;
+
+ ok = smbdirect_map_sges_single_page(state,
+ bv[i].bv_page,
+ off,
+ len);
+ if (!ok)
+ return -EIO;
+
+ ret += len;
+ maxsize -= len;
+ if (state->num_sge >= state->max_sge || maxsize <= 0)
+ break;
+ start = 0;
+ }
+
+ if (ret > 0)
+ iov_iter_advance(iter, ret);
+ return ret;
+}
+
+/*
+ * Extract fragments from a KVEC-class iterator and add them to an ib_sge list.
+ * This can deal with vmalloc'd buffers as well as kmalloc'd or static buffers.
+ * The pages are not pinned.
+ */
+static ssize_t smbdirect_map_sges_from_kvec(struct iov_iter *iter,
+ struct smbdirect_map_sges *state,
+ ssize_t maxsize)
+{
+ const struct kvec *kv = iter->kvec;
+ unsigned long start = iter->iov_offset;
+ unsigned int i;
+ ssize_t ret = 0;
+
+ for (i = 0; i < iter->nr_segs; i++) {
+ struct page *page;
+ unsigned long kaddr;
+ size_t off, len, seg;
+
+ len = kv[i].iov_len;
+ if (start >= len) {
+ start -= len;
+ continue;
+ }
+
+ kaddr = (unsigned long)kv[i].iov_base + start;
+ off = kaddr & ~PAGE_MASK;
+ len = min_t(size_t, maxsize, len - start);
+ kaddr &= PAGE_MASK;
+
+ maxsize -= len;
+ do {
+ bool ok;
+
+ seg = min_t(size_t, len, PAGE_SIZE - off);
+
+ if (is_vmalloc_or_module_addr((void *)kaddr))
+ page = vmalloc_to_page((void *)kaddr);
+ else
+ page = virt_to_page((void *)kaddr);
+
+ ok = smbdirect_map_sges_single_page(state, page, off, seg);
+ if (!ok)
+ return -EIO;
+
+ ret += seg;
+ len -= seg;
+ kaddr += PAGE_SIZE;
+ off = 0;
+ } while (len > 0 && state->num_sge < state->max_sge);
+
+ if (state->num_sge >= state->max_sge || maxsize <= 0)
+ break;
+ start = 0;
+ }
+
+ if (ret > 0)
+ iov_iter_advance(iter, ret);
+ return ret;
+}
+
+/*
+ * Extract folio fragments from a FOLIOQ-class iterator and add them to an
+ * ib_sge list. The folios are not pinned.
+ */
+static ssize_t smbdirect_map_sges_from_folioq(struct iov_iter *iter,
+ struct smbdirect_map_sges *state,
+ ssize_t maxsize)
+{
+ const struct folio_queue *folioq = iter->folioq;
+ unsigned int slot = iter->folioq_slot;
+ ssize_t ret = 0;
+ size_t offset = iter->iov_offset;
+
+ if (WARN_ON_ONCE(!folioq))
+ return -EIO;
+
+ if (slot >= folioq_nr_slots(folioq)) {
+ folioq = folioq->next;
+ if (WARN_ON_ONCE(!folioq))
+ return -EIO;
+ slot = 0;
+ }
+
+ do {
+ struct folio *folio = folioq_folio(folioq, slot);
+ size_t fsize = folioq_folio_size(folioq, slot);
+
+ if (offset < fsize) {
+ size_t part = umin(maxsize, fsize - offset);
+ bool ok;
+
+ ok = smbdirect_map_sges_single_page(state,
+ folio_page(folio, 0),
+ offset,
+ part);
+ if (!ok)
+ return -EIO;
+
+ offset += part;
+ ret += part;
+ maxsize -= part;
+ }
+
+ if (offset >= fsize) {
+ offset = 0;
+ slot++;
+ if (slot >= folioq_nr_slots(folioq)) {
+ if (!folioq->next) {
+ WARN_ON_ONCE(ret < iter->count);
+ break;
+ }
+ folioq = folioq->next;
+ slot = 0;
+ }
+ }
+ } while (state->num_sge < state->max_sge && maxsize > 0);
+
+ iter->folioq = folioq;
+ iter->folioq_slot = slot;
+ iter->iov_offset = offset;
+ iter->count -= ret;
+ return ret;
+}
+
+/*
+ * Extract page fragments from up to the given amount of the source iterator
+ * and build up an ib_sge list that refers to all of those bits. The ib_sge list
+ * is appended to, up to the maximum number of elements set in the parameter
+ * block.
+ *
+ * The extracted page fragments are not pinned or ref'd in any way; if an
+ * IOVEC/UBUF-type iterator is to be used, it should be converted to a
+ * BVEC-type iterator and the pages pinned, ref'd or otherwise held in some
+ * way.
+ */
+__maybe_unused /* this is temporary while this file is included in orders */
+static ssize_t smbdirect_map_sges_from_iter(struct iov_iter *iter, size_t len,
+ struct smbdirect_map_sges *state)
+{
+ ssize_t ret;
+ size_t before = state->num_sge;
+
+ if (WARN_ON_ONCE(iov_iter_rw(iter) != ITER_SOURCE))
+ return -EIO;
+
+ switch (iov_iter_type(iter)) {
+ case ITER_BVEC:
+ ret = smbdirect_map_sges_from_bvec(iter, state, len);
+ break;
+ case ITER_KVEC:
+ ret = smbdirect_map_sges_from_kvec(iter, state, len);
+ break;
+ case ITER_FOLIOQ:
+ ret = smbdirect_map_sges_from_folioq(iter, state, len);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ return -EIO;
+ }
+
+ if (ret < 0) {
+ while (state->num_sge > before) {
+ struct ib_sge *sge = &state->sge[state->num_sge--];
+
+ ib_dma_unmap_page(state->device,
+ sge->addr,
+ sge->length,
+ state->direction);
+ }
+ }
+
+ return ret;
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 023/127] smb: smbdirect: introduce smbdirect_connection_qp_event_handler()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (21 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 022/127] smb: smbdirect: introduce smbdirect_map_sges_from_iter() and helper functions Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 024/127] smb: smbdirect: introduce smbdirect_connection_negotiate_rdma_resources() Stefan Metzmacher
` (104 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This is basically a copy of smbd_qp_async_error_upcall()
in the client and smb_direct_qpair_handler() in the server.
They will be replaced by the new common function soon,
which will allow more code to be moved as well.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 26 ++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index 1113a7e9d575..5afb27f790a5 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -101,6 +101,31 @@ static void smbdirect_connection_wake_up_all(struct smbdirect_socket *sc)
wake_up_all(&sc->mr_io.cleanup.wait_queue);
}
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_connection_qp_event_handler(struct ib_event *event, void *context)
+{
+ struct smbdirect_socket *sc = context;
+
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "%s on device %.*s socket %p (cm_id=%p) status %s first_error %1pe\n",
+ ib_event_msg(event->event),
+ IB_DEVICE_NAME_MAX,
+ event->device->name,
+ sc, sc->rdma.cm_id,
+ smbdirect_socket_status_string(sc->status),
+ SMBDIRECT_DEBUG_ERR_PTR(sc->first_error));
+
+ switch (event->event) {
+ case IB_EVENT_CQ_ERR:
+ case IB_EVENT_QP_FATAL:
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+ break;
+
+ default:
+ break;
+ }
+}
+
static void smbdirect_connection_destroy_mem_pools(struct smbdirect_socket *sc);
__maybe_unused /* this is temporary while this file is included in orders */
@@ -331,7 +356,6 @@ smbdirect_connection_reassembly_first_recv_io(struct smbdirect_socket *sc)
return msg;
}
-__maybe_unused /* this is temporary while this file is included in orders */
static void smbdirect_connection_schedule_disconnect(struct smbdirect_socket *sc,
int error)
{
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 024/127] smb: smbdirect: introduce smbdirect_connection_negotiate_rdma_resources()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (22 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 023/127] smb: smbdirect: introduce smbdirect_connection_qp_event_handler() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 025/127] smb: smbdirect: introduce smbdirect_connection_{create,destroy}_qp() Stefan Metzmacher
` (103 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This is a copy of the same logic used in client and server,
it's inlined there, but they will use the new helper function
soon.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 62 +++++++++++++++++++
1 file changed, 62 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index 5afb27f790a5..7a8a351d0484 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -356,6 +356,68 @@ smbdirect_connection_reassembly_first_recv_io(struct smbdirect_socket *sc)
return msg;
}
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_connection_negotiate_rdma_resources(struct smbdirect_socket *sc,
+ u8 peer_initiator_depth,
+ u8 peer_responder_resources,
+ const struct rdma_conn_param *param)
+{
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+
+ if (rdma_protocol_iwarp(sc->ib.dev, sc->rdma.cm_id->port_num) &&
+ param->private_data_len == 8) {
+ /*
+ * Legacy clients with only iWarp MPA v1 support
+ * need a private blob in order to negotiate
+ * the IRD/ORD values.
+ */
+ const __be32 *ird_ord_hdr = param->private_data;
+ u32 ird32 = be32_to_cpu(ird_ord_hdr[0]);
+ u32 ord32 = be32_to_cpu(ird_ord_hdr[1]);
+
+ /*
+ * cifs.ko sends the legacy IRD/ORD negotiation
+ * event if iWarp MPA v2 was used.
+ *
+ * Here we check that the values match and only
+ * mark the client as legacy if they don't match.
+ */
+ if ((u32)param->initiator_depth != ird32 ||
+ (u32)param->responder_resources != ord32) {
+ /*
+ * There are broken clients (old cifs.ko)
+ * using little endian and also
+ * struct rdma_conn_param only uses u8
+ * for initiator_depth and responder_resources,
+ * so we truncate the value to U8_MAX.
+ *
+ * smb_direct_accept_client() will then
+ * do the real negotiation in order to
+ * select the minimum between client and
+ * server.
+ */
+ ird32 = min_t(u32, ird32, U8_MAX);
+ ord32 = min_t(u32, ord32, U8_MAX);
+
+ sc->rdma.legacy_iwarp = true;
+ peer_initiator_depth = (u8)ird32;
+ peer_responder_resources = (u8)ord32;
+ }
+ }
+
+ /*
+ * negotiate the value by using the minimum
+ * between client and server if the client provided
+ * non 0 values.
+ */
+ if (peer_initiator_depth != 0)
+ sp->initiator_depth = min_t(u8, sp->initiator_depth,
+ peer_initiator_depth);
+ if (peer_responder_resources != 0)
+ sp->responder_resources = min_t(u8, sp->responder_resources,
+ peer_responder_resources);
+}
+
static void smbdirect_connection_schedule_disconnect(struct smbdirect_socket *sc,
int error)
{
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 025/127] smb: smbdirect: introduce smbdirect_connection_{create,destroy}_qp()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (23 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 024/127] smb: smbdirect: introduce smbdirect_connection_negotiate_rdma_resources() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 026/127] smb: smbdirect: introduce smbdirect_connection_post_recv_io() Stefan Metzmacher
` (102 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
smbdirect_connection_create_qp() is basically a copy of
smb_direct_create_qpair() in the server, it just adds
extra send_wr space for MR requests.
smbdirect_connection_destroy_qp() is the cleanup code
smb_direct_create_qpair() has, plus calling
ib_drain_qp(), it be a no-op if no requests are posted.
These additions allow the functions to be used by client and
server.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 214 ++++++++++++++++++
fs/smb/common/smbdirect/smbdirect_socket.h | 3 +
2 files changed, 217 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index 7a8a351d0484..448723d438af 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -126,6 +126,220 @@ static void smbdirect_connection_qp_event_handler(struct ib_event *event, void *
}
}
+static u32 smbdirect_rdma_rw_send_wrs(struct ib_device *dev,
+ const struct ib_qp_init_attr *attr)
+{
+ /*
+ * This could be split out of rdma_rw_init_qp()
+ * and be a helper function next to rdma_rw_mr_factor()
+ *
+ * We can't check unlikely(rdma_rw_force_mr) here,
+ * but that is most likely 0 anyway.
+ */
+ u32 factor;
+
+ WARN_ON_ONCE(attr->port_num == 0);
+
+ /*
+ * Each context needs at least one RDMA READ or WRITE WR.
+ *
+ * For some hardware we might need more, eventually we should ask the
+ * HCA driver for a multiplier here.
+ */
+ factor = 1;
+
+ /*
+ * If the device needs MRs to perform RDMA READ or WRITE operations,
+ * we'll need two additional MRs for the registrations and the
+ * invalidation.
+ */
+ if (rdma_protocol_iwarp(dev, attr->port_num) || dev->attrs.max_sgl_rd)
+ factor += 2; /* inv + reg */
+
+ return factor * attr->cap.max_rdma_ctxs;
+}
+
+static void smbdirect_connection_destroy_qp(struct smbdirect_socket *sc);
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static int smbdirect_connection_create_qp(struct smbdirect_socket *sc)
+{
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+ struct ib_qp_init_attr qp_attr;
+ struct ib_qp_cap qp_cap;
+ u32 rdma_send_wr;
+ u32 max_send_wr;
+ int ret;
+
+ /*
+ * Note that {rdma,ib}_create_qp() will call
+ * rdma_rw_init_qp() if max_rdma_ctxs is not 0.
+ * It will adjust max_send_wr to the required
+ * number of additional WRs for the RDMA RW operations.
+ * It will cap max_send_wr to the device limit.
+ *
+ * We use allocate sp->responder_resources * 2 MRs
+ * and each MR needs WRs for REG and INV, so
+ * we use '* 4'.
+ *
+ * +1 for ib_drain_qp()
+ */
+ memset(&qp_cap, 0, sizeof(qp_cap));
+ qp_cap.max_send_wr = sp->send_credit_target + sp->responder_resources * 4 + 1;
+ qp_cap.max_recv_wr = sp->recv_credit_max + 1;
+ qp_cap.max_send_sge = SMBDIRECT_SEND_IO_MAX_SGE;
+ qp_cap.max_recv_sge = SMBDIRECT_RECV_IO_MAX_SGE;
+ qp_cap.max_inline_data = 0;
+ qp_cap.max_rdma_ctxs = sc->rw_io.credits.max;
+
+ /*
+ * Find out the number of max_send_wr
+ * after rdma_rw_init_qp() adjusted it.
+ *
+ * We only do it on a temporary variable,
+ * as rdma_create_qp() will trigger
+ * rdma_rw_init_qp() again.
+ */
+ memset(&qp_attr, 0, sizeof(qp_attr));
+ qp_attr.cap = qp_cap;
+ qp_attr.port_num = sc->rdma.cm_id->port_num;
+ rdma_send_wr = smbdirect_rdma_rw_send_wrs(sc->ib.dev, &qp_attr);
+ max_send_wr = qp_cap.max_send_wr + rdma_send_wr;
+
+ if (qp_cap.max_send_wr > sc->ib.dev->attrs.max_cqe ||
+ qp_cap.max_send_wr > sc->ib.dev->attrs.max_qp_wr) {
+ pr_err("Possible CQE overrun: max_send_wr %d\n",
+ qp_cap.max_send_wr);
+ pr_err("device %.*s reporting max_cqe %d max_qp_wr %d\n",
+ IB_DEVICE_NAME_MAX,
+ sc->ib.dev->name,
+ sc->ib.dev->attrs.max_cqe,
+ sc->ib.dev->attrs.max_qp_wr);
+ pr_err("consider lowering send_credit_target = %d\n",
+ sp->send_credit_target);
+ return -EINVAL;
+ }
+
+ if (qp_cap.max_rdma_ctxs &&
+ (max_send_wr >= sc->ib.dev->attrs.max_cqe ||
+ max_send_wr >= sc->ib.dev->attrs.max_qp_wr)) {
+ pr_err("Possible CQE overrun: rdma_send_wr %d + max_send_wr %d = %d\n",
+ rdma_send_wr, qp_cap.max_send_wr, max_send_wr);
+ pr_err("device %.*s reporting max_cqe %d max_qp_wr %d\n",
+ IB_DEVICE_NAME_MAX,
+ sc->ib.dev->name,
+ sc->ib.dev->attrs.max_cqe,
+ sc->ib.dev->attrs.max_qp_wr);
+ pr_err("consider lowering send_credit_target = %d, max_rdma_ctxs = %d\n",
+ sp->send_credit_target, qp_cap.max_rdma_ctxs);
+ return -EINVAL;
+ }
+
+ if (qp_cap.max_recv_wr > sc->ib.dev->attrs.max_cqe ||
+ qp_cap.max_recv_wr > sc->ib.dev->attrs.max_qp_wr) {
+ pr_err("Possible CQE overrun: max_recv_wr %d\n",
+ qp_cap.max_recv_wr);
+ pr_err("device %.*s reporting max_cqe %d max_qp_wr %d\n",
+ IB_DEVICE_NAME_MAX,
+ sc->ib.dev->name,
+ sc->ib.dev->attrs.max_cqe,
+ sc->ib.dev->attrs.max_qp_wr);
+ pr_err("consider lowering receive_credit_max = %d\n",
+ sp->recv_credit_max);
+ return -EINVAL;
+ }
+
+ if (qp_cap.max_send_sge > sc->ib.dev->attrs.max_send_sge ||
+ qp_cap.max_recv_sge > sc->ib.dev->attrs.max_recv_sge) {
+ pr_err("device %.*s max_send_sge/max_recv_sge = %d/%d too small\n",
+ IB_DEVICE_NAME_MAX,
+ sc->ib.dev->name,
+ sc->ib.dev->attrs.max_send_sge,
+ sc->ib.dev->attrs.max_recv_sge);
+ return -EINVAL;
+ }
+
+ sc->ib.pd = ib_alloc_pd(sc->ib.dev, 0);
+ if (IS_ERR(sc->ib.pd)) {
+ pr_err("Can't create RDMA PD: %1pe\n", sc->ib.pd);
+ ret = PTR_ERR(sc->ib.pd);
+ sc->ib.pd = NULL;
+ return ret;
+ }
+
+ sc->ib.send_cq = ib_alloc_cq_any(sc->ib.dev, sc,
+ max_send_wr,
+ sc->ib.poll_ctx);
+ if (IS_ERR(sc->ib.send_cq)) {
+ pr_err("Can't create RDMA send CQ: %1pe\n", sc->ib.send_cq);
+ ret = PTR_ERR(sc->ib.send_cq);
+ sc->ib.send_cq = NULL;
+ goto err;
+ }
+
+ sc->ib.recv_cq = ib_alloc_cq_any(sc->ib.dev, sc,
+ qp_cap.max_recv_wr,
+ sc->ib.poll_ctx);
+ if (IS_ERR(sc->ib.recv_cq)) {
+ pr_err("Can't create RDMA recv CQ: %1pe\n", sc->ib.recv_cq);
+ ret = PTR_ERR(sc->ib.recv_cq);
+ sc->ib.recv_cq = NULL;
+ goto err;
+ }
+
+ /*
+ * We reset completely here!
+ * As the above use was just temporary
+ * to calc max_send_wr and rdma_send_wr.
+ *
+ * rdma_create_qp() will trigger rdma_rw_init_qp()
+ * again if max_rdma_ctxs is not 0.
+ */
+ memset(&qp_attr, 0, sizeof(qp_attr));
+ qp_attr.event_handler = smbdirect_connection_qp_event_handler;
+ qp_attr.qp_context = sc;
+ qp_attr.cap = qp_cap;
+ qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR;
+ qp_attr.qp_type = IB_QPT_RC;
+ qp_attr.send_cq = sc->ib.send_cq;
+ qp_attr.recv_cq = sc->ib.recv_cq;
+ qp_attr.port_num = ~0;
+
+ ret = rdma_create_qp(sc->rdma.cm_id, sc->ib.pd, &qp_attr);
+ if (ret) {
+ pr_err("Can't create RDMA QP: %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ goto err;
+ }
+ sc->ib.qp = sc->rdma.cm_id->qp;
+
+ return 0;
+err:
+ smbdirect_connection_destroy_qp(sc);
+ return ret;
+}
+
+static void smbdirect_connection_destroy_qp(struct smbdirect_socket *sc)
+{
+ if (sc->ib.qp) {
+ ib_drain_qp(sc->ib.qp);
+ sc->ib.qp = NULL;
+ rdma_destroy_qp(sc->rdma.cm_id);
+ }
+ if (sc->ib.recv_cq) {
+ ib_destroy_cq(sc->ib.recv_cq);
+ sc->ib.recv_cq = NULL;
+ }
+ if (sc->ib.send_cq) {
+ ib_destroy_cq(sc->ib.send_cq);
+ sc->ib.send_cq = NULL;
+ }
+ if (sc->ib.pd) {
+ ib_dealloc_pd(sc->ib.pd);
+ sc->ib.pd = NULL;
+ }
+}
+
static void smbdirect_connection_destroy_mem_pools(struct smbdirect_socket *sc);
__maybe_unused /* this is temporary while this file is included in orders */
diff --git a/fs/smb/common/smbdirect/smbdirect_socket.h b/fs/smb/common/smbdirect/smbdirect_socket.h
index a25bf92cfff7..5856ce287afa 100644
--- a/fs/smb/common/smbdirect/smbdirect_socket.h
+++ b/fs/smb/common/smbdirect/smbdirect_socket.h
@@ -120,6 +120,7 @@ struct smbdirect_socket {
/* IB verbs related */
struct {
struct ib_pd *pd;
+ enum ib_poll_context poll_ctx;
struct ib_cq *send_cq;
struct ib_cq *recv_cq;
@@ -476,6 +477,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->ib.poll_ctx = IB_POLL_UNBOUND_WORKQUEUE;
+
INIT_WORK(&sc->idle.immediate_work, __smbdirect_socket_disabled_work);
disable_work_sync(&sc->idle.immediate_work);
INIT_DELAYED_WORK(&sc->idle.timer_work, __smbdirect_socket_disabled_work);
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 026/127] smb: smbdirect: introduce smbdirect_connection_post_recv_io()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (24 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 025/127] smb: smbdirect: introduce smbdirect_connection_{create,destroy}_qp() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 027/127] smb: smbdirect: introduce smbdirect_connection_recv_io_refill_work() Stefan Metzmacher
` (101 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This is basically a copy of smbd_post_recv() in the client and
smb_direct_post_recv() in the server.
The only difference is that this returns early if the connection
is already broken.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 42 +++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index 448723d438af..959b0c49857f 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -839,6 +839,48 @@ static void smbdirect_connection_send_io_done(struct ib_cq *cq, struct ib_wc *wc
wake_up(&sc->send_io.pending.dec_wait_queue);
}
+__maybe_unused /* this is temporary while this file is included in orders */
+static int smbdirect_connection_post_recv_io(struct smbdirect_recv_io *msg)
+{
+ struct smbdirect_socket *sc = msg->socket;
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+ struct ib_recv_wr recv_wr = {
+ .wr_cqe = &msg->cqe,
+ .sg_list = &msg->sge,
+ .num_sge = 1,
+ };
+ int ret;
+
+ if (unlikely(sc->first_error))
+ return sc->first_error;
+
+ msg->sge.addr = ib_dma_map_single(sc->ib.dev,
+ msg->packet,
+ sp->max_recv_size,
+ DMA_FROM_DEVICE);
+ ret = ib_dma_mapping_error(sc->ib.dev, msg->sge.addr);
+ if (ret)
+ return ret;
+
+ msg->sge.length = sp->max_recv_size;
+ msg->sge.lkey = sc->ib.pd->local_dma_lkey;
+
+ ret = ib_post_recv(sc->ib.qp, &recv_wr, NULL);
+ if (ret) {
+ smbdirect_log_rdma_recv(sc, SMBDIRECT_LOG_ERR,
+ "ib_post_recv failed ret=%d (%s)\n",
+ ret, errname(ret));
+ ib_dma_unmap_single(sc->ib.dev,
+ msg->sge.addr,
+ msg->sge.length,
+ DMA_FROM_DEVICE);
+ msg->sge.length = 0;
+ smbdirect_connection_schedule_disconnect(sc, ret);
+ }
+
+ return ret;
+}
+
static bool smbdirect_map_sges_single_page(struct smbdirect_map_sges *state,
struct page *page, size_t off, size_t len)
{
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 027/127] smb: smbdirect: introduce smbdirect_connection_recv_io_refill_work()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (25 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 026/127] smb: smbdirect: introduce smbdirect_connection_post_recv_io() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 028/127] smb: smbdirect: split out smbdirect_connection_recv_io_refill() Stefan Metzmacher
` (100 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This is basically a copy of smbd_post_send_credits() in the client
and smb_direct_post_recv_credits() in the server.
There are several improvements compared to the existing functions:
1. We calculate the number of missing posted buffers by getting the
difference between recv_io.credits.target and recv_io.posted.count.
Instead of the difference between recv_io.credits.target
and recv_io.credits.count, because recv_io.credits.count is
only updated once a message is send to the peer.
It was not really a problem before, because we have
a fixed number smbdirect_recv_io buffers, so the
loop terminated when smbdirect_connection_get_recv_io()
returns NULL.
But using recv_io.posted.count makes it easier to
understand.
2. In order to tell the peer about the newly posted buffer
and grant the credits, we only trigger the send immediate
when we're not granting only the last possible credit.
This is mostly a difference relative to the servers
smb_direct_post_recv_credits() implementation,
which should avoid useless ping pong messages.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 92 +++++++++++++++++++
1 file changed, 92 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index 959b0c49857f..95e212877e9f 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -881,6 +881,98 @@ static int smbdirect_connection_post_recv_io(struct smbdirect_recv_io *msg)
return ret;
}
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_connection_recv_io_refill_work(struct work_struct *work)
+{
+ struct smbdirect_socket *sc =
+ container_of(work, struct smbdirect_socket, recv_io.posted.refill_work);
+ int missing;
+ int posted = 0;
+
+ if (unlikely(sc->first_error))
+ return;
+
+ /*
+ * Find out how much smbdirect_recv_io buffers we should post.
+ *
+ * Note that sc->recv_io.credits.target is the value
+ * from the peer and it can in theory change over time,
+ * but it is forced to be at least 1 and at max
+ * sp->recv_credit_max.
+ *
+ * So it can happen that missing will be lower than 0,
+ * which means the peer has recently lowered its desired
+ * tarted, while be already granted a higher number of credits.
+ *
+ * Note 'posted' is the number of smbdirect_recv_io buffers
+ * posted within this function, while sc->recv_io.posted.count
+ * is the overall value of posted smbdirect_recv_io buffers.
+ *
+ * We try to post as much buffers as missing, but
+ * this is limited if a lot of smbdirect_recv_io buffers
+ * are still in the sc->recv_io.reassembly.list instead of
+ * the sc->recv_io.free.list.
+ *
+ */
+ missing = (int)sc->recv_io.credits.target - atomic_read(&sc->recv_io.posted.count);
+ while (posted < missing) {
+ struct smbdirect_recv_io *recv_io;
+ int ret;
+
+ /*
+ * It's ok if smbdirect_connection_get_recv_io()
+ * returns NULL, it means smbdirect_recv_io structures
+ * are still be in the reassembly.list.
+ */
+ recv_io = smbdirect_connection_get_recv_io(sc);
+ if (!recv_io)
+ break;
+
+ recv_io->first_segment = false;
+
+ ret = smbdirect_connection_post_recv_io(recv_io);
+ if (ret) {
+ smbdirect_log_rdma_recv(sc, SMBDIRECT_LOG_ERR,
+ "smbdirect_connection_post_recv_io failed rc=%d (%s)\n",
+ ret, errname(ret));
+ smbdirect_connection_put_recv_io(recv_io);
+ return;
+ }
+
+ atomic_inc(&sc->recv_io.posted.count);
+ posted += 1;
+ }
+
+ /* If nothing was posted we're done */
+ if (posted == 0)
+ return;
+
+ /*
+ * If we posted at least one smbdirect_recv_io buffer,
+ * we need to inform the peer about it and grant
+ * additional credits.
+ *
+ * However there is one case where we don't want to
+ * do that.
+ *
+ * If only a single credit was missing before
+ * reaching the requested target, we should not
+ * post an immediate send, as that would cause
+ * endless ping pong once a keep alive exchange
+ * is started.
+ *
+ * However if sc->recv_io.credits.target is only 1,
+ * the peer has no credit left and we need to
+ * grant the credit anyway.
+ */
+ if (missing == 1 && sc->recv_io.credits.target != 1)
+ return;
+
+ smbdirect_log_keep_alive(sc, SMBDIRECT_LOG_INFO,
+ "schedule send of an empty message\n");
+ queue_work(sc->workqueue, &sc->idle.immediate_work);
+}
+
static bool smbdirect_map_sges_single_page(struct smbdirect_map_sges *state,
struct page *page, size_t off, size_t len)
{
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 028/127] smb: smbdirect: split out smbdirect_connection_recv_io_refill()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (26 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 027/127] smb: smbdirect: introduce smbdirect_connection_recv_io_refill_work() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 029/127] smb: smbdirect: introduce smbdirect_get_buf_page_count() Stefan Metzmacher
` (99 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This will allow us to refill the recv queue in a sync way
after negotiation.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 36 +++++++++++++------
1 file changed, 25 insertions(+), 11 deletions(-)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index 95e212877e9f..c1281807ff8c 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -881,16 +881,13 @@ static int smbdirect_connection_post_recv_io(struct smbdirect_recv_io *msg)
return ret;
}
-__maybe_unused /* this is temporary while this file is included in orders */
-static void smbdirect_connection_recv_io_refill_work(struct work_struct *work)
+static int smbdirect_connection_recv_io_refill(struct smbdirect_socket *sc)
{
- struct smbdirect_socket *sc =
- container_of(work, struct smbdirect_socket, recv_io.posted.refill_work);
int missing;
int posted = 0;
if (unlikely(sc->first_error))
- return;
+ return sc->first_error;
/*
* Find out how much smbdirect_recv_io buffers we should post.
@@ -936,7 +933,7 @@ static void smbdirect_connection_recv_io_refill_work(struct work_struct *work)
"smbdirect_connection_post_recv_io failed rc=%d (%s)\n",
ret, errname(ret));
smbdirect_connection_put_recv_io(recv_io);
- return;
+ return ret;
}
atomic_inc(&sc->recv_io.posted.count);
@@ -945,7 +942,7 @@ static void smbdirect_connection_recv_io_refill_work(struct work_struct *work)
/* If nothing was posted we're done */
if (posted == 0)
- return;
+ return 0;
/*
* If we posted at least one smbdirect_recv_io buffer,
@@ -966,11 +963,28 @@ static void smbdirect_connection_recv_io_refill_work(struct work_struct *work)
* grant the credit anyway.
*/
if (missing == 1 && sc->recv_io.credits.target != 1)
- return;
+ return 0;
- smbdirect_log_keep_alive(sc, SMBDIRECT_LOG_INFO,
- "schedule send of an empty message\n");
- queue_work(sc->workqueue, &sc->idle.immediate_work);
+ return posted;
+}
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_connection_recv_io_refill_work(struct work_struct *work)
+{
+ struct smbdirect_socket *sc =
+ container_of(work, struct smbdirect_socket, recv_io.posted.refill_work);
+ int posted;
+
+ posted = smbdirect_connection_recv_io_refill(sc);
+ if (unlikely(posted < 0)) {
+ smbdirect_connection_schedule_disconnect(sc, posted);
+ return;
+ }
+ if (posted > 0) {
+ smbdirect_log_keep_alive(sc, SMBDIRECT_LOG_INFO,
+ "schedule send of an empty message\n");
+ queue_work(sc->workqueue, &sc->idle.immediate_work);
+ }
}
static bool smbdirect_map_sges_single_page(struct smbdirect_map_sges *state,
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 029/127] smb: smbdirect: introduce smbdirect_get_buf_page_count()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (27 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 028/127] smb: smbdirect: split out smbdirect_connection_recv_io_refill() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 030/127] smb: smbdirect: introduce smbdirect_connection_wait_for_credits() Stefan Metzmacher
` (98 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This is a copy of get_buf_page_count() in the server
and will replace it soon.
The only difference is that we now use size_t instead
of int.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/common/smbdirect/smbdirect_socket.h | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_socket.h b/fs/smb/common/smbdirect/smbdirect_socket.h
index 5856ce287afa..983e08c8d2ee 100644
--- a/fs/smb/common/smbdirect/smbdirect_socket.h
+++ b/fs/smb/common/smbdirect/smbdirect_socket.h
@@ -640,4 +640,10 @@ struct smbdirect_rw_io {
struct scatterlist sg_list[];
};
+static inline size_t smbdirect_get_buf_page_count(const void *buf, size_t size)
+{
+ return DIV_ROUND_UP((uintptr_t)buf + size, PAGE_SIZE) -
+ (uintptr_t)buf / PAGE_SIZE;
+}
+
#endif /* __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_SOCKET_H__ */
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 030/127] smb: smbdirect: introduce smbdirect_connection_wait_for_credits()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (28 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 029/127] smb: smbdirect: introduce smbdirect_get_buf_page_count() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 031/127] smb: smbdirect: introduce smbdirect_mr.c with client mr code Stefan Metzmacher
` (97 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This is a copy of wait_for_credits() in the server, which
will be replaced by this soon.
This will allow us to share more common code between client
and server soon.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 27 +++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index c1281807ff8c..1b84e0789d77 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -796,6 +796,33 @@ static void smbdirect_connection_idle_timer_work(struct work_struct *work)
queue_work(sc->workqueue, &sc->idle.immediate_work);
}
+__maybe_unused /* this is temporary while this file is included in orders */
+static int smbdirect_connection_wait_for_credits(struct smbdirect_socket *sc,
+ wait_queue_head_t *waitq,
+ atomic_t *total_credits,
+ int needed)
+{
+ int ret;
+
+ if (WARN_ON_ONCE(needed < 0))
+ return -EINVAL;
+
+ do {
+ if (atomic_sub_return(needed, total_credits) >= 0)
+ return 0;
+
+ atomic_add(needed, total_credits);
+ ret = wait_event_interruptible(*waitq,
+ atomic_read(total_credits) >= needed ||
+ sc->status != SMBDIRECT_SOCKET_CONNECTED);
+
+ if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
+ return -ENOTCONN;
+ else if (ret < 0)
+ return ret;
+ } while (true);
+}
+
__maybe_unused /* this is temporary while this file is included in orders */
static void smbdirect_connection_send_io_done(struct ib_cq *cq, struct ib_wc *wc)
{
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 031/127] smb: smbdirect: introduce smbdirect_mr.c with client mr code
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (29 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 030/127] smb: smbdirect: introduce smbdirect_connection_wait_for_credits() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 032/127] smb: smbdirect: introduce smbdirect_rw.c with server rw code Stefan Metzmacher
` (96 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This is basically contains the following functions copied from
the client: destroy_mr_list, allocate_mr_list, register_mr_done,
smbd_mr_recovery_work, get_mr, smbd_iter_to_mr, smbd_register_mr
and smbd_deregister_mr.
They got new names, some indentation/formatting changes,
some variable names are changed too.
They also only use struct smbdirect_socket instead of
struct smbd_connection.
But the logic is still the same. They will be used
by the client soon.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_all_c_files.c | 1 +
fs/smb/common/smbdirect/smbdirect_mr.c | 544 ++++++++++++++++++
2 files changed, 545 insertions(+)
create mode 100644 fs/smb/common/smbdirect/smbdirect_mr.c
diff --git a/fs/smb/common/smbdirect/smbdirect_all_c_files.c b/fs/smb/common/smbdirect/smbdirect_all_c_files.c
index ba92f0813932..15022ca39815 100644
--- a/fs/smb/common/smbdirect/smbdirect_all_c_files.c
+++ b/fs/smb/common/smbdirect/smbdirect_all_c_files.c
@@ -16,3 +16,4 @@
#error SMBDIRECT_USE_INLINE_C_FILES define needed
#endif
#include "smbdirect_connection.c"
+#include "smbdirect_mr.c"
diff --git a/fs/smb/common/smbdirect/smbdirect_mr.c b/fs/smb/common/smbdirect/smbdirect_mr.c
new file mode 100644
index 000000000000..5fd6a853e656
--- /dev/null
+++ b/fs/smb/common/smbdirect/smbdirect_mr.c
@@ -0,0 +1,544 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2017, Microsoft Corporation.
+ * Copyright (c) 2025, Stefan Metzmacher
+ */
+
+#include "smbdirect_internal.h"
+
+static void smbdirect_connection_destroy_mr_list(struct smbdirect_socket *sc);
+static void smbdirect_connection_mr_io_recovery_work(struct work_struct *work);
+
+/*
+ * Allocate MRs used for RDMA read/write
+ * The number of MRs will not exceed hardware capability in responder_resources
+ * All MRs are kept in mr_list. The MR can be recovered after it's used
+ * Recovery is done in smbd_mr_recovery_work. The content of list entry changes
+ * as MRs are used and recovered for I/O, but the list links will not change
+ */
+__maybe_unused /* this is temporary while this file is included in orders */
+static int smbdirect_connection_create_mr_list(struct smbdirect_socket *sc)
+{
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+ struct smbdirect_mr_io *mr;
+ int ret;
+ u32 i;
+
+ if (sp->responder_resources == 0) {
+ smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
+ "responder_resources negotiated as 0\n");
+ return -EINVAL;
+ }
+
+ /* Allocate more MRs (2x) than hardware responder_resources */
+ for (i = 0; i < sp->responder_resources * 2; i++) {
+ mr = kzalloc(sizeof(*mr), GFP_KERNEL);
+ if (!mr) {
+ ret = -ENOMEM;
+ goto kzalloc_mr_failed;
+ }
+
+ kref_init(&mr->kref);
+ mutex_init(&mr->mutex);
+
+ mr->mr = ib_alloc_mr(sc->ib.pd,
+ sc->mr_io.type,
+ sp->max_frmr_depth);
+ if (IS_ERR(mr->mr)) {
+ ret = PTR_ERR(mr->mr);
+ smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
+ "ib_alloc_mr failed ret=%d (%s) type=0x%x max_frmr_depth=%u\n",
+ ret, errname(ret), sc->mr_io.type, sp->max_frmr_depth);
+ goto ib_alloc_mr_failed;
+ }
+ mr->sgt.sgl = kcalloc(sp->max_frmr_depth,
+ sizeof(struct scatterlist),
+ GFP_KERNEL);
+ if (!mr->sgt.sgl) {
+ ret = -ENOMEM;
+ smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
+ "failed to allocate sgl, max_frmr_depth=%u\n",
+ sp->max_frmr_depth);
+ goto kcalloc_sgl_failed;
+ }
+ mr->state = SMBDIRECT_MR_READY;
+ mr->socket = sc;
+
+ list_add_tail(&mr->list, &sc->mr_io.all.list);
+ atomic_inc(&sc->mr_io.ready.count);
+ }
+
+ INIT_WORK(&sc->mr_io.recovery_work, smbdirect_connection_mr_io_recovery_work);
+
+ return 0;
+
+kcalloc_sgl_failed:
+ ib_dereg_mr(mr->mr);
+ib_alloc_mr_failed:
+ mutex_destroy(&mr->mutex);
+ kfree(mr);
+kzalloc_mr_failed:
+ smbdirect_connection_destroy_mr_list(sc);
+ return ret;
+}
+
+static void smbdirect_mr_io_disable_locked(struct smbdirect_mr_io *mr)
+{
+ struct smbdirect_socket *sc = mr->socket;
+
+ lockdep_assert_held(&mr->mutex);
+
+ if (mr->state == SMBDIRECT_MR_DISABLED)
+ return;
+
+ if (mr->mr)
+ ib_dereg_mr(mr->mr);
+ if (mr->sgt.nents)
+ ib_dma_unmap_sg(sc->ib.dev, mr->sgt.sgl, mr->sgt.nents, mr->dir);
+ kfree(mr->sgt.sgl);
+
+ mr->mr = NULL;
+ mr->sgt.sgl = NULL;
+ mr->sgt.nents = 0;
+
+ mr->state = SMBDIRECT_MR_DISABLED;
+}
+
+static void smbdirect_mr_io_free_locked(struct kref *kref)
+{
+ struct smbdirect_mr_io *mr =
+ container_of(kref, struct smbdirect_mr_io, kref);
+
+ lockdep_assert_held(&mr->mutex);
+
+ /*
+ * smbdirect_mr_io_disable_locked() should already be called!
+ */
+ if (WARN_ON_ONCE(mr->state != SMBDIRECT_MR_DISABLED))
+ smbdirect_mr_io_disable_locked(mr);
+
+ mutex_unlock(&mr->mutex);
+ mutex_destroy(&mr->mutex);
+ kfree(mr);
+}
+
+static void smbdirect_connection_destroy_mr_list(struct smbdirect_socket *sc)
+{
+ struct smbdirect_mr_io *mr, *tmp;
+ LIST_HEAD(all_list);
+ unsigned long flags;
+
+ disable_work_sync(&sc->mr_io.recovery_work);
+
+ spin_lock_irqsave(&sc->mr_io.all.lock, flags);
+ list_splice_tail_init(&sc->mr_io.all.list, &all_list);
+ spin_unlock_irqrestore(&sc->mr_io.all.lock, flags);
+
+ list_for_each_entry_safe(mr, tmp, &all_list, list) {
+ mutex_lock(&mr->mutex);
+
+ smbdirect_mr_io_disable_locked(mr);
+ list_del(&mr->list);
+ mr->socket = NULL;
+
+ /*
+ * No kref_put_mutex() as it's already locked.
+ *
+ * If smbdirect_mr_io_free_locked() is called
+ * and the mutex is unlocked and mr is gone,
+ * in that case kref_put() returned 1.
+ *
+ * If kref_put() returned 0 we know that
+ * smbdirect_mr_io_free_locked() didn't
+ * run. Not by us nor by anyone else, as we
+ * still hold the mutex, so we need to unlock.
+ *
+ * If the mr is still registered it will
+ * be dangling (detached from the connection
+ * waiting for smbd_deregister_mr() to be
+ * called in order to free the memory.
+ */
+ if (!kref_put(&mr->kref, smbdirect_mr_io_free_locked))
+ mutex_unlock(&mr->mutex);
+ }
+}
+
+/*
+ * Get a MR from mr_list. This function waits until there is at least one MR
+ * available in the list. It may access the list while the
+ * smbdirect_connection_mr_io_recovery_work is recovering the MR list. This
+ * doesn't need a lock as they never modify the same places. However, there may
+ * be several CPUs issuing I/O trying to get MR at the same time, mr_list_lock
+ * is used to protect this situation.
+ */
+static struct smbdirect_mr_io *
+smbdirect_connection_get_mr_io(struct smbdirect_socket *sc)
+{
+ struct smbdirect_mr_io *mr;
+ unsigned long flags;
+ int ret;
+
+again:
+ ret = wait_event_interruptible(sc->mr_io.ready.wait_queue,
+ atomic_read(&sc->mr_io.ready.count) ||
+ sc->status != SMBDIRECT_SOCKET_CONNECTED);
+ if (ret) {
+ smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
+ "wait_event_interruptible ret=%d (%s)\n",
+ ret, errname(ret));
+ return NULL;
+ }
+
+ if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
+ smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
+ "sc->status=%s sc->first_error=%1pe\n",
+ smbdirect_socket_status_string(sc->status),
+ SMBDIRECT_DEBUG_ERR_PTR(sc->first_error));
+ return NULL;
+ }
+
+ spin_lock_irqsave(&sc->mr_io.all.lock, flags);
+ list_for_each_entry(mr, &sc->mr_io.all.list, list) {
+ if (mr->state == SMBDIRECT_MR_READY) {
+ mr->state = SMBDIRECT_MR_REGISTERED;
+ kref_get(&mr->kref);
+ spin_unlock_irqrestore(&sc->mr_io.all.lock, flags);
+ atomic_dec(&sc->mr_io.ready.count);
+ atomic_inc(&sc->mr_io.used.count);
+ return mr;
+ }
+ }
+
+ spin_unlock_irqrestore(&sc->mr_io.all.lock, flags);
+ /*
+ * It is possible that we could fail to get MR because other processes may
+ * try to acquire a MR at the same time. If this is the case, retry it.
+ */
+ goto again;
+}
+
+static void smbdirect_connection_mr_io_register_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+ struct smbdirect_mr_io *mr =
+ container_of(wc->wr_cqe, struct smbdirect_mr_io, cqe);
+ struct smbdirect_socket *sc = mr->socket;
+
+ if (wc->status != IB_WC_SUCCESS) {
+ smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
+ "wc->status=%s opcode=%d\n",
+ ib_wc_status_msg(wc->status), wc->opcode);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+ }
+}
+
+static void smbdirect_connection_mr_io_local_inv_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+ struct smbdirect_mr_io *mr =
+ container_of(wc->wr_cqe, struct smbdirect_mr_io, cqe);
+ struct smbdirect_socket *sc = mr->socket;
+
+ mr->state = SMBDIRECT_MR_INVALIDATED;
+ if (wc->status != IB_WC_SUCCESS) {
+ smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
+ "invalidate failed status=%s\n",
+ ib_wc_status_msg(wc->status));
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+ }
+ complete(&mr->invalidate_done);
+}
+
+/*
+ * The work queue function that recovers MRs
+ * We need to call ib_dereg_mr() and ib_alloc_mr() before this MR can be used
+ * again. Both calls are slow, so finish them in a workqueue. This will not
+ * block I/O path.
+ * There is one workqueue that recovers MRs, there is no need to lock as the
+ * I/O requests calling smbd_register_mr will never update the links in the
+ * mr_list.
+ */
+static void smbdirect_connection_mr_io_recovery_work(struct work_struct *work)
+{
+ struct smbdirect_socket *sc =
+ container_of(work, struct smbdirect_socket, mr_io.recovery_work);
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+ struct smbdirect_mr_io *mr;
+ int ret;
+
+ list_for_each_entry(mr, &sc->mr_io.all.list, list) {
+ if (mr->state != SMBDIRECT_MR_ERROR)
+ /* This MR is being used, don't recover it */
+ continue;
+
+ /* recover this MR entry */
+ ret = ib_dereg_mr(mr->mr);
+ if (ret) {
+ smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
+ "ib_dereg_mr failed ret=%u (%s)\n",
+ ret, errname(ret));
+ smbdirect_connection_schedule_disconnect(sc, ret);
+ continue;
+ }
+
+ mr->mr = ib_alloc_mr(sc->ib.pd,
+ sc->mr_io.type,
+ sp->max_frmr_depth);
+ if (IS_ERR(mr->mr)) {
+ ret = PTR_ERR(mr->mr);
+ smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
+ "ib_alloc_mr failed ret=%d (%s) type=0x%x depth=%u\n",
+ ret, errname(ret), sc->mr_io.type, sp->max_frmr_depth);
+ smbdirect_connection_schedule_disconnect(sc, ret);
+ continue;
+ }
+
+ mr->state = SMBDIRECT_MR_READY;
+
+ /* smbdirect_mr->state is updated by this function
+ * and is read and updated by I/O issuing CPUs trying
+ * to get a MR, the call to atomic_inc_return
+ * implicates a memory barrier and guarantees this
+ * value is updated before waking up any calls to
+ * get_mr() from the I/O issuing CPUs
+ */
+ if (atomic_inc_return(&sc->mr_io.ready.count) == 1)
+ wake_up(&sc->mr_io.ready.wait_queue);
+ }
+}
+
+/*
+ * Transcribe the pages from an iterator into an MR scatterlist.
+ */
+static int smbdirect_iter_to_sgt(struct iov_iter *iter,
+ struct sg_table *sgt,
+ unsigned int max_sg)
+{
+ int ret;
+
+ memset(sgt->sgl, 0, max_sg * sizeof(struct scatterlist));
+
+ ret = extract_iter_to_sg(iter, iov_iter_count(iter), sgt, max_sg, 0);
+ WARN_ON(ret < 0);
+ if (sgt->nents > 0)
+ sg_mark_end(&sgt->sgl[sgt->nents - 1]);
+
+ return ret;
+}
+
+/*
+ * Register memory for RDMA read/write
+ * iter: the buffer to register memory with
+ * writing: true if this is a RDMA write (SMB read), false for RDMA read
+ * need_invalidate: true if this MR needs to be locally invalidated after I/O
+ * return value: the MR registered, NULL if failed.
+ */
+__maybe_unused /* this is temporary while this file is included in orders */
+static struct smbdirect_mr_io *
+smbdirect_connection_register_mr_io(struct smbdirect_socket *sc,
+ struct iov_iter *iter,
+ bool writing,
+ bool need_invalidate)
+{
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+ struct smbdirect_mr_io *mr;
+ int ret, num_pages;
+ struct ib_reg_wr *reg_wr;
+
+ num_pages = iov_iter_npages(iter, sp->max_frmr_depth + 1);
+ if (num_pages > sp->max_frmr_depth) {
+ smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
+ "num_pages=%d max_frmr_depth=%d\n",
+ num_pages, sp->max_frmr_depth);
+ WARN_ON_ONCE(1);
+ return NULL;
+ }
+
+ mr = smbdirect_connection_get_mr_io(sc);
+ if (!mr) {
+ smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
+ "smbdirect_connection_get_mr_io returning NULL\n");
+ return NULL;
+ }
+
+ mutex_lock(&mr->mutex);
+
+ mr->dir = writing ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+ mr->need_invalidate = need_invalidate;
+ mr->sgt.nents = 0;
+ mr->sgt.orig_nents = 0;
+
+ smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_INFO,
+ "num_pages=%u count=%zu depth=%u\n",
+ num_pages, iov_iter_count(iter), sp->max_frmr_depth);
+ smbdirect_iter_to_sgt(iter, &mr->sgt, sp->max_frmr_depth);
+
+ ret = ib_dma_map_sg(sc->ib.dev, mr->sgt.sgl, mr->sgt.nents, mr->dir);
+ if (!ret) {
+ smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
+ "ib_dma_map_sg num_pages=%u dir=%x ret=%d (%s)\n",
+ num_pages, mr->dir, ret, errname(ret));
+ goto dma_map_error;
+ }
+
+ ret = ib_map_mr_sg(mr->mr, mr->sgt.sgl, mr->sgt.nents, NULL, PAGE_SIZE);
+ if (ret != mr->sgt.nents) {
+ smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
+ "ib_map_mr_sg failed ret = %d nents = %u\n",
+ ret, mr->sgt.nents);
+ goto map_mr_error;
+ }
+
+ ib_update_fast_reg_key(mr->mr, ib_inc_rkey(mr->mr->rkey));
+ reg_wr = &mr->wr;
+ reg_wr->wr.opcode = IB_WR_REG_MR;
+ mr->cqe.done = smbdirect_connection_mr_io_register_done;
+ reg_wr->wr.wr_cqe = &mr->cqe;
+ reg_wr->wr.num_sge = 0;
+ reg_wr->wr.send_flags = IB_SEND_SIGNALED;
+ reg_wr->mr = mr->mr;
+ reg_wr->key = mr->mr->rkey;
+ reg_wr->access = writing ?
+ IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE :
+ IB_ACCESS_REMOTE_READ;
+
+ /*
+ * There is no need for waiting for complemtion on ib_post_send
+ * on IB_WR_REG_MR. Hardware enforces a barrier and order of execution
+ * on the next ib_post_send when we actually send I/O to remote peer
+ */
+ ret = ib_post_send(sc->ib.qp, ®_wr->wr, NULL);
+ if (!ret) {
+ /*
+ * smbdirect_connection_get_mr_io() gave us a reference
+ * via kref_get(&mr->kref), we keep that and let
+ * the caller use smbdirect_connection_deregister_mr_io()
+ * to remove it again.
+ */
+ mutex_unlock(&mr->mutex);
+ return mr;
+ }
+
+ smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
+ "ib_post_send failed ret=%d (%s) reg_wr->key=0x%x\n",
+ ret, errname(ret), reg_wr->key);
+
+ /* If all failed, attempt to recover this MR by setting it SMBDIRECT_MR_ERROR*/
+map_mr_error:
+ ib_dma_unmap_sg(sc->ib.dev, mr->sgt.sgl, mr->sgt.nents, mr->dir);
+
+dma_map_error:
+ mr->sgt.nents = 0;
+ mr->state = SMBDIRECT_MR_ERROR;
+ if (atomic_dec_and_test(&sc->mr_io.used.count))
+ wake_up(&sc->mr_io.cleanup.wait_queue);
+
+ smbdirect_connection_schedule_disconnect(sc, ret);
+
+ /*
+ * smbdirect_connection_get_mr_io() gave us a reference
+ * via kref_get(&mr->kref), we need to remove it again
+ * on error.
+ *
+ * No kref_put_mutex() as it's already locked.
+ *
+ * If smbdirect_mr_io_free_locked() is called
+ * and the mutex is unlocked and mr is gone,
+ * in that case kref_put() returned 1.
+ *
+ * If kref_put() returned 0 we know that
+ * smbdirect_mr_io_free_locked() didn't
+ * run. Not by us nor by anyone else, as we
+ * still hold the mutex, so we need to unlock.
+ */
+ if (!kref_put(&mr->kref, smbdirect_mr_io_free_locked))
+ mutex_unlock(&mr->mutex);
+ return NULL;
+}
+/*
+ * Deregister a MR after I/O is done
+ * This function may wait if remote invalidation is not used
+ * and we have to locally invalidate the buffer to prevent data is being
+ * modified by remote peer after upper layer consumes it
+ */
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_connection_deregister_mr_io(struct smbdirect_mr_io *mr)
+{
+ struct smbdirect_socket *sc = mr->socket;
+ int ret = 0;
+
+ mutex_lock(&mr->mutex);
+ if (mr->state == SMBDIRECT_MR_DISABLED)
+ goto put_kref;
+
+ if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
+ smbdirect_mr_io_disable_locked(mr);
+ goto put_kref;
+ }
+
+ if (mr->need_invalidate) {
+ struct ib_send_wr *wr = &mr->inv_wr;
+
+ /* Need to finish local invalidation before returning */
+ wr->opcode = IB_WR_LOCAL_INV;
+ mr->cqe.done = smbdirect_connection_mr_io_local_inv_done;
+ wr->wr_cqe = &mr->cqe;
+ wr->num_sge = 0;
+ wr->ex.invalidate_rkey = mr->mr->rkey;
+ wr->send_flags = IB_SEND_SIGNALED;
+
+ init_completion(&mr->invalidate_done);
+ ret = ib_post_send(sc->ib.qp, wr, NULL);
+ if (ret) {
+ smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
+ "ib_post_send failed ret=%d (%s)\n",
+ ret, errname(ret));
+ smbdirect_mr_io_disable_locked(mr);
+ smbdirect_connection_schedule_disconnect(sc, ret);
+ goto done;
+ }
+ wait_for_completion(&mr->invalidate_done);
+ mr->need_invalidate = false;
+ } else
+ /*
+ * For remote invalidation, just set it to SMBDIRECT_MR_INVALIDATED
+ * and defer to mr_recovery_work to recover the MR for next use
+ */
+ mr->state = SMBDIRECT_MR_INVALIDATED;
+
+ if (mr->sgt.nents) {
+ ib_dma_unmap_sg(sc->ib.dev, mr->sgt.sgl, mr->sgt.nents, mr->dir);
+ mr->sgt.nents = 0;
+ }
+
+ if (mr->state == SMBDIRECT_MR_INVALIDATED) {
+ mr->state = SMBDIRECT_MR_READY;
+ if (atomic_inc_return(&sc->mr_io.ready.count) == 1)
+ wake_up(&sc->mr_io.ready.wait_queue);
+ } else
+ /*
+ * Schedule the work to do MR recovery for future I/Os MR
+ * recovery is slow and don't want it to block current I/O
+ */
+ queue_work(sc->workqueue, &sc->mr_io.recovery_work);
+
+done:
+ if (atomic_dec_and_test(&sc->mr_io.used.count))
+ wake_up(&sc->mr_io.cleanup.wait_queue);
+
+put_kref:
+ /*
+ * No kref_put_mutex() as it's already locked.
+ *
+ * If smbdirect_mr_io_free_locked() is called
+ * and the mutex is unlocked and mr is gone,
+ * in that case kref_put() returned 1.
+ *
+ * If kref_put() returned 0 we know that
+ * smbdirect_mr_io_free_locked() didn't
+ * run. Not by us nor by anyone else, as we
+ * still hold the mutex, so we need to unlock
+ * and keep the mr in SMBDIRECT_MR_READY or
+ * SMBDIRECT_MR_ERROR state.
+ */
+ if (!kref_put(&mr->kref, smbdirect_mr_io_free_locked))
+ mutex_unlock(&mr->mutex);
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 032/127] smb: smbdirect: introduce smbdirect_rw.c with server rw code
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (30 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 031/127] smb: smbdirect: introduce smbdirect_mr.c with client mr code Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 033/127] smb: smbdirect: define SMBDIRECT_MIN_{RECEIVE,FRAGMENTED}_SIZE Stefan Metzmacher
` (95 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This is basically contains the following functions copied from
the server: wait_for_rw_credits, calc_rw_credits, get_sg_list,
smb_direct_free_rdma_rw_msg, read_write_done, read_done,
write_done, smb_direct_rdma_xmit.
They got new names, some indentation/formatting changes,
some variable names are changed too.
They also only use struct smbdirect_socket instead of
struct smb_direct_transport.
But the logic is still the same. They will be used
by the server soon.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_all_c_files.c | 1 +
fs/smb/common/smbdirect/smbdirect_rw.c | 253 ++++++++++++++++++
fs/smb/common/smbdirect/smbdirect_socket.h | 9 +
3 files changed, 263 insertions(+)
create mode 100644 fs/smb/common/smbdirect/smbdirect_rw.c
diff --git a/fs/smb/common/smbdirect/smbdirect_all_c_files.c b/fs/smb/common/smbdirect/smbdirect_all_c_files.c
index 15022ca39815..3423330465ae 100644
--- a/fs/smb/common/smbdirect/smbdirect_all_c_files.c
+++ b/fs/smb/common/smbdirect/smbdirect_all_c_files.c
@@ -17,3 +17,4 @@
#endif
#include "smbdirect_connection.c"
#include "smbdirect_mr.c"
+#include "smbdirect_rw.c"
diff --git a/fs/smb/common/smbdirect/smbdirect_rw.c b/fs/smb/common/smbdirect/smbdirect_rw.c
new file mode 100644
index 000000000000..2f6a1e34e665
--- /dev/null
+++ b/fs/smb/common/smbdirect/smbdirect_rw.c
@@ -0,0 +1,253 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2017, Microsoft Corporation.
+ * Copyright (C) 2018, LG Electronics.
+ * Copyright (c) 2025, Stefan Metzmacher
+ */
+
+#include "smbdirect_internal.h"
+
+static int smbdirect_connection_wait_for_rw_credits(struct smbdirect_socket *sc,
+ int credits)
+{
+ return smbdirect_connection_wait_for_credits(sc,
+ &sc->rw_io.credits.wait_queue,
+ &sc->rw_io.credits.count,
+ credits);
+}
+
+static int smbdirect_connection_calc_rw_credits(struct smbdirect_socket *sc,
+ const void *buf,
+ size_t len)
+{
+ return DIV_ROUND_UP(smbdirect_get_buf_page_count(buf, len),
+ sc->rw_io.credits.num_pages);
+}
+
+static int smbdirect_connection_rdma_get_sg_list(void *buf,
+ size_t size,
+ struct scatterlist *sg_list,
+ size_t nentries)
+{
+ bool high = is_vmalloc_addr(buf);
+ struct page *page;
+ size_t offset, len;
+ int i = 0;
+
+ if (size == 0 || nentries < smbdirect_get_buf_page_count(buf, size))
+ return -EINVAL;
+
+ offset = offset_in_page(buf);
+ buf -= offset;
+ while (size > 0) {
+ len = min_t(size_t, PAGE_SIZE - offset, size);
+ if (high)
+ page = vmalloc_to_page(buf);
+ else
+ page = kmap_to_page(buf);
+
+ if (!sg_list)
+ return -EINVAL;
+ sg_set_page(sg_list, page, len, offset);
+ sg_list = sg_next(sg_list);
+
+ buf += PAGE_SIZE;
+ size -= len;
+ offset = 0;
+ i++;
+ }
+
+ return i;
+}
+
+static void smbdirect_connection_rw_io_free(struct smbdirect_rw_io *msg,
+ enum dma_data_direction dir)
+{
+ struct smbdirect_socket *sc = msg->socket;
+
+ rdma_rw_ctx_destroy(&msg->rdma_ctx,
+ sc->ib.qp,
+ sc->ib.qp->port,
+ msg->sgt.sgl,
+ msg->sgt.nents,
+ dir);
+ sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE);
+ kfree(msg);
+}
+
+static void smbdirect_connection_rdma_rw_done(struct ib_cq *cq, struct ib_wc *wc,
+ enum dma_data_direction dir)
+{
+ struct smbdirect_rw_io *msg =
+ container_of(wc->wr_cqe, struct smbdirect_rw_io, cqe);
+ struct smbdirect_socket *sc = msg->socket;
+
+ if (wc->status != IB_WC_SUCCESS) {
+ msg->error = -EIO;
+ pr_err("read/write error. opcode = %d, status = %s(%d)\n",
+ wc->opcode, ib_wc_status_msg(wc->status), wc->status);
+ if (wc->status != IB_WC_WR_FLUSH_ERR)
+ smbdirect_connection_schedule_disconnect(sc, msg->error);
+ }
+
+ complete(msg->completion);
+}
+
+static void smbdirect_connection_rdma_read_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+ smbdirect_connection_rdma_rw_done(cq, wc, DMA_FROM_DEVICE);
+}
+
+static void smbdirect_connection_rdma_write_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+ smbdirect_connection_rdma_rw_done(cq, wc, DMA_TO_DEVICE);
+}
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static int smbdirect_connection_rdma_xmit(struct smbdirect_socket *sc,
+ void *buf, size_t buf_len,
+ struct smbdirect_buffer_descriptor_v1 *desc,
+ size_t desc_len,
+ bool is_read)
+{
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+ enum dma_data_direction direction = is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+ struct smbdirect_rw_io *msg, *next_msg;
+ size_t i;
+ int ret;
+ DECLARE_COMPLETION_ONSTACK(completion);
+ struct ib_send_wr *first_wr;
+ LIST_HEAD(msg_list);
+ u8 *desc_buf;
+ int credits_needed;
+ size_t desc_buf_len, desc_num = 0;
+
+ if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
+ return -ENOTCONN;
+
+ if (buf_len > sp->max_read_write_size)
+ return -EINVAL;
+
+ /* calculate needed credits */
+ credits_needed = 0;
+ desc_buf = buf;
+ for (i = 0; i < desc_len / sizeof(*desc); i++) {
+ if (!buf_len)
+ break;
+
+ desc_buf_len = le32_to_cpu(desc[i].length);
+ if (!desc_buf_len)
+ return -EINVAL;
+
+ if (desc_buf_len > buf_len) {
+ desc_buf_len = buf_len;
+ desc[i].length = cpu_to_le32(desc_buf_len);
+ buf_len = 0;
+ }
+
+ credits_needed += smbdirect_connection_calc_rw_credits(sc,
+ desc_buf,
+ desc_buf_len);
+ desc_buf += desc_buf_len;
+ buf_len -= desc_buf_len;
+ desc_num++;
+ }
+
+ smbdirect_log_rdma_rw(sc, SMBDIRECT_LOG_INFO,
+ "RDMA %s, len %zu, needed credits %d\n",
+ str_read_write(is_read), buf_len, credits_needed);
+
+ ret = smbdirect_connection_wait_for_rw_credits(sc, credits_needed);
+ if (ret < 0)
+ return ret;
+
+ /* build rdma_rw_ctx for each descriptor */
+ desc_buf = buf;
+ for (i = 0; i < desc_num; i++) {
+ size_t page_count;
+
+ msg = kzalloc(struct_size(msg, sg_list, SG_CHUNK_SIZE),
+ sc->rw_io.mem.gfp_mask);
+ if (!msg) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ desc_buf_len = le32_to_cpu(desc[i].length);
+ page_count = smbdirect_get_buf_page_count(desc_buf, desc_buf_len);
+
+ msg->socket = sc;
+ msg->cqe.done = is_read ?
+ smbdirect_connection_rdma_read_done :
+ smbdirect_connection_rdma_write_done;
+ msg->completion = &completion;
+
+ msg->sgt.sgl = &msg->sg_list[0];
+ ret = sg_alloc_table_chained(&msg->sgt,
+ page_count,
+ msg->sg_list,
+ SG_CHUNK_SIZE);
+ if (ret) {
+ ret = -ENOMEM;
+ goto free_msg;
+ }
+
+ ret = smbdirect_connection_rdma_get_sg_list(desc_buf,
+ desc_buf_len,
+ msg->sgt.sgl,
+ msg->sgt.orig_nents);
+ if (ret < 0)
+ goto free_table;
+
+ ret = rdma_rw_ctx_init(&msg->rdma_ctx,
+ sc->ib.qp,
+ sc->ib.qp->port,
+ msg->sgt.sgl,
+ page_count,
+ 0,
+ le64_to_cpu(desc[i].offset),
+ le32_to_cpu(desc[i].token),
+ direction);
+ if (ret < 0) {
+ pr_err("failed to init rdma_rw_ctx: %d\n", ret);
+ goto free_table;
+ }
+
+ list_add_tail(&msg->list, &msg_list);
+ desc_buf += desc_buf_len;
+ }
+
+ /* concatenate work requests of rdma_rw_ctxs */
+ first_wr = NULL;
+ list_for_each_entry_reverse(msg, &msg_list, list) {
+ first_wr = rdma_rw_ctx_wrs(&msg->rdma_ctx,
+ sc->ib.qp,
+ sc->ib.qp->port,
+ &msg->cqe,
+ first_wr);
+ }
+
+ ret = ib_post_send(sc->ib.qp, first_wr, NULL);
+ if (ret) {
+ pr_err("failed to post send wr for RDMA R/W: %d\n", ret);
+ goto out;
+ }
+
+ msg = list_last_entry(&msg_list, struct smbdirect_rw_io, list);
+ wait_for_completion(&completion);
+ ret = msg->error;
+out:
+ list_for_each_entry_safe(msg, next_msg, &msg_list, list) {
+ list_del(&msg->list);
+ smbdirect_connection_rw_io_free(msg, direction);
+ }
+ atomic_add(credits_needed, &sc->rw_io.credits.count);
+ wake_up(&sc->rw_io.credits.wait_queue);
+ return ret;
+
+free_table:
+ sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE);
+free_msg:
+ kfree(msg);
+ goto out;
+}
diff --git a/fs/smb/common/smbdirect/smbdirect_socket.h b/fs/smb/common/smbdirect/smbdirect_socket.h
index 983e08c8d2ee..14c5d8503fca 100644
--- a/fs/smb/common/smbdirect/smbdirect_socket.h
+++ b/fs/smb/common/smbdirect/smbdirect_socket.h
@@ -306,6 +306,14 @@ struct smbdirect_socket {
* The state for RDMA read/write requests on the server
*/
struct {
+ /*
+ * Memory hints for
+ * smbdirect_rw_io structs
+ */
+ struct {
+ gfp_t gfp_mask;
+ } mem;
+
/*
* The credit state for the send side
*/
@@ -511,6 +519,7 @@ static __always_inline void smbdirect_socket_init(struct smbdirect_socket *sc)
spin_lock_init(&sc->recv_io.reassembly.lock);
init_waitqueue_head(&sc->recv_io.reassembly.wait_queue);
+ sc->rw_io.mem.gfp_mask = GFP_KERNEL;
atomic_set(&sc->rw_io.credits.count, 0);
init_waitqueue_head(&sc->rw_io.credits.wait_queue);
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 033/127] smb: smbdirect: define SMBDIRECT_MIN_{RECEIVE,FRAGMENTED}_SIZE
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (31 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 032/127] smb: smbdirect: introduce smbdirect_rw.c with server rw code Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 034/127] smb: smbdirect: define SMBDIRECT_RDMA_CM_[RNR_]RETRY Stefan Metzmacher
` (94 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
These are specified in MS-SMBD...
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/common/smbdirect/smbdirect_pdu.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_pdu.h b/fs/smb/common/smbdirect/smbdirect_pdu.h
index ae9fdb05ce23..7693ba337873 100644
--- a/fs/smb/common/smbdirect/smbdirect_pdu.h
+++ b/fs/smb/common/smbdirect/smbdirect_pdu.h
@@ -8,6 +8,10 @@
#define SMBDIRECT_V1 0x0100
+/* SMBD minimum receive size and fragmented sized defined in [MS-SMBD] */
+#define SMBDIRECT_MIN_RECEIVE_SIZE 128
+#define SMBDIRECT_MIN_FRAGMENTED_SIZE 131072
+
/* SMBD negotiation request packet [MS-SMBD] 2.2.1 */
struct smbdirect_negotiate_req {
__le16 min_version;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 034/127] smb: smbdirect: define SMBDIRECT_RDMA_CM_[RNR_]RETRY
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (32 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 033/127] smb: smbdirect: define SMBDIRECT_MIN_{RECEIVE,FRAGMENTED}_SIZE Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 035/127] smb: smbdirect: introduce smbdirect_connection_recv_io_done() Stefan Metzmacher
` (93 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
These are copies of {SMBD,SMB_DIRECT}_CM_[RNR_]RETRY.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/common/smbdirect/smbdirect_socket.h | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_socket.h b/fs/smb/common/smbdirect/smbdirect_socket.h
index 14c5d8503fca..795ce4b976ff 100644
--- a/fs/smb/common/smbdirect/smbdirect_socket.h
+++ b/fs/smb/common/smbdirect/smbdirect_socket.h
@@ -655,4 +655,13 @@ static inline size_t smbdirect_get_buf_page_count(const void *buf, size_t size)
(uintptr_t)buf / PAGE_SIZE;
}
+/*
+ * Maximum number of retries on data transfer operations
+ */
+#define SMBDIRECT_RDMA_CM_RETRY 6
+/*
+ * No need to retry on Receiver Not Ready since SMB_DIRECT manages credits
+ */
+#define SMBDIRECT_RDMA_CM_RNR_RETRY 0
+
#endif /* __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_SOCKET_H__ */
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 035/127] smb: smbdirect: introduce smbdirect_connection_recv_io_done()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (33 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 034/127] smb: smbdirect: define SMBDIRECT_RDMA_CM_[RNR_]RETRY Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 036/127] smb: smbdirect: introduce smbdirect_connection_destroy[_sync]() Stefan Metzmacher
` (92 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This is basically a copy of recv_done() in client and server,
with the following additions:
- Only handling the SMBDIRECT_EXPECT_DATA_TRANSFER code path,
as we'll have separate functions for the negotiate messages.
- Using more helper variables
- Improved logging
- Add credits_requested == 0 error check
- Add data_offset not 8 bytes aligned error check
- Use disable_work(&sc->recv_io.posted.refill_work)
before smbdirect_connection_put_recv_io, when it
is followed by smbdirect_connection_schedule_disconnect()
This will be used on common between client and server in future
and replace the existing recv_done() functions.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 167 ++++++++++++++++++
1 file changed, 167 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index 1b84e0789d77..cea05753c80e 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -908,6 +908,173 @@ static int smbdirect_connection_post_recv_io(struct smbdirect_recv_io *msg)
return ret;
}
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_connection_recv_io_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+ struct smbdirect_recv_io *recv_io =
+ container_of(wc->wr_cqe, struct smbdirect_recv_io, cqe);
+ struct smbdirect_socket *sc = recv_io->socket;
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+ struct smbdirect_data_transfer *data_transfer;
+ u16 old_recv_credit_target;
+ u16 credits_requested;
+ u16 credits_granted;
+ u16 flags;
+ u32 data_offset;
+ u32 data_length;
+ u32 remaining_data_length;
+
+ if (unlikely(wc->status != IB_WC_SUCCESS || WARN_ON_ONCE(wc->opcode != IB_WC_RECV))) {
+ if (wc->status != IB_WC_WR_FLUSH_ERR)
+ smbdirect_log_rdma_recv(sc, SMBDIRECT_LOG_ERR,
+ "wc->status=%s (%d) wc->opcode=%d\n",
+ ib_wc_status_msg(wc->status), wc->status, wc->opcode);
+ goto error;
+ }
+
+ smbdirect_log_rdma_recv(sc, SMBDIRECT_LOG_INFO,
+ "recv_io=0x%p type=%d wc status=%s wc opcode %d byte_len=%d pkey_index=%u\n",
+ recv_io, sc->recv_io.expected,
+ ib_wc_status_msg(wc->status), wc->opcode,
+ wc->byte_len, wc->pkey_index);
+
+ /*
+ * Reset timer to the keepalive interval in
+ * order to trigger our next keepalive message.
+ */
+ sc->idle.keepalive = SMBDIRECT_KEEPALIVE_NONE;
+ mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
+ msecs_to_jiffies(sp->keepalive_interval_msec));
+
+ ib_dma_sync_single_for_cpu(wc->qp->device,
+ recv_io->sge.addr,
+ recv_io->sge.length,
+ DMA_FROM_DEVICE);
+
+ if (unlikely(wc->byte_len <
+ offsetof(struct smbdirect_data_transfer, padding))) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "wc->byte_len=%u < %zu\n",
+ wc->byte_len,
+ offsetof(struct smbdirect_data_transfer, padding));
+ goto error;
+ }
+
+ data_transfer = (struct smbdirect_data_transfer *)recv_io->packet;
+ credits_requested = le16_to_cpu(data_transfer->credits_requested);
+ credits_granted = le16_to_cpu(data_transfer->credits_granted);
+ flags = le16_to_cpu(data_transfer->flags);
+ remaining_data_length = le32_to_cpu(data_transfer->remaining_data_length);
+ data_offset = le32_to_cpu(data_transfer->data_offset);
+ data_length = le32_to_cpu(data_transfer->data_length);
+
+ smbdirect_log_incoming(sc, SMBDIRECT_LOG_INFO,
+ "DataIn: %s=%u, %s=%u, %s=0x%x, %s=%u, %s=%u, %s=%u\n",
+ "CreditsRequested",
+ credits_requested,
+ "CreditsGranted",
+ credits_granted,
+ "Flags",
+ flags,
+ "RemainingDataLength",
+ remaining_data_length,
+ "DataOffset",
+ data_offset,
+ "DataLength",
+ data_length);
+
+ if (unlikely(credits_requested == 0)) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "invalid: credits_requested == 0\n");
+ goto error;
+ }
+
+ if (unlikely(data_offset % 8 != 0)) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "invalid: data_offset=%u (0x%x) not aligned to 8\n",
+ data_offset, data_offset);
+ goto error;
+ }
+
+ if (unlikely(wc->byte_len < data_offset ||
+ (u64)wc->byte_len < (u64)data_offset + data_length)) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "wc->byte_len=%u < date_offset=%u + data_length=%u\n",
+ wc->byte_len, data_offset, data_length);
+ goto error;
+ }
+
+ if (unlikely(remaining_data_length > sp->max_fragmented_recv_size ||
+ data_length > sp->max_fragmented_recv_size ||
+ (u64)remaining_data_length + (u64)data_length > (u64)sp->max_fragmented_recv_size)) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "remaining_data_length=%u + data_length=%u > max_fragmented=%u\n",
+ remaining_data_length, data_length, sp->max_fragmented_recv_size);
+ goto error;
+ }
+
+ if (data_length) {
+ if (sc->recv_io.reassembly.full_packet_received)
+ recv_io->first_segment = true;
+
+ if (remaining_data_length)
+ sc->recv_io.reassembly.full_packet_received = false;
+ else
+ sc->recv_io.reassembly.full_packet_received = true;
+ }
+
+ atomic_dec(&sc->recv_io.posted.count);
+ atomic_dec(&sc->recv_io.credits.count);
+ old_recv_credit_target = sc->recv_io.credits.target;
+ /*
+ * We take the value from the peer, which is checked to be higher than 0,
+ * but we limit it to the max value we support in order to have
+ * the main logic simpler.
+ */
+ sc->recv_io.credits.target = credits_requested;
+ sc->recv_io.credits.target = min_t(u16, sc->recv_io.credits.target,
+ sp->recv_credit_max);
+ if (credits_granted) {
+ atomic_add(credits_granted, &sc->send_io.credits.count);
+ /*
+ * We have new send credits granted from remote peer
+ * If any sender is waiting for credits, unblock it
+ */
+ wake_up(&sc->send_io.credits.wait_queue);
+ }
+
+ /* Send an immediate response right away if requested */
+ if (flags & SMBDIRECT_FLAG_RESPONSE_REQUESTED) {
+ smbdirect_log_keep_alive(sc, SMBDIRECT_LOG_INFO,
+ "schedule send of immediate response\n");
+ queue_work(sc->workqueue, &sc->idle.immediate_work);
+ }
+
+ /*
+ * If this is a packet with data playload place the data in
+ * reassembly queue and wake up the reading thread
+ */
+ if (data_length) {
+ if (sc->recv_io.credits.target > old_recv_credit_target)
+ queue_work(sc->workqueue, &sc->recv_io.posted.refill_work);
+
+ smbdirect_connection_reassembly_append_recv_io(sc, recv_io, data_length);
+ wake_up(&sc->recv_io.reassembly.wait_queue);
+ } else
+ smbdirect_connection_put_recv_io(recv_io);
+
+ return;
+
+error:
+ /*
+ * Make sure smbdirect_connection_put_recv_io() does not
+ * start recv_io.posted.refill_work.
+ */
+ disable_work(&sc->recv_io.posted.refill_work);
+ smbdirect_connection_put_recv_io(recv_io);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+}
+
static int smbdirect_connection_recv_io_refill(struct smbdirect_socket *sc)
{
int missing;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 036/127] smb: smbdirect: introduce smbdirect_connection_destroy[_sync]()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (34 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 035/127] smb: smbdirect: introduce smbdirect_connection_recv_io_done() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 037/127] smb: smbdirect: introduce smbdirect_connection_rdma_{established,event_handler}() Stefan Metzmacher
` (91 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This will be used in common between client and server in
order to destroy all resources attached to a connection.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 126 ++++++++++++++++++
1 file changed, 126 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index cea05753c80e..6fe6c53e10ea 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -24,6 +24,8 @@ static void smbdirect_connection_schedule_disconnect(struct smbdirect_socket *sc
static void smbdirect_connection_disconnect_work(struct work_struct *work);
static void smbdirect_connection_idle_timer_work(struct work_struct *work);
+static void smbdirect_connection_destroy_mr_list(struct smbdirect_socket *sc);
+
__maybe_unused /* this is temporary while this file is included in orders */
static bool smbdirect_frwr_is_supported(const struct ib_device_attr *attrs)
{
@@ -765,6 +767,130 @@ static void smbdirect_connection_disconnect_work(struct work_struct *work)
smbdirect_connection_wake_up_all(sc);
}
+static void smbdirect_connection_destroy(struct smbdirect_socket *sc)
+{
+ struct smbdirect_recv_io *recv_io;
+ struct smbdirect_recv_io *recv_tmp;
+ LIST_HEAD(all_list);
+ unsigned long flags;
+
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
+ "status=%s first_error=%1pe",
+ smbdirect_socket_status_string(sc->status),
+ SMBDIRECT_DEBUG_ERR_PTR(sc->first_error));
+
+ /*
+ * This should not never be called in an interrupt!
+ */
+ WARN_ON_ONCE(in_interrupt());
+
+ if (sc->status == SMBDIRECT_SOCKET_DESTROYED)
+ return;
+
+ WARN_ONCE(sc->status != SMBDIRECT_SOCKET_DISCONNECTED,
+ "status=%s first_error=%1pe",
+ smbdirect_socket_status_string(sc->status),
+ SMBDIRECT_DEBUG_ERR_PTR(sc->first_error));
+
+ /*
+ * Wake up all waiters in all wait queues
+ * in order to notice the broken connection.
+ *
+ * Most likely this was already called via
+ * smbdirect_connection_disconnect_work(), but call it again...
+ */
+ smbdirect_connection_wake_up_all(sc);
+
+ disable_work_sync(&sc->disconnect_work);
+ disable_work_sync(&sc->recv_io.posted.refill_work);
+ disable_work_sync(&sc->mr_io.recovery_work);
+ disable_work_sync(&sc->idle.immediate_work);
+ disable_delayed_work_sync(&sc->idle.timer_work);
+
+ if (sc->rdma.cm_id)
+ rdma_lock_handler(sc->rdma.cm_id);
+
+ if (sc->ib.qp) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
+ "drain qp\n");
+ ib_drain_qp(sc->ib.qp);
+ }
+
+ /* It's not possible for upper layer to get to reassembly */
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
+ "drain the reassembly queue\n");
+ spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags);
+ list_splice_tail_init(&sc->recv_io.reassembly.list, &all_list);
+ spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags);
+ list_for_each_entry_safe(recv_io, recv_tmp, &all_list, list) {
+ smbdirect_connection_put_recv_io(recv_io);
+ }
+ sc->recv_io.reassembly.data_length = 0;
+
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
+ "freeing mr list\n");
+ smbdirect_connection_destroy_mr_list(sc);
+
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
+ "destroying qp\n");
+ smbdirect_connection_destroy_qp(sc);
+ if (sc->rdma.cm_id) {
+ rdma_unlock_handler(sc->rdma.cm_id);
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
+ "destroying cm_id\n");
+ rdma_destroy_id(sc->rdma.cm_id);
+ sc->rdma.cm_id = NULL;
+ }
+
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
+ "destroying mem pools\n");
+ smbdirect_connection_destroy_mem_pools(sc);
+
+ sc->status = SMBDIRECT_SOCKET_DESTROYED;
+
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
+ "rdma session destroyed\n");
+}
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_connection_destroy_sync(struct smbdirect_socket *sc)
+{
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
+ "status=%s first_error=%1pe",
+ smbdirect_socket_status_string(sc->status),
+ SMBDIRECT_DEBUG_ERR_PTR(sc->first_error));
+
+ /*
+ * This should not never be called in an interrupt!
+ */
+ WARN_ON_ONCE(in_interrupt());
+
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
+ "cancelling and disable disconnect_work\n");
+ disable_work_sync(&sc->disconnect_work);
+
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO, "destroying rdma session\n");
+ if (sc->status < SMBDIRECT_SOCKET_DISCONNECTING)
+ smbdirect_connection_disconnect_work(&sc->disconnect_work);
+ if (sc->status < SMBDIRECT_SOCKET_DISCONNECTED) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
+ "wait for transport being disconnected\n");
+ wait_event(sc->status_wait, sc->status == SMBDIRECT_SOCKET_DISCONNECTED);
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
+ "waited for transport being disconnected\n");
+ }
+
+ /*
+ * Once we reached SMBDIRECT_SOCKET_DISCONNECTED,
+ * we should call smbdirect_connection_destroy()
+ */
+ smbdirect_connection_destroy(sc);
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
+ "status=%s first_error=%1pe",
+ smbdirect_socket_status_string(sc->status),
+ SMBDIRECT_DEBUG_ERR_PTR(sc->first_error));
+}
+
static void smbdirect_connection_idle_timer_work(struct work_struct *work)
{
struct smbdirect_socket *sc =
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 037/127] smb: smbdirect: introduce smbdirect_connection_rdma_{established,event_handler}()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (35 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 036/127] smb: smbdirect: introduce smbdirect_connection_destroy[_sync]() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 038/127] smb: smbdirect: introduce smbdirect_connection_recvmsg() Stefan Metzmacher
` (90 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
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@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../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
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 038/127] smb: smbdirect: introduce smbdirect_connection_recvmsg()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (36 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 037/127] smb: smbdirect: introduce smbdirect_connection_rdma_{established,event_handler}() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 039/127] smb: smbdirect: introduce smbdirect_connection_grant_recv_credits() Stefan Metzmacher
` (89 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This is basically a copy of smbd_recv() in the client.
And it's very similar to smb_direct_read() in the server.
It will replace both in the following commits.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 151 ++++++++++++++++++
1 file changed, 151 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index cd4f3e6fa5e2..36f82b090bc7 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -1395,6 +1395,157 @@ static void smbdirect_connection_recv_io_refill_work(struct work_struct *work)
}
}
+__maybe_unused /* this is temporary while this file is included in orders */
+static int smbdirect_connection_recvmsg(struct smbdirect_socket *sc,
+ struct msghdr *msg,
+ unsigned int flags)
+{
+ struct smbdirect_recv_io *response;
+ struct smbdirect_data_transfer *data_transfer;
+ size_t size = iov_iter_count(&msg->msg_iter);
+ int to_copy, to_read, data_read, offset;
+ u32 data_length, remaining_data_length, data_offset;
+ int ret;
+
+ if (WARN_ON_ONCE(flags))
+ return -EINVAL; /* no flags support for now */
+
+ if (WARN_ON_ONCE(iov_iter_rw(&msg->msg_iter) != ITER_DEST))
+ return -EINVAL; /* It's a bug in upper layer to get there */
+
+again:
+ if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
+ smbdirect_log_read(sc, SMBDIRECT_LOG_ERR,
+ "status=%s first_error=%1pe => %s\n",
+ smbdirect_socket_status_string(sc->status),
+ SMBDIRECT_DEBUG_ERR_PTR(sc->first_error),
+ errname(-ENOTCONN));
+ return -ENOTCONN;
+ }
+
+ /*
+ * No need to hold the reassembly queue lock all the time as we are
+ * the only one reading from the front of the queue. The transport
+ * may add more entries to the back of the queue at the same time
+ */
+ smbdirect_log_read(sc, SMBDIRECT_LOG_INFO,
+ "size=%zd sc->recv_io.reassembly.data_length=%d\n",
+ size, sc->recv_io.reassembly.data_length);
+ if (sc->recv_io.reassembly.data_length >= size) {
+ int queue_length;
+ int queue_removed = 0;
+ unsigned long flags;
+
+ /*
+ * Need to make sure reassembly_data_length is read before
+ * reading reassembly_queue_length and calling
+ * smbdirect_connection_reassembly_first_recv_io. This call is lock free
+ * as we never read at the end of the queue which are being
+ * updated in SOFTIRQ as more data is received
+ */
+ virt_rmb();
+ queue_length = sc->recv_io.reassembly.queue_length;
+ data_read = 0;
+ to_read = size;
+ offset = sc->recv_io.reassembly.first_entry_offset;
+ while (data_read < size) {
+ response = smbdirect_connection_reassembly_first_recv_io(sc);
+ data_transfer = (void *)response->packet;
+ data_length = le32_to_cpu(data_transfer->data_length);
+ remaining_data_length =
+ le32_to_cpu(
+ data_transfer->remaining_data_length);
+ data_offset = le32_to_cpu(data_transfer->data_offset);
+
+ /*
+ * The upper layer expects RFC1002 length at the
+ * beginning of the payload. Return it to indicate
+ * the total length of the packet. This minimize the
+ * change to upper layer packet processing logic. This
+ * will be eventually remove when an intermediate
+ * transport layer is added
+ */
+ if (response->first_segment && size == 4) {
+ unsigned int rfc1002_len =
+ data_length + remaining_data_length;
+ __be32 rfc1002_hdr = cpu_to_be32(rfc1002_len);
+
+ if (copy_to_iter(&rfc1002_hdr, sizeof(rfc1002_hdr),
+ &msg->msg_iter) != sizeof(rfc1002_hdr))
+ return -EFAULT;
+ data_read = 4;
+ response->first_segment = false;
+ smbdirect_log_read(sc, SMBDIRECT_LOG_INFO,
+ "returning rfc1002 length %d\n",
+ rfc1002_len);
+ goto read_rfc1002_done;
+ }
+
+ to_copy = min_t(int, data_length - offset, to_read);
+ if (copy_to_iter((u8 *)data_transfer + data_offset + offset,
+ to_copy, &msg->msg_iter) != to_copy)
+ return -EFAULT;
+
+ /* move on to the next buffer? */
+ if (to_copy == data_length - offset) {
+ queue_length--;
+ /*
+ * No need to lock if we are not at the
+ * end of the queue
+ */
+ if (queue_length)
+ list_del(&response->list);
+ else {
+ spin_lock_irqsave(
+ &sc->recv_io.reassembly.lock, flags);
+ list_del(&response->list);
+ spin_unlock_irqrestore(
+ &sc->recv_io.reassembly.lock, flags);
+ }
+ queue_removed++;
+ sc->statistics.dequeue_reassembly_queue++;
+ smbdirect_connection_put_recv_io(response);
+ offset = 0;
+ smbdirect_log_read(sc, SMBDIRECT_LOG_INFO,
+ "smbdirect_connection_put_recv_io offset=0\n");
+ } else
+ offset += to_copy;
+
+ to_read -= to_copy;
+ data_read += to_copy;
+
+ smbdirect_log_read(sc, SMBDIRECT_LOG_INFO,
+ "memcpy %d bytes len-ofs=%u => todo=%u done=%u ofs=%u\n",
+ to_copy, data_length - offset,
+ to_read, data_read, offset);
+ }
+
+ spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags);
+ sc->recv_io.reassembly.data_length -= data_read;
+ sc->recv_io.reassembly.queue_length -= queue_removed;
+ spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags);
+
+ sc->recv_io.reassembly.first_entry_offset = offset;
+ smbdirect_log_read(sc, SMBDIRECT_LOG_INFO,
+ "returning data_read=%d reassembly_length=%d first_ofs=%u\n",
+ data_read, sc->recv_io.reassembly.data_length,
+ sc->recv_io.reassembly.first_entry_offset);
+read_rfc1002_done:
+ return data_read;
+ }
+
+ smbdirect_log_read(sc, SMBDIRECT_LOG_INFO,
+ "wait_event on more data\n");
+ ret = wait_event_interruptible(sc->recv_io.reassembly.wait_queue,
+ sc->recv_io.reassembly.data_length >= size ||
+ sc->status != SMBDIRECT_SOCKET_CONNECTED);
+ /* Don't return any data if interrupted */
+ if (ret)
+ return ret;
+
+ goto again;
+}
+
static bool smbdirect_map_sges_single_page(struct smbdirect_map_sges *state,
struct page *page, size_t off, size_t len)
{
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 039/127] smb: smbdirect: introduce smbdirect_connection_grant_recv_credits()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (37 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 038/127] smb: smbdirect: introduce smbdirect_connection_recvmsg() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 040/127] smb: smbdirect: introduce smbdirect_connection_request_keep_alive() Stefan Metzmacher
` (88 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This is a copy of manage_credits_prior_sending() in the server.
It is very similar to manage_credits_prior_sending() in the
client, the only difference is that
atomic_add(new_credits, &sc->recv_io.credits.count) is done
in the caller there.
It will replace both versions in future.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 20 +++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index 36f82b090bc7..da2e9ecdd98d 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -1037,6 +1037,26 @@ static int smbdirect_connection_wait_for_credits(struct smbdirect_socket *sc,
} while (true);
}
+__maybe_unused /* this is temporary while this file is included in orders */
+static u16 smbdirect_connection_grant_recv_credits(struct smbdirect_socket *sc)
+{
+ u16 new_credits;
+
+ if (atomic_read(&sc->recv_io.credits.count) >= sc->recv_io.credits.target)
+ return 0;
+
+ new_credits = atomic_read(&sc->recv_io.posted.count);
+ if (new_credits == 0)
+ return 0;
+
+ new_credits -= atomic_read(&sc->recv_io.credits.count);
+ if (new_credits <= 0)
+ return 0;
+
+ atomic_add(new_credits, &sc->recv_io.credits.count);
+ return new_credits;
+}
+
__maybe_unused /* this is temporary while this file is included in orders */
static void smbdirect_connection_send_io_done(struct ib_cq *cq, struct ib_wc *wc)
{
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 040/127] smb: smbdirect: introduce smbdirect_connection_request_keep_alive()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (38 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 039/127] smb: smbdirect: introduce smbdirect_connection_grant_recv_credits() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 041/127] smb: smbdirect: introduce smbdirect_connection_send_iter() and related functions Stefan Metzmacher
` (87 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This a copy of manage_keep_alive_before_sending() in client and server,
it will replace these in future.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index da2e9ecdd98d..e2eb3c6cf0f1 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -1057,6 +1057,25 @@ static u16 smbdirect_connection_grant_recv_credits(struct smbdirect_socket *sc)
return new_credits;
}
+__maybe_unused /* this is temporary while this file is included in orders */
+static bool smbdirect_connection_request_keep_alive(struct smbdirect_socket *sc)
+{
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+
+ if (sc->idle.keepalive == SMBDIRECT_KEEPALIVE_PENDING) {
+ sc->idle.keepalive = SMBDIRECT_KEEPALIVE_SENT;
+ /*
+ * Now use the keepalive timeout (instead of keepalive interval)
+ * in order to wait for a response
+ */
+ mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
+ msecs_to_jiffies(sp->keepalive_timeout_msec));
+ return true;
+ }
+
+ return false;
+}
+
__maybe_unused /* this is temporary while this file is included in orders */
static void smbdirect_connection_send_io_done(struct ib_cq *cq, struct ib_wc *wc)
{
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 041/127] smb: smbdirect: introduce smbdirect_connection_send_iter() and related functions
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (39 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 040/127] smb: smbdirect: introduce smbdirect_connection_request_keep_alive() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 042/127] smb: smbdirect: introduce smbdirect_connection_send_immediate_work() Stefan Metzmacher
` (86 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
David Howells
This is basically a copy of the following functions in the server:
smb_direct_post_send => smbdirect_connection_post_send_wr
smb_direct_send_ctx_init => smbdirect_connection_send_batch_init
smb_direct_flush_send_list => smbdirect_connection_send_batch_flush
wait_for_send_lcredit => smbdirect_connection_wait_for_send_lcredit
wait_for_send_credits => smbdirect_connection_wait_for_send_credits
post_sendmsg => smbdirect_connection_post_send_io
smb_direct_post_send_data => smbdirect_connection_send_single_iter
smb_direct_send_iter => smbdirect_connection_send_iter
They will replace the server functions soon and will also be used in
the client as smbdirect_connection_send_single_iter() is very similar to
smbd_post_send_iter().
There's also a smbdirect_connection_send_wait_zero_pending()
helper that can be used together with
smbdirect_connection_send_single_iter() in the client
until it can use smbdirect_connection_send_iter(),
which can happen with David's refactoring.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: Namjae Jeon <linkinjeon@kernel.org>
Cc: David Howells <dhowells@redhat.com>
Cc: linux-cifs@vger.kernel.org
Cc: samba-technical@lists.samba.org
Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
.../common/smbdirect/smbdirect_connection.c | 404 +++++++++++++++++-
1 file changed, 403 insertions(+), 1 deletion(-)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index e2eb3c6cf0f1..e834fcfe05af 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -1076,7 +1076,410 @@ static bool smbdirect_connection_request_keep_alive(struct smbdirect_socket *sc)
return false;
}
+static int smbdirect_connection_post_send_wr(struct smbdirect_socket *sc,
+ struct ib_send_wr *wr)
+{
+ int ret;
+
+ if (unlikely(sc->first_error))
+ return sc->first_error;
+
+ atomic_inc(&sc->send_io.pending.count);
+ ret = ib_post_send(sc->ib.qp, wr, NULL);
+ if (ret) {
+ atomic_dec(&sc->send_io.pending.count);
+ smbdirect_log_rdma_send(sc, SMBDIRECT_LOG_ERR,
+ "ib_post_send() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ smbdirect_connection_schedule_disconnect(sc, ret);
+ }
+
+ return ret;
+}
+
+static void smbdirect_connection_send_batch_init(struct smbdirect_send_batch *batch,
+ bool need_invalidate_rkey,
+ unsigned int remote_key)
+{
+ INIT_LIST_HEAD(&batch->msg_list);
+ batch->wr_cnt = 0;
+ batch->need_invalidate_rkey = need_invalidate_rkey;
+ batch->remote_key = remote_key;
+}
+
+static int smbdirect_connection_send_batch_flush(struct smbdirect_socket *sc,
+ struct smbdirect_send_batch *batch,
+ bool is_last)
+{
+ struct smbdirect_send_io *first, *last;
+ int ret;
+
+ if (list_empty(&batch->msg_list))
+ return 0;
+
+ first = list_first_entry(&batch->msg_list,
+ struct smbdirect_send_io,
+ sibling_list);
+ last = list_last_entry(&batch->msg_list,
+ struct smbdirect_send_io,
+ sibling_list);
+
+ if (batch->need_invalidate_rkey) {
+ first->wr.opcode = IB_WR_SEND_WITH_INV;
+ first->wr.ex.invalidate_rkey = batch->remote_key;
+ batch->need_invalidate_rkey = false;
+ batch->remote_key = 0;
+ }
+
+ last->wr.send_flags = IB_SEND_SIGNALED;
+ last->wr.wr_cqe = &last->cqe;
+
+ /*
+ * Remove last from send_ctx->msg_list
+ * and splice the rest of send_ctx->msg_list
+ * to last->sibling_list.
+ *
+ * send_ctx->msg_list is a valid empty list
+ * at the end.
+ */
+ list_del_init(&last->sibling_list);
+ list_splice_tail_init(&batch->msg_list, &last->sibling_list);
+ batch->wr_cnt = 0;
+
+ ret = smbdirect_connection_post_send_wr(sc, &first->wr);
+ if (ret) {
+ struct smbdirect_send_io *sibling, *next;
+
+ list_for_each_entry_safe(sibling, next, &last->sibling_list, sibling_list) {
+ list_del_init(&sibling->sibling_list);
+ smbdirect_connection_free_send_io(sibling);
+ }
+ smbdirect_connection_free_send_io(last);
+ }
+
+ return ret;
+}
+
+
+static int smbdirect_connection_wait_for_send_lcredit(struct smbdirect_socket *sc,
+ struct smbdirect_send_batch *batch)
+{
+ if (batch && atomic_read(&sc->send_io.lcredits.count) <= 1) {
+ int ret;
+
+ ret = smbdirect_connection_send_batch_flush(sc, batch, false);
+ if (ret)
+ return ret;
+ }
+
+ return smbdirect_connection_wait_for_credits(sc,
+ &sc->send_io.lcredits.wait_queue,
+ &sc->send_io.lcredits.count,
+ 1);
+}
+
+static int smbdirect_connection_wait_for_send_credits(struct smbdirect_socket *sc,
+ struct smbdirect_send_batch *batch)
+{
+ if (batch && (batch->wr_cnt >= 16 || atomic_read(&sc->send_io.credits.count) <= 1)) {
+ int ret;
+
+ ret = smbdirect_connection_send_batch_flush(sc, batch, false);
+ if (ret)
+ return ret;
+ }
+
+ return smbdirect_connection_wait_for_credits(sc,
+ &sc->send_io.credits.wait_queue,
+ &sc->send_io.credits.count,
+ 1);
+}
+
+static void smbdirect_connection_send_io_done(struct ib_cq *cq, struct ib_wc *wc);
+
+static int smbdirect_connection_post_send_io(struct smbdirect_socket *sc,
+ struct smbdirect_send_batch *batch,
+ struct smbdirect_send_io *msg)
+{
+ int i;
+
+ for (i = 0; i < msg->num_sge; i++)
+ ib_dma_sync_single_for_device(sc->ib.dev,
+ msg->sge[i].addr, msg->sge[i].length,
+ DMA_TO_DEVICE);
+
+ msg->cqe.done = smbdirect_connection_send_io_done;
+ msg->wr.wr_cqe = &msg->cqe;
+ msg->wr.opcode = IB_WR_SEND;
+ msg->wr.sg_list = &msg->sge[0];
+ msg->wr.num_sge = msg->num_sge;
+ msg->wr.next = NULL;
+
+ if (batch) {
+ msg->wr.send_flags = 0;
+ if (!list_empty(&batch->msg_list)) {
+ struct smbdirect_send_io *last;
+
+ last = list_last_entry(&batch->msg_list,
+ struct smbdirect_send_io,
+ sibling_list);
+ last->wr.next = &msg->wr;
+ }
+ list_add_tail(&msg->sibling_list, &batch->msg_list);
+ batch->wr_cnt++;
+ return 0;
+ }
+
+ msg->wr.send_flags = IB_SEND_SIGNALED;
+ return smbdirect_connection_post_send_wr(sc, &msg->wr);
+}
+
+static int smbdirect_connection_send_single_iter(struct smbdirect_socket *sc,
+ struct smbdirect_send_batch *batch,
+ struct iov_iter *iter,
+ unsigned int flags,
+ u32 remaining_data_length)
+{
+ const struct smbdirect_socket_parameters *sp = &sc->parameters;
+ struct smbdirect_send_io *msg;
+ struct smbdirect_data_transfer *packet;
+ size_t header_length;
+ u16 new_credits = 0;
+ u32 data_length = 0;
+ int ret;
+
+ if (WARN_ON_ONCE(flags))
+ return -EINVAL; /* no flags support for now */
+
+ if (iter) {
+ if (WARN_ON_ONCE(iov_iter_rw(iter) != ITER_SOURCE))
+ return -EINVAL; /* It's a bug in upper layer to get there */
+
+ header_length = sizeof(struct smbdirect_data_transfer);
+ if (WARN_ON_ONCE(remaining_data_length == 0 ||
+ iov_iter_count(iter) > remaining_data_length))
+ return -EINVAL;
+ } else {
+ /* If this is a packet without payload, don't send padding */
+ header_length = offsetof(struct smbdirect_data_transfer, padding);
+ if (WARN_ON_ONCE(remaining_data_length))
+ return -EINVAL;
+ }
+
+ if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
+ smbdirect_log_write(sc, SMBDIRECT_LOG_ERR,
+ "status=%s first_error=%1pe => %s\n",
+ smbdirect_socket_status_string(sc->status),
+ SMBDIRECT_DEBUG_ERR_PTR(sc->first_error),
+ errname(-ENOTCONN));
+ return -ENOTCONN;
+ }
+
+ ret = smbdirect_connection_wait_for_send_lcredit(sc, batch);
+ if (ret)
+ goto lcredit_failed;
+
+ ret = smbdirect_connection_wait_for_send_credits(sc, batch);
+ if (ret)
+ goto credit_failed;
+
+ msg = smbdirect_connection_alloc_send_io(sc);
+ if (IS_ERR(msg)) {
+ ret = PTR_ERR(msg);
+ goto alloc_failed;
+ }
+
+ /* Map the packet to DMA */
+ msg->sge[0].addr = ib_dma_map_single(sc->ib.dev,
+ msg->packet,
+ header_length,
+ DMA_TO_DEVICE);
+ ret = ib_dma_mapping_error(sc->ib.dev, msg->sge[0].addr);
+ if (ret)
+ goto err;
+
+ msg->sge[0].length = header_length;
+ msg->sge[0].lkey = sc->ib.pd->local_dma_lkey;
+ msg->num_sge = 1;
+
+ if (iter) {
+ struct smbdirect_map_sges extract = {
+ .num_sge = msg->num_sge,
+ .max_sge = ARRAY_SIZE(msg->sge),
+ .sge = msg->sge,
+ .device = sc->ib.dev,
+ .local_dma_lkey = sc->ib.pd->local_dma_lkey,
+ .direction = DMA_TO_DEVICE,
+ };
+ size_t payload_len = umin(iov_iter_count(iter),
+ sp->max_send_size - sizeof(*packet));
+
+ ret = smbdirect_map_sges_from_iter(iter, payload_len, &extract);
+ if (ret < 0)
+ goto err;
+ data_length = ret;
+ remaining_data_length -= data_length;
+ msg->num_sge = extract.num_sge;
+ }
+
+ /* Fill in the packet header */
+ packet = (struct smbdirect_data_transfer *)msg->packet;
+ packet->credits_requested = cpu_to_le16(sp->send_credit_target);
+ new_credits = smbdirect_connection_grant_recv_credits(sc);
+ packet->credits_granted = cpu_to_le16(new_credits);
+
+ packet->flags = 0;
+ if (smbdirect_connection_request_keep_alive(sc))
+ packet->flags |= cpu_to_le16(SMBDIRECT_FLAG_RESPONSE_REQUESTED);
+
+ packet->reserved = 0;
+ if (!data_length)
+ packet->data_offset = 0;
+ else
+ packet->data_offset = cpu_to_le32(24);
+ packet->data_length = cpu_to_le32(data_length);
+ packet->remaining_data_length = cpu_to_le32(remaining_data_length);
+ packet->padding = 0;
+
+ smbdirect_log_outgoing(sc, SMBDIRECT_LOG_INFO,
+ "DataOut: %s=%u, %s=%u, %s=0x%x, %s=%u, %s=%u, %s=%u\n",
+ "CreditsRequested",
+ le16_to_cpu(packet->credits_requested),
+ "CreditsGranted",
+ le16_to_cpu(packet->credits_granted),
+ "Flags",
+ le16_to_cpu(packet->flags),
+ "RemainingDataLength",
+ le32_to_cpu(packet->remaining_data_length),
+ "DataOffset",
+ le32_to_cpu(packet->data_offset),
+ "DataLength",
+ le32_to_cpu(packet->data_length));
+
+ ret = smbdirect_connection_post_send_io(sc, batch, msg);
+ if (ret)
+ goto err;
+ return data_length;
+err:
+ smbdirect_connection_free_send_io(msg);
+alloc_failed:
+ atomic_inc(&sc->send_io.credits.count);
+credit_failed:
+ atomic_inc(&sc->send_io.lcredits.count);
+lcredit_failed:
+ return ret;
+}
+
__maybe_unused /* this is temporary while this file is included in orders */
+static int smbdirect_connection_send_wait_zero_pending(struct smbdirect_socket *sc)
+{
+ /*
+ * As an optimization, we don't wait for individual I/O to finish
+ * before sending the next one.
+ * Send them all and wait for pending send count to get to 0
+ * that means all the I/Os have been out and we are good to return
+ */
+
+ wait_event(sc->send_io.pending.zero_wait_queue,
+ atomic_read(&sc->send_io.pending.count) == 0 ||
+ sc->status != SMBDIRECT_SOCKET_CONNECTED);
+ if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
+ smbdirect_log_write(sc, SMBDIRECT_LOG_ERR,
+ "status=%s first_error=%1pe => %s\n",
+ smbdirect_socket_status_string(sc->status),
+ SMBDIRECT_DEBUG_ERR_PTR(sc->first_error),
+ errname(-ENOTCONN));
+ return -ENOTCONN;
+ }
+
+ return 0;
+}
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static int smbdirect_connection_send_iter(struct smbdirect_socket *sc,
+ struct iov_iter *iter,
+ unsigned int flags,
+ bool need_invalidate,
+ unsigned int remote_key)
+{
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+ struct smbdirect_send_batch batch;
+ int total_count = iov_iter_count(iter);
+ int ret;
+ int error = 0;
+ __be32 hdr;
+
+ if (WARN_ON_ONCE(flags))
+ return -EINVAL; /* no flags support for now */
+
+ if (WARN_ON_ONCE(iov_iter_rw(iter) != ITER_SOURCE))
+ return -EINVAL; /* It's a bug in upper layer to get there */
+
+ if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
+ smbdirect_log_write(sc, SMBDIRECT_LOG_ERR,
+ "status=%s first_error=%1pe => %s\n",
+ smbdirect_socket_status_string(sc->status),
+ SMBDIRECT_DEBUG_ERR_PTR(sc->first_error),
+ errname(-ENOTCONN));
+ return -ENOTCONN;
+ }
+
+ /*
+ * For now we expect the iter to have the full
+ * message, including a 4 byte length header.
+ */
+ if (iov_iter_count(iter) <= 4)
+ return -EINVAL;
+ if (!copy_from_iter_full(&hdr, sizeof(hdr), iter))
+ return -EFAULT;
+ if (iov_iter_count(iter) != be32_to_cpu(hdr))
+ return -EINVAL;
+
+ /*
+ * The size must fit into the negotiated
+ * fragmented send size.
+ */
+ if (iov_iter_count(iter) > sp->max_fragmented_send_size)
+ return -EMSGSIZE;
+
+ smbdirect_log_write(sc, SMBDIRECT_LOG_INFO,
+ "Sending (RDMA): length=%zu\n",
+ iov_iter_count(iter));
+
+ smbdirect_connection_send_batch_init(&batch, need_invalidate, remote_key);
+ while (iov_iter_count(iter)) {
+ ret = smbdirect_connection_send_single_iter(sc,
+ &batch,
+ iter,
+ flags,
+ iov_iter_count(iter));
+ if (unlikely(ret < 0)) {
+ error = ret;
+ break;
+ }
+ }
+
+ ret = smbdirect_connection_send_batch_flush(sc, &batch, true);
+ if (unlikely(ret && !error))
+ error = ret;
+
+ /*
+ * As an optimization, we don't wait for individual I/O to finish
+ * before sending the next one.
+ * Send them all and wait for pending send count to get to 0
+ * that means all the I/Os have been out and we are good to return
+ */
+
+ ret = smbdirect_connection_send_wait_zero_pending(sc);
+ if (unlikely(ret && !error))
+ error = ret;
+
+ if (unlikely(error))
+ return error;
+
+ return total_count;
+}
+
static void smbdirect_connection_send_io_done(struct ib_cq *cq, struct ib_wc *wc)
{
struct smbdirect_send_io *msg =
@@ -1788,7 +2191,6 @@ static ssize_t smbdirect_map_sges_from_folioq(struct iov_iter *iter,
* BVEC-type iterator and the pages pinned, ref'd or otherwise held in some
* way.
*/
-__maybe_unused /* this is temporary while this file is included in orders */
static ssize_t smbdirect_map_sges_from_iter(struct iov_iter *iter, size_t len,
struct smbdirect_map_sges *state)
{
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 042/127] smb: smbdirect: introduce smbdirect_connection_send_immediate_work()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (40 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 041/127] smb: smbdirect: introduce smbdirect_connection_send_iter() and related functions Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 043/127] smb: smbdirect: introduce smbdirect_connection_negotiation_done() Stefan Metzmacher
` (85 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This is a combination of smb_direct_send_immediate_work() in the server
as well as send_immediate_empty_message() and smbd_post_send_empty() in
the client.
smbdirect_connection_send_immediate_work() replace all of them in
client and server.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 22 +++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index e834fcfe05af..cb977f014c3a 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -1522,6 +1522,28 @@ static void smbdirect_connection_send_io_done(struct ib_cq *cq, struct ib_wc *wc
wake_up(&sc->send_io.pending.dec_wait_queue);
}
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_connection_send_immediate_work(struct work_struct *work)
+{
+ struct smbdirect_socket *sc =
+ container_of(work, struct smbdirect_socket, idle.immediate_work);
+ int ret;
+
+ if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
+ return;
+
+ smbdirect_log_keep_alive(sc, SMBDIRECT_LOG_INFO,
+ "send an empty message\n");
+ sc->statistics.send_empty++;
+ ret = smbdirect_connection_send_single_iter(sc, NULL, NULL, 0, 0);
+ if (ret < 0) {
+ smbdirect_log_write(sc, SMBDIRECT_LOG_ERR,
+ "smbdirect_connection_send_single_iter ret=%1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ smbdirect_connection_schedule_disconnect(sc, ret);
+ }
+}
+
__maybe_unused /* this is temporary while this file is included in orders */
static int smbdirect_connection_post_recv_io(struct smbdirect_recv_io *msg)
{
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 043/127] smb: smbdirect: introduce smbdirect_connection_negotiation_done()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (41 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 042/127] smb: smbdirect: introduce smbdirect_connection_send_immediate_work() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 044/127] smb: smbdirect: introduce smbdirect_mr_io_fill_buffer_descriptor() Stefan Metzmacher
` (84 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This will be used by client and server in order to turn the
connection into a usable state.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 47 ++++++++++++++++++-
1 file changed, 45 insertions(+), 2 deletions(-)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index cb977f014c3a..daab8b5eba49 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -23,6 +23,8 @@ static void smbdirect_connection_schedule_disconnect(struct smbdirect_socket *sc
int error);
static void smbdirect_connection_disconnect_work(struct work_struct *work);
static void smbdirect_connection_idle_timer_work(struct work_struct *work);
+static void smbdirect_connection_recv_io_refill_work(struct work_struct *work);
+static void smbdirect_connection_send_immediate_work(struct work_struct *work);
static void smbdirect_connection_destroy_mr_list(struct smbdirect_socket *sc);
@@ -216,6 +218,49 @@ static void smbdirect_connection_rdma_established(struct smbdirect_socket *sc)
sc->rdma.expected_event = RDMA_CM_EVENT_DISCONNECTED;
}
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_connection_negotiation_done(struct smbdirect_socket *sc)
+{
+ if (unlikely(sc->first_error))
+ return;
+
+ if (sc->status != SMBDIRECT_SOCKET_NEGOTIATE_RUNNING) {
+ /*
+ * Something went wrong...
+ */
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "status=%s first_error=%1pe local: %pISpsfc remote: %pISpsfc\n",
+ smbdirect_socket_status_string(sc->status),
+ SMBDIRECT_DEBUG_ERR_PTR(sc->first_error),
+ &sc->rdma.cm_id->route.addr.src_addr,
+ &sc->rdma.cm_id->route.addr.dst_addr);
+ return;
+ }
+
+ /*
+ * We are done, so we can wake up the waiter.
+ */
+ WARN_ONCE(sc->status == SMBDIRECT_SOCKET_CONNECTED,
+ "status=%s first_error=%1pe",
+ smbdirect_socket_status_string(sc->status),
+ SMBDIRECT_DEBUG_ERR_PTR(sc->first_error));
+ sc->status = SMBDIRECT_SOCKET_CONNECTED;
+
+ /*
+ * We need to setup the refill and send immediate work
+ * in order to get a working connection.
+ */
+ INIT_WORK(&sc->recv_io.posted.refill_work, smbdirect_connection_recv_io_refill_work);
+ INIT_WORK(&sc->idle.immediate_work, smbdirect_connection_send_immediate_work);
+
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
+ "negotiated: local: %pISpsfc remote: %pISpsfc\n",
+ &sc->rdma.cm_id->route.addr.src_addr,
+ &sc->rdma.cm_id->route.addr.dst_addr);
+
+ wake_up(&sc->status_wait);
+}
+
static u32 smbdirect_rdma_rw_send_wrs(struct ib_device *dev,
const struct ib_qp_init_attr *attr)
{
@@ -1522,7 +1567,6 @@ static void smbdirect_connection_send_io_done(struct ib_cq *cq, struct ib_wc *wc
wake_up(&sc->send_io.pending.dec_wait_queue);
}
-__maybe_unused /* this is temporary while this file is included in orders */
static void smbdirect_connection_send_immediate_work(struct work_struct *work)
{
struct smbdirect_socket *sc =
@@ -1840,7 +1884,6 @@ static int smbdirect_connection_recv_io_refill(struct smbdirect_socket *sc)
return posted;
}
-__maybe_unused /* this is temporary while this file is included in orders */
static void smbdirect_connection_recv_io_refill_work(struct work_struct *work)
{
struct smbdirect_socket *sc =
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 044/127] smb: smbdirect: introduce smbdirect_mr_io_fill_buffer_descriptor()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (42 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 043/127] smb: smbdirect: introduce smbdirect_connection_negotiation_done() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 045/127] smb: smbdirect: introduce smbdirect_connection_legacy_debug_proc_show() Stefan Metzmacher
` (83 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This will be used by the client instead of dereferencing
struct smbdirect_mr_io internals.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/common/smbdirect/smbdirect_mr.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_mr.c b/fs/smb/common/smbdirect/smbdirect_mr.c
index 5fd6a853e656..bca58eee783b 100644
--- a/fs/smb/common/smbdirect/smbdirect_mr.c
+++ b/fs/smb/common/smbdirect/smbdirect_mr.c
@@ -453,6 +453,24 @@ smbdirect_connection_register_mr_io(struct smbdirect_socket *sc,
mutex_unlock(&mr->mutex);
return NULL;
}
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_mr_io_fill_buffer_descriptor(struct smbdirect_mr_io *mr,
+ struct smbdirect_buffer_descriptor_v1 *v1)
+{
+ mutex_lock(&mr->mutex);
+ if (mr->state == SMBDIRECT_MR_REGISTERED) {
+ v1->offset = cpu_to_le64(mr->mr->iova);
+ v1->token = cpu_to_le32(mr->mr->rkey);
+ v1->length = cpu_to_le32(mr->mr->length);
+ } else {
+ v1->offset = cpu_to_le64(U64_MAX);
+ v1->token = cpu_to_le32(U32_MAX);
+ v1->length = cpu_to_le32(U32_MAX);
+ }
+ mutex_unlock(&mr->mutex);
+}
+
/*
* Deregister a MR after I/O is done
* This function may wait if remote invalidation is not used
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 045/127] smb: smbdirect: introduce smbdirect_connection_legacy_debug_proc_show()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (43 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 044/127] smb: smbdirect: introduce smbdirect_mr_io_fill_buffer_descriptor() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 046/127] smb: smbdirect: introduce smbdirect_connection_wait_for_connected() Stefan Metzmacher
` (82 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This will be used by the client in order to keep the debug output
in the current way without the need to access struct smbdirect_socket
internals.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_all_c_files.c | 1 +
fs/smb/common/smbdirect/smbdirect_debug.c | 88 +++++++++++++++++++
2 files changed, 89 insertions(+)
create mode 100644 fs/smb/common/smbdirect/smbdirect_debug.c
diff --git a/fs/smb/common/smbdirect/smbdirect_all_c_files.c b/fs/smb/common/smbdirect/smbdirect_all_c_files.c
index 3423330465ae..6d4cd41ebe10 100644
--- a/fs/smb/common/smbdirect/smbdirect_all_c_files.c
+++ b/fs/smb/common/smbdirect/smbdirect_all_c_files.c
@@ -18,3 +18,4 @@
#include "smbdirect_connection.c"
#include "smbdirect_mr.c"
#include "smbdirect_rw.c"
+#include "smbdirect_debug.c"
diff --git a/fs/smb/common/smbdirect/smbdirect_debug.c b/fs/smb/common/smbdirect/smbdirect_debug.c
new file mode 100644
index 000000000000..e7258e0d28a6
--- /dev/null
+++ b/fs/smb/common/smbdirect/smbdirect_debug.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2017, Microsoft Corporation.
+ * Copyright (c) 2025, Stefan Metzmacher
+ */
+
+#include "smbdirect_internal.h"
+#include <linux/seq_file.h>
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_connection_legacy_debug_proc_show(struct smbdirect_socket *sc,
+ unsigned int rdma_readwrite_threshold,
+ struct seq_file *m)
+{
+ const struct smbdirect_socket_parameters *sp;
+
+ if (!sc)
+ return;
+ sp = &sc->parameters;
+
+ seq_puts(m, "\n");
+ seq_printf(m, "SMBDirect protocol version: 0x%x ",
+ SMBDIRECT_V1);
+ seq_printf(m, "transport status: %s (%u)",
+ smbdirect_socket_status_string(sc->status),
+ sc->status);
+
+ seq_puts(m, "\n");
+ seq_printf(m, "Conn receive_credit_max: %u ",
+ sp->recv_credit_max);
+ seq_printf(m, "send_credit_target: %u max_send_size: %u",
+ sp->send_credit_target,
+ sp->max_send_size);
+
+ seq_puts(m, "\n");
+ seq_printf(m, "Conn max_fragmented_recv_size: %u ",
+ sp->max_fragmented_recv_size);
+ seq_printf(m, "max_fragmented_send_size: %u max_receive_size:%u",
+ sp->max_fragmented_send_size,
+ sp->max_recv_size);
+
+ seq_puts(m, "\n");
+ seq_printf(m, "Conn keep_alive_interval: %u ",
+ sp->keepalive_interval_msec * 1000);
+ seq_printf(m, "max_readwrite_size: %u rdma_readwrite_threshold: %u",
+ sp->max_read_write_size,
+ rdma_readwrite_threshold);
+
+ seq_puts(m, "\n");
+ seq_printf(m, "Debug count_get_receive_buffer: %llu ",
+ sc->statistics.get_receive_buffer);
+ seq_printf(m, "count_put_receive_buffer: %llu count_send_empty: %llu",
+ sc->statistics.put_receive_buffer,
+ sc->statistics.send_empty);
+
+ seq_puts(m, "\n");
+ seq_printf(m, "Read Queue count_enqueue_reassembly_queue: %llu ",
+ sc->statistics.enqueue_reassembly_queue);
+ seq_printf(m, "count_dequeue_reassembly_queue: %llu ",
+ sc->statistics.dequeue_reassembly_queue);
+ seq_printf(m, "reassembly_data_length: %u ",
+ sc->recv_io.reassembly.data_length);
+ seq_printf(m, "reassembly_queue_length: %u",
+ sc->recv_io.reassembly.queue_length);
+
+ seq_puts(m, "\n");
+ seq_printf(m, "Current Credits send_credits: %u ",
+ atomic_read(&sc->send_io.credits.count));
+ seq_printf(m, "receive_credits: %u receive_credit_target: %u",
+ atomic_read(&sc->recv_io.credits.count),
+ sc->recv_io.credits.target);
+
+ seq_puts(m, "\n");
+ seq_printf(m, "Pending send_pending: %u ",
+ atomic_read(&sc->send_io.pending.count));
+
+ seq_puts(m, "\n");
+ seq_printf(m, "MR responder_resources: %u ",
+ sp->responder_resources);
+ seq_printf(m, "max_frmr_depth: %u mr_type: 0x%x",
+ sp->max_frmr_depth,
+ sc->mr_io.type);
+
+ seq_puts(m, "\n");
+ seq_printf(m, "MR mr_ready_count: %u mr_used_count: %u",
+ atomic_read(&sc->mr_io.ready.count),
+ atomic_read(&sc->mr_io.used.count));
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 046/127] smb: smbdirect: introduce smbdirect_connection_wait_for_connected()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (44 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 045/127] smb: smbdirect: introduce smbdirect_connection_legacy_debug_proc_show() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 047/127] smb: smbdirect: introduce smbdirect_connection_is_connected() Stefan Metzmacher
` (81 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This will be used by client and server in order to wait for
the connect/negotiation to finish in order to get a usable
connection.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 68 +++++++++++++++++++
1 file changed, 68 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index daab8b5eba49..858b071ba1bb 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -900,6 +900,74 @@ static void smbdirect_connection_disconnect_work(struct work_struct *work)
smbdirect_connection_wake_up_all(sc);
}
+__maybe_unused /* this is temporary while this file is included in orders */
+static int smbdirect_connection_wait_for_connected(struct smbdirect_socket *sc)
+{
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_storage ss;
+ } src_addr, dst_addr;
+ const struct sockaddr *src = NULL;
+ const struct sockaddr *dst = NULL;
+ char _devname[IB_DEVICE_NAME_MAX] = { 0, };
+ const char *devname = NULL;
+ int ret;
+
+ if (sc->rdma.cm_id) {
+ src_addr.ss = sc->rdma.cm_id->route.addr.src_addr;
+ if (src_addr.sa.sa_family != AF_UNSPEC)
+ src = &src_addr.sa;
+ dst_addr.ss = sc->rdma.cm_id->route.addr.dst_addr;
+ if (dst_addr.sa.sa_family != AF_UNSPEC)
+ dst = &dst_addr.sa;
+
+ if (sc->ib.dev) {
+ memcpy(_devname, sc->ib.dev->name, IB_DEVICE_NAME_MAX);
+ devname = _devname;
+ }
+ }
+
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
+ "waiting for connection: device: %.*s local: %pISpsfc remote: %pISpsfc\n",
+ IB_DEVICE_NAME_MAX, devname, src, dst);
+
+ ret = wait_event_interruptible_timeout(sc->status_wait,
+ sc->status == SMBDIRECT_SOCKET_CONNECTED ||
+ sc->first_error,
+ msecs_to_jiffies(sp->negotiate_timeout_msec));
+ if (sc->rdma.cm_id) {
+ /*
+ * Maybe src and dev are updated in the meantime.
+ */
+ src_addr.ss = sc->rdma.cm_id->route.addr.src_addr;
+ if (src_addr.sa.sa_family != AF_UNSPEC)
+ src = &src_addr.sa;
+ dst_addr.ss = sc->rdma.cm_id->route.addr.dst_addr;
+ if (dst_addr.sa.sa_family != AF_UNSPEC)
+ dst = &dst_addr.sa;
+
+ if (sc->ib.dev) {
+ memcpy(_devname, sc->ib.dev->name, IB_DEVICE_NAME_MAX);
+ devname = _devname;
+ }
+ }
+ if (ret == 0)
+ ret = -ETIMEDOUT;
+ if (ret < 0)
+ smbdirect_connection_schedule_disconnect(sc, ret);
+ if (sc->first_error) {
+ ret = sc->first_error;
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "connection failed %1pe device: %.*s local: %pISpsfc remote: %pISpsfc\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret),
+ IB_DEVICE_NAME_MAX, devname, src, dst);
+ return ret;
+ }
+
+ return 0;
+}
+
static void smbdirect_connection_destroy(struct smbdirect_socket *sc)
{
struct smbdirect_recv_io *recv_io;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 047/127] smb: smbdirect: introduce smbdirect_connection_is_connected()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (45 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 046/127] smb: smbdirect: introduce smbdirect_connection_wait_for_connected() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 048/127] smb: smbdirect: introduce smbdirect_socket_shutdown() Stefan Metzmacher
` (80 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This is a simple way to check is the connection is still ok
without the need to know internals of struct smbdirect_socket.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/common/smbdirect/smbdirect_connection.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index 858b071ba1bb..1487efbe7620 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -900,6 +900,14 @@ static void smbdirect_connection_disconnect_work(struct work_struct *work)
smbdirect_connection_wake_up_all(sc);
}
+__maybe_unused /* this is temporary while this file is included in orders */
+static bool smbdirect_connection_is_connected(struct smbdirect_socket *sc)
+{
+ if (unlikely(!sc || sc->first_error || sc->status != SMBDIRECT_SOCKET_CONNECTED))
+ return false;
+ return true;
+}
+
__maybe_unused /* this is temporary while this file is included in orders */
static int smbdirect_connection_wait_for_connected(struct smbdirect_socket *sc)
{
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 048/127] smb: smbdirect: introduce smbdirect_socket_shutdown()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (46 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 047/127] smb: smbdirect: introduce smbdirect_connection_is_connected() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 049/127] smb: smbdirect: introduce smbdirect_socket_init_{new,accepting}() and helpers Stefan Metzmacher
` (79 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This can be used by client and server to trigger a
disconnect of the connection, the idea of to be
similar to kernel_sock_shutdown(), but for smbdirect
there's no point in shutting down only one direct
so there's no 'how' argument.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/common/smbdirect/smbdirect_connection.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index 1487efbe7620..5670e442e129 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -1100,6 +1100,12 @@ static void smbdirect_connection_destroy_sync(struct smbdirect_socket *sc)
SMBDIRECT_DEBUG_ERR_PTR(sc->first_error));
}
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_socket_shutdown(struct smbdirect_socket *sc)
+{
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+}
+
static void smbdirect_connection_idle_timer_work(struct work_struct *work)
{
struct smbdirect_socket *sc =
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 049/127] smb: smbdirect: introduce smbdirect_socket_init_{new,accepting}() and helpers
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (47 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 048/127] smb: smbdirect: introduce smbdirect_socket_shutdown() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 050/127] smb: smbdirect: introduce smbdirect_connect[_sync]() Stefan Metzmacher
` (78 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
These will be used in order to initialize struct smbdirect_socket
with rdma.cm_id being valid from the start in order to hold
a reference to the correct net namespace, this will allow
us to implement async connecting and accepting logic in
the next steps.
This comes with some related helper functions in
order to initialize the socket without the need
to access internals of struct smbdirect_socket:
smbdirect_socket_set_initial_parameters
smbdirect_socket_get_current_parameters
smbdirect_socket_set_kernel_settings
smbdirect_socket_set_custom_workqueue
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 145 ++++++++++++++++++
1 file changed, 145 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index 5670e442e129..34be36cf5d00 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -67,6 +67,151 @@ static void smbdirect_socket_prepare_create(struct smbdirect_socket *sc,
INIT_DELAYED_WORK(&sc->idle.timer_work, smbdirect_connection_idle_timer_work);
}
+static int smbdirect_socket_rdma_event_handler(struct rdma_cm_id *id,
+ struct rdma_cm_event *event)
+{
+ struct smbdirect_socket *sc = id->context;
+ int ret = -ESTALE;
+
+ /*
+ * This should be replaced before any real work
+ * starts! So it should never be called!
+ */
+
+ if (event->event == RDMA_CM_EVENT_DEVICE_REMOVAL)
+ ret = -ENETDOWN;
+ if (IS_ERR(SMBDIRECT_DEBUG_ERR_PTR(event->status)))
+ ret = event->status;
+ pr_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));
+ WARN_ONCE(1, "%s should not be called!\n", __func__);
+ sc->rdma.cm_id = NULL;
+ return 1;
+}
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static int smbdirect_socket_init_new(struct net *net, struct smbdirect_socket *sc)
+{
+ struct rdma_cm_id *id;
+
+ smbdirect_socket_init(sc);
+
+ id = rdma_create_id(net,
+ smbdirect_socket_rdma_event_handler,
+ sc,
+ RDMA_PS_TCP,
+ IB_QPT_RC);
+ if (IS_ERR(id)) {
+ pr_err("%s: rdma_create_id() failed %1pe\n", __func__, id);
+ return PTR_ERR(id);
+ }
+
+ sc->rdma.cm_id = id;
+
+ INIT_WORK(&sc->disconnect_work, smbdirect_connection_disconnect_work);
+
+ return 0;
+}
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static int smbdirect_socket_init_accepting(struct rdma_cm_id *id, struct smbdirect_socket *sc)
+{
+ smbdirect_socket_init(sc);
+
+ sc->rdma.cm_id = id;
+ sc->rdma.cm_id->context = sc;
+ sc->rdma.cm_id->event_handler = smbdirect_socket_rdma_event_handler;
+
+ sc->ib.dev = sc->rdma.cm_id->device;
+
+ INIT_WORK(&sc->disconnect_work, smbdirect_connection_disconnect_work);
+
+ return 0;
+}
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static int smbdirect_socket_set_initial_parameters(struct smbdirect_socket *sc,
+ const struct smbdirect_socket_parameters *sp)
+{
+ /*
+ * This is only allowed before connect or accept
+ */
+ WARN_ONCE(sc->status != SMBDIRECT_SOCKET_CREATED,
+ "status=%s first_error=%1pe",
+ smbdirect_socket_status_string(sc->status),
+ SMBDIRECT_DEBUG_ERR_PTR(sc->first_error));
+ if (sc->status != SMBDIRECT_SOCKET_CREATED)
+ return -EINVAL;
+
+ /*
+ * Make a copy of the callers parameters
+ * from here we only work on the copy
+ *
+ * TODO: do we want consistency checking?
+ */
+ sc->parameters = *sp;
+
+ return 0;
+}
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static const struct smbdirect_socket_parameters *
+smbdirect_socket_get_current_parameters(struct smbdirect_socket *sc)
+{
+ return &sc->parameters;
+}
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static int smbdirect_socket_set_kernel_settings(struct smbdirect_socket *sc,
+ enum ib_poll_context poll_ctx,
+ gfp_t gfp_mask)
+{
+ /*
+ * This is only allowed before connect or accept
+ */
+ WARN_ONCE(sc->status != SMBDIRECT_SOCKET_CREATED,
+ "status=%s first_error=%1pe",
+ smbdirect_socket_status_string(sc->status),
+ SMBDIRECT_DEBUG_ERR_PTR(sc->first_error));
+ if (sc->status != SMBDIRECT_SOCKET_CREATED)
+ return -EINVAL;
+
+ sc->ib.poll_ctx = poll_ctx;
+
+ sc->send_io.mem.gfp_mask = gfp_mask;
+ sc->recv_io.mem.gfp_mask = gfp_mask;
+ sc->rw_io.mem.gfp_mask = gfp_mask;
+
+ return 0;
+}
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static int smbdirect_socket_set_custom_workqueue(struct smbdirect_socket *sc,
+ struct workqueue_struct *workqueue)
+{
+ /*
+ * This is only allowed before connect or accept
+ */
+ WARN_ONCE(sc->status != SMBDIRECT_SOCKET_CREATED,
+ "status=%s first_error=%1pe",
+ smbdirect_socket_status_string(sc->status),
+ SMBDIRECT_DEBUG_ERR_PTR(sc->first_error));
+ if (sc->status != SMBDIRECT_SOCKET_CREATED)
+ return -EINVAL;
+
+ /*
+ * Remember the callers workqueue
+ */
+ sc->workqueue = workqueue;
+
+ return 0;
+}
+
__maybe_unused /* this is temporary while this file is included in orders */
static void smbdirect_socket_set_logging(struct smbdirect_socket *sc,
void *private_ptr,
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 050/127] smb: smbdirect: introduce smbdirect_connect[_sync]()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (48 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 049/127] smb: smbdirect: introduce smbdirect_socket_init_{new,accepting}() and helpers Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 051/127] smb: smbdirect: introduce smbdirect_accept_connect_request() Stefan Metzmacher
` (77 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This implements a fully async connect logic over
all rdma related operations: rdma_resolve_addr,
rdma_resolve_route and rdma_connect_locked
until we reach RDMA_CM_EVENT_ESTABLISHED,
followed by the smbdirect negotiation request/response
handling until we reach SMBDIRECT_SOCKET_CONNECTED.
smbdirect_connect_sync() is just a useful wrapper
around the async logic calling smbdirect_connect()
followed by smbdirect_connection_wait_for_connected(),
which only waits for SMBDIRECT_SOCKET_CONNECTED or
an error.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_all_c_files.c | 1 +
fs/smb/common/smbdirect/smbdirect_connect.c | 796 ++++++++++++++++++
2 files changed, 797 insertions(+)
create mode 100644 fs/smb/common/smbdirect/smbdirect_connect.c
diff --git a/fs/smb/common/smbdirect/smbdirect_all_c_files.c b/fs/smb/common/smbdirect/smbdirect_all_c_files.c
index 6d4cd41ebe10..257cf0cf92d0 100644
--- a/fs/smb/common/smbdirect/smbdirect_all_c_files.c
+++ b/fs/smb/common/smbdirect/smbdirect_all_c_files.c
@@ -19,3 +19,4 @@
#include "smbdirect_mr.c"
#include "smbdirect_rw.c"
#include "smbdirect_debug.c"
+#include "smbdirect_connect.c"
diff --git a/fs/smb/common/smbdirect/smbdirect_connect.c b/fs/smb/common/smbdirect/smbdirect_connect.c
new file mode 100644
index 000000000000..458566c99d2e
--- /dev/null
+++ b/fs/smb/common/smbdirect/smbdirect_connect.c
@@ -0,0 +1,796 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2012,2016,2017,2025 Stefan Metzmacher
+ */
+
+#include "smbdirect_internal.h"
+
+static int smbdirect_connect_setup_connection(struct smbdirect_socket *sc);
+static int smbdirect_connect_resolve_addr(struct smbdirect_socket *sc,
+ const struct sockaddr *src,
+ const struct sockaddr *dst);
+static int smbdirect_connect_rdma_event_handler(struct rdma_cm_id *id,
+ struct rdma_cm_event *event);
+static int smbdirect_connect_negotiate_start(struct smbdirect_socket *sc);
+static void smbdirect_connect_negotiate_send_done(struct ib_cq *cq, struct ib_wc *wc);
+static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc *wc);
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static int smbdirect_connect(struct smbdirect_socket *sc,
+ const struct sockaddr *dst)
+{
+ const struct sockaddr *src = NULL;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_storage ss;
+ } src_addr = {
+ .sa = {
+ .sa_family = AF_UNSPEC,
+ },
+ };
+ int ret;
+
+ if (sc->first_error)
+ return -ENOTCONN;
+
+ if (sc->status != SMBDIRECT_SOCKET_CREATED)
+ return -EALREADY;
+
+ if (WARN_ON_ONCE(!sc->rdma.cm_id))
+ return -EINVAL;
+
+ src_addr.ss = sc->rdma.cm_id->route.addr.src_addr;
+ if (src_addr.sa.sa_family != AF_UNSPEC)
+ src = &src_addr.sa;
+
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
+ "connect: src: %pISpsfc dst: %pISpsfc\n",
+ src, dst);
+
+ ret = smbdirect_connect_setup_connection(sc);
+ if (ret)
+ return ret;
+
+ ret = smbdirect_connect_resolve_addr(sc, src, dst);
+ if (ret)
+ return ret;
+
+ /*
+ * The rest happens async via smbdirect_connect_rdma_event_handler()
+ * the caller will decide to wait or not.
+ */
+ return 0;
+}
+
+static int smbdirect_connect_setup_connection(struct smbdirect_socket *sc)
+{
+ int ret;
+
+ ret = rdma_set_afonly(sc->rdma.cm_id, 1);
+ if (ret) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "rdma_set_afonly() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ return ret;
+ }
+
+ rdma_lock_handler(sc->rdma.cm_id);
+ sc->rdma.cm_id->event_handler = smbdirect_connect_rdma_event_handler;
+ rdma_unlock_handler(sc->rdma.cm_id);
+
+ WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_CREATED);
+ sc->status = SMBDIRECT_SOCKET_RESOLVE_ADDR_NEEDED;
+
+ return 0;
+}
+
+static int smbdirect_connect_resolve_addr(struct smbdirect_socket *sc,
+ const struct sockaddr *src,
+ const struct sockaddr *dst)
+{
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+ struct sockaddr *src_addr = NULL;
+ struct sockaddr *dst_addr = NULL;
+ int ret;
+
+ src_addr = (struct sockaddr *)src;
+ if (src_addr && src_addr->sa_family == AF_UNSPEC)
+ src_addr = NULL;
+ dst_addr = (struct sockaddr *)dst;
+
+ WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RESOLVE_ADDR_NEEDED);
+ sc->status = SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING;
+ sc->rdma.expected_event = RDMA_CM_EVENT_ADDR_RESOLVED;
+ ret = rdma_resolve_addr(sc->rdma.cm_id, src_addr, dst_addr,
+ sp->resolve_addr_timeout_msec);
+ if (ret) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "rdma_resolve_addr() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ return ret;
+ }
+
+ return 0;
+}
+
+static int smbdirect_connect_resolve_route(struct smbdirect_socket *sc)
+{
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+ int ret;
+
+ WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RESOLVE_ROUTE_NEEDED);
+ sc->status = SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING;
+ sc->rdma.expected_event = RDMA_CM_EVENT_ROUTE_RESOLVED;
+ ret = rdma_resolve_route(sc->rdma.cm_id, sp->resolve_route_timeout_msec);
+ if (ret) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "rdma_resolve_route() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ return ret;
+ }
+
+ return 0;
+}
+
+static int smbdirect_connect_rdma_connect(struct smbdirect_socket *sc)
+{
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+ struct rdma_conn_param conn_param;
+ __be32 ird_ord_hdr[2];
+ int ret;
+
+ sc->ib.dev = sc->rdma.cm_id->device;
+
+ if (!smbdirect_frwr_is_supported(&sc->ib.dev->attrs)) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "Fast Registration Work Requests (FRWR) is not supported device %.*s\n",
+ IB_DEVICE_NAME_MAX,
+ sc->ib.dev->name);
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "Device capability flags = %llx max_fast_reg_page_list_len = %u\n",
+ sc->ib.dev->attrs.device_cap_flags,
+ sc->ib.dev->attrs.max_fast_reg_page_list_len);
+ return -EPROTONOSUPPORT;
+ }
+
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
+ "rdma connect: 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);
+
+ sp->max_frmr_depth = min_t(u32, sp->max_frmr_depth,
+ sc->ib.dev->attrs.max_fast_reg_page_list_len);
+ sc->mr_io.type = IB_MR_TYPE_MEM_REG;
+ if (sc->ib.dev->attrs.kernel_cap_flags & IBK_SG_GAPS_REG)
+ sc->mr_io.type = IB_MR_TYPE_SG_GAPS;
+
+ sp->responder_resources = min_t(u8, sp->responder_resources,
+ sc->ib.dev->attrs.max_qp_rd_atom);
+ smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_INFO,
+ "responder_resources=%d\n",
+ sp->responder_resources);
+
+ ret = smbdirect_connection_create_qp(sc);
+ if (ret) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "smbdirect_connection_create_qp() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ return ret;
+ }
+
+ memset(&conn_param, 0, sizeof(conn_param));
+ conn_param.initiator_depth = sp->initiator_depth;
+ conn_param.responder_resources = sp->responder_resources;
+
+ /* Need to send IRD/ORD in private data for iWARP */
+ if (rdma_protocol_iwarp(sc->ib.dev, sc->rdma.cm_id->port_num)) {
+ ird_ord_hdr[0] = cpu_to_be32(conn_param.responder_resources);
+ ird_ord_hdr[1] = cpu_to_be32(conn_param.initiator_depth);
+ conn_param.private_data = ird_ord_hdr;
+ conn_param.private_data_len = sizeof(ird_ord_hdr);
+ } else {
+ conn_param.private_data = NULL;
+ conn_param.private_data_len = 0;
+ }
+
+ conn_param.retry_count = SMBDIRECT_RDMA_CM_RETRY;
+ conn_param.rnr_retry_count = SMBDIRECT_RDMA_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;
+ sc->rdma.expected_event = RDMA_CM_EVENT_ESTABLISHED;
+ ret = rdma_connect_locked(sc->rdma.cm_id, &conn_param);
+ if (ret) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "rdma_connect_locked() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ return ret;
+ }
+
+ /*
+ * start with the rdma connect timeout and SMBDIRECT_KEEPALIVE_PENDING
+ * so that the timer will cause a disconnect.
+ */
+ INIT_DELAYED_WORK(&sc->idle.timer_work, smbdirect_connection_idle_timer_work);
+ sc->idle.keepalive = SMBDIRECT_KEEPALIVE_PENDING;
+ mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
+ msecs_to_jiffies(sp->rdma_connect_timeout_msec));
+
+ return 0;
+}
+
+static int smbdirect_connect_rdma_event_handler(struct rdma_cm_id *id,
+ struct rdma_cm_event *event)
+{
+ struct smbdirect_socket *sc = id->context;
+ u8 peer_initiator_depth;
+ u8 peer_responder_resources;
+ int ret;
+
+ /*
+ * 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,
+ * as we might sleep.
+ *
+ * We didn't timeout so we cancel our idle timer,
+ * it will be scheduled again if needed.
+ */
+ WARN_ON_ONCE(in_interrupt());
+ sc->idle.keepalive = SMBDIRECT_KEEPALIVE_NONE;
+ cancel_delayed_work_sync(&sc->idle.timer_work);
+
+ if (event->status || event->event != sc->rdma.expected_event) {
+ ret = -ECONNABORTED;
+
+ if (event->event == RDMA_CM_EVENT_REJECTED)
+ ret = -ECONNREFUSED;
+ 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));
+
+ smbdirect_connection_schedule_disconnect(sc, ret);
+ 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_ADDR_RESOLVED:
+ WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING);
+ sc->status = SMBDIRECT_SOCKET_RESOLVE_ROUTE_NEEDED;
+
+ ret = smbdirect_connect_resolve_route(sc);
+ if (ret)
+ smbdirect_connection_schedule_disconnect(sc, ret);
+ return 0;
+
+ case RDMA_CM_EVENT_ROUTE_RESOLVED:
+ WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING);
+ sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED;
+
+ ret = smbdirect_connect_rdma_connect(sc);
+ if (ret)
+ smbdirect_connection_schedule_disconnect(sc, ret);
+ return 0;
+
+ case RDMA_CM_EVENT_ESTABLISHED:
+ smbdirect_connection_rdma_established(sc);
+
+ WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING);
+ sc->status = SMBDIRECT_SOCKET_NEGOTIATE_NEEDED;
+
+ /*
+ * Here we work around an inconsistency between
+ * iWarp and other devices (at least rxe and irdma using RoCEv2)
+ */
+ if (rdma_protocol_iwarp(id->device, id->port_num)) {
+ /*
+ * iWarp devices report the peer's values
+ * with the perspective of the peer here.
+ * Tested with siw and irdma (in iwarp mode)
+ * We need to change to our perspective here,
+ * so we need to switch the values.
+ */
+ peer_initiator_depth = event->param.conn.responder_resources;
+ peer_responder_resources = event->param.conn.initiator_depth;
+ } else {
+ /*
+ * Non iWarp devices report the peer's values
+ * already changed to our perspective here.
+ * Tested with rxe and irdma (in roce mode).
+ */
+ peer_initiator_depth = event->param.conn.initiator_depth;
+ peer_responder_resources = event->param.conn.responder_resources;
+ }
+ smbdirect_connection_negotiate_rdma_resources(sc,
+ peer_initiator_depth,
+ peer_responder_resources,
+ &event->param.conn);
+
+ ret = smbdirect_connect_negotiate_start(sc);
+ if (ret)
+ smbdirect_connection_schedule_disconnect(sc, ret);
+ return 0;
+
+ default:
+ break;
+ }
+
+ /*
+ * This is an internal error
+ */
+ WARN_ON_ONCE(sc->rdma.expected_event != RDMA_CM_EVENT_ESTABLISHED);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+ return 0;
+}
+
+static int smbdirect_connect_negotiate_start(struct smbdirect_socket *sc)
+{
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+ struct smbdirect_recv_io *recv_io = NULL;
+ struct smbdirect_send_io *send_io = NULL;
+ struct smbdirect_negotiate_req *nreq = NULL;
+ struct ib_send_wr send_wr;
+ int ret;
+
+ WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_NEGOTIATE_NEEDED);
+ sc->status = SMBDIRECT_SOCKET_NEGOTIATE_RUNNING;
+
+ ret = smbdirect_connection_create_mem_pools(sc);
+ if (ret) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "smbdirect_connection_create_mem_pools() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ goto create_mem_pools_failed;
+ }
+
+ /*
+ * Initialize the local credits to post
+ * IB_WR_SEND[_WITH_INV].
+ */
+ atomic_set(&sc->send_io.lcredits.count, sp->send_credit_target);
+
+ recv_io = smbdirect_connection_get_recv_io(sc);
+ if (WARN_ON_ONCE(!recv_io)) {
+ ret = -EINVAL;
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "smbdirect_connection_get_recv_io() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ goto get_recv_io_failed;
+ }
+ recv_io->cqe.done = smbdirect_connect_negotiate_recv_done;
+
+ send_io = smbdirect_connection_alloc_send_io(sc);
+ if (IS_ERR(send_io)) {
+ ret = PTR_ERR(send_io);
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "smbdirect_connection_alloc_send_io() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ goto alloc_send_io_failed;
+ }
+ send_io->cqe.done = smbdirect_connect_negotiate_send_done;
+
+ nreq = (struct smbdirect_negotiate_req *)send_io->packet;
+ nreq->min_version = cpu_to_le16(SMBDIRECT_V1);
+ nreq->max_version = cpu_to_le16(SMBDIRECT_V1);
+ nreq->reserved = 0;
+ nreq->credits_requested = cpu_to_le16(sp->send_credit_target);
+ nreq->preferred_send_size = cpu_to_le32(sp->max_send_size);
+ nreq->max_receive_size = cpu_to_le32(sp->max_recv_size);
+ nreq->max_fragmented_size = cpu_to_le32(sp->max_fragmented_recv_size);
+
+ smbdirect_log_negotiate(sc, SMBDIRECT_LOG_INFO,
+ "ReqOut: %s%x, %s%x, %s%u, %s%u, %s%u, %s%u\n",
+ "MinVersion=0x",
+ le16_to_cpu(nreq->min_version),
+ "MaxVersion=0x",
+ le16_to_cpu(nreq->max_version),
+ "CreditsRequested=",
+ le16_to_cpu(nreq->credits_requested),
+ "PreferredSendSize=",
+ le32_to_cpu(nreq->preferred_send_size),
+ "MaxRecvSize=",
+ le32_to_cpu(nreq->max_receive_size),
+ "MaxFragmentedSize=",
+ le32_to_cpu(nreq->max_fragmented_size));
+
+ send_io->sge[0].addr = ib_dma_map_single(sc->ib.dev,
+ nreq,
+ sizeof(*nreq),
+ DMA_TO_DEVICE);
+ ret = ib_dma_mapping_error(sc->ib.dev, send_io->sge[0].addr);
+ if (ret) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "ib_dma_mapping_error() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ goto dma_mapping_failed;
+ }
+
+ send_io->sge[0].length = sizeof(*nreq);
+ send_io->sge[0].lkey = sc->ib.pd->local_dma_lkey;
+ send_io->num_sge = 1;
+
+ ib_dma_sync_single_for_device(sc->ib.dev,
+ send_io->sge[0].addr,
+ send_io->sge[0].length,
+ DMA_TO_DEVICE);
+
+ smbdirect_log_rdma_send(sc, SMBDIRECT_LOG_INFO,
+ "sge addr=0x%llx length=%u lkey=0x%x\n",
+ send_io->sge[0].addr,
+ send_io->sge[0].length,
+ send_io->sge[0].lkey);
+
+ /*
+ * Now post the recv_io buffer in order to get
+ * the negotiate response
+ */
+ sc->recv_io.expected = SMBDIRECT_EXPECT_NEGOTIATE_REP;
+ ret = smbdirect_connection_post_recv_io(recv_io);
+ if (ret) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "smbdirect_connection_post_recv_io() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ goto post_recv_io_failed;
+ }
+
+ send_wr.next = NULL;
+ send_wr.wr_cqe = &send_io->cqe;
+ send_wr.sg_list = send_io->sge;
+ send_wr.num_sge = send_io->num_sge;
+ send_wr.opcode = IB_WR_SEND;
+ send_wr.send_flags = IB_SEND_SIGNALED;
+
+ ret = smbdirect_connection_post_send_wr(sc, &send_wr);
+ if (ret) {
+ /* if we reach here, post send failed */
+ smbdirect_log_rdma_send(sc, SMBDIRECT_LOG_ERR,
+ "smbdirect_connection_post_send_wr() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ goto post_send_wr_failed;
+ }
+
+ /*
+ * start with the negotiate timeout and SMBDIRECT_KEEPALIVE_PENDING
+ * so that the timer will cause a disconnect.
+ */
+ sc->idle.keepalive = SMBDIRECT_KEEPALIVE_PENDING;
+ mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
+ msecs_to_jiffies(sp->negotiate_timeout_msec));
+
+ return 0;
+
+post_send_wr_failed:
+ /*
+ * ib_dma_unmap_single is called in
+ * smbdirect_connection_free_send_io()
+ */
+ smbdirect_connection_free_send_io(send_io);
+ /*
+ * recv_io is given to the rdma layer,
+ * we should not put it even on error
+ * nor call smbdirect_connection_destroy_mem_pools()
+ * it will be cleaned up during disconnect.
+ */
+ return ret;
+
+post_recv_io_failed:
+ /*
+ * ib_dma_unmap_single is called in
+ * smbdirect_connection_free_send_io()
+ */
+dma_mapping_failed:
+ smbdirect_connection_free_send_io(send_io);
+
+alloc_send_io_failed:
+ smbdirect_connection_put_recv_io(recv_io);
+
+get_recv_io_failed:
+ smbdirect_connection_destroy_mem_pools(sc);
+
+create_mem_pools_failed:
+ return ret;
+}
+
+static void smbdirect_connect_negotiate_send_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+ struct smbdirect_send_io *send_io =
+ container_of(wc->wr_cqe, struct smbdirect_send_io, cqe);
+ struct smbdirect_socket *sc = send_io->socket;
+
+ smbdirect_log_rdma_send(sc, SMBDIRECT_LOG_INFO,
+ "smbdirect_send_io completed. status='%s (%d)', opcode=%d\n",
+ ib_wc_status_msg(wc->status), wc->status, wc->opcode);
+
+ /* Note this frees wc->wr_cqe, but not wc */
+ smbdirect_connection_free_send_io(send_io);
+ atomic_dec(&sc->send_io.pending.count);
+
+ if (unlikely(wc->status != IB_WC_SUCCESS || WARN_ON_ONCE(wc->opcode != IB_WC_SEND))) {
+ if (wc->status != IB_WC_WR_FLUSH_ERR)
+ smbdirect_log_rdma_send(sc, SMBDIRECT_LOG_ERR,
+ "wc->status=%s (%d) wc->opcode=%d\n",
+ ib_wc_status_msg(wc->status), wc->status, wc->opcode);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+ return;
+ }
+}
+
+static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+ struct smbdirect_recv_io *recv_io =
+ container_of(wc->wr_cqe, struct smbdirect_recv_io, cqe);
+ struct smbdirect_socket *sc = recv_io->socket;
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+ struct smbdirect_negotiate_resp *nrep;
+ u16 negotiated_version;
+ u16 credits_requested;
+ u16 credits_granted;
+ u32 status;
+ u32 max_readwrite_size;
+ u32 preferred_send_size;
+ u32 max_receive_size;
+ u32 max_fragmented_size;
+ int posted;
+ int ret;
+
+ if (unlikely(wc->status != IB_WC_SUCCESS || WARN_ON_ONCE(wc->opcode != IB_WC_RECV))) {
+ if (wc->status != IB_WC_WR_FLUSH_ERR)
+ smbdirect_log_rdma_recv(sc, SMBDIRECT_LOG_ERR,
+ "wc->status=%s (%d) wc->opcode=%d\n",
+ ib_wc_status_msg(wc->status), wc->status, wc->opcode);
+ goto error;
+ }
+
+ smbdirect_log_rdma_recv(sc, SMBDIRECT_LOG_INFO,
+ "smbdirect_recv_io completed. status='%s (%d)', opcode=%d\n",
+ ib_wc_status_msg(wc->status), wc->status, wc->opcode);
+
+ /*
+ * Reset timer to the keepalive interval in
+ * order to trigger our next keepalive message.
+ */
+ sc->idle.keepalive = SMBDIRECT_KEEPALIVE_NONE;
+ mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
+ msecs_to_jiffies(sp->keepalive_interval_msec));
+
+ ib_dma_sync_single_for_cpu(wc->qp->device,
+ recv_io->sge.addr,
+ recv_io->sge.length,
+ DMA_FROM_DEVICE);
+
+ if (wc->byte_len < sizeof(*nrep)) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "wc->byte_len=%u < %zu\n",
+ wc->byte_len, sizeof(*nrep));
+ goto error;
+ }
+
+ nrep = (struct smbdirect_negotiate_resp *)recv_io->packet;
+ negotiated_version = le16_to_cpu(nrep->negotiated_version);
+ credits_requested = le16_to_cpu(nrep->credits_requested);
+ credits_granted = le16_to_cpu(nrep->credits_granted);
+ status = le32_to_cpu(nrep->status);
+ max_readwrite_size = le32_to_cpu(nrep->max_readwrite_size);
+ preferred_send_size = le32_to_cpu(nrep->preferred_send_size);
+ max_receive_size = le32_to_cpu(nrep->max_receive_size);
+ max_fragmented_size = le32_to_cpu(nrep->max_fragmented_size);
+
+ smbdirect_log_negotiate(sc, SMBDIRECT_LOG_INFO,
+ "RepIn: %s%x, %s%x, %s%x, %s%u, %s%u, %s%x, %s%u, %s%u, %s%u, %s%u\n",
+ "MinVersion=0x",
+ le16_to_cpu(nrep->min_version),
+ "MaxVersion=0x",
+ le16_to_cpu(nrep->max_version),
+ "NegotiatedVersion=0x",
+ le16_to_cpu(nrep->negotiated_version),
+ "CreditsRequested=",
+ le16_to_cpu(nrep->credits_requested),
+ "CreditsGranted=",
+ le16_to_cpu(nrep->credits_granted),
+ "Status=0x",
+ le32_to_cpu(nrep->status),
+ "MaxReadWriteSize=",
+ le32_to_cpu(nrep->max_readwrite_size),
+ "PreferredSendSize=",
+ le32_to_cpu(nrep->preferred_send_size),
+ "MaxRecvSize=",
+ le32_to_cpu(nrep->max_receive_size),
+ "MaxFragmentedSize=",
+ le32_to_cpu(nrep->max_fragmented_size));
+
+ if (negotiated_version != SMBDIRECT_V1) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "invalid: negotiated_version=0x%x\n",
+ negotiated_version);
+ goto error;
+ }
+
+ if (max_receive_size < SMBDIRECT_MIN_RECEIVE_SIZE) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "invalid: max_receive_size=%u < %u\n",
+ max_receive_size,
+ SMBDIRECT_MIN_RECEIVE_SIZE);
+ goto error;
+ }
+
+ if (max_fragmented_size < SMBDIRECT_MIN_FRAGMENTED_SIZE) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "invalid: max_fragmented_size=%u < %u\n",
+ max_fragmented_size,
+ SMBDIRECT_MIN_FRAGMENTED_SIZE);
+ goto error;
+ }
+
+ if (credits_granted == 0) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "invalid: credits_granted == 0\n");
+ goto error;
+ }
+
+ if (credits_requested == 0) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "invalid: credits_requested == 0\n");
+ goto error;
+ }
+
+ if (preferred_send_size > sp->max_recv_size) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "invalid: preferred_send_size=%u < max_recv_size=%u\n",
+ preferred_send_size,
+ sp->max_recv_size);
+ goto error;
+ }
+
+ if (status != 0) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "invalid: status=0x%x != 0x0\n",
+ status);
+ goto error;
+ }
+
+ /*
+ * We take the value from the peer, which is checked to be higher than 0,
+ * but we limit it to the max value we support in order to have
+ * the main logic simpler.
+ */
+ sc->recv_io.credits.target = credits_requested;
+ sc->recv_io.credits.target = min_t(u16, sc->recv_io.credits.target,
+ sp->recv_credit_max);
+
+ /*
+ * At least the value of SMBDIRECT_MIN_RECEIVE_SIZE is used.
+ */
+ sp->max_recv_size = min_t(u32, sp->max_recv_size, preferred_send_size);
+ sp->max_recv_size = max_t(u32, sp->max_recv_size, SMBDIRECT_MIN_RECEIVE_SIZE);
+
+ /*
+ * Note nrep->max_receive_size was already checked against
+ * SMBDIRECT_MIN_RECEIVE_SIZE above.
+ */
+ sp->max_send_size = min_t(u32, sp->max_send_size, max_receive_size);
+
+ /*
+ * Make sure the resulting max_frmr_depth is at least 1,
+ * which means max_read_write_size needs to be at least PAGE_SIZE.
+ */
+ sp->max_read_write_size = min_t(u32, sp->max_frmr_depth * PAGE_SIZE,
+ max_readwrite_size);
+ if (sp->max_read_write_size < PAGE_SIZE) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "invalid: max_readwrite_size=%u < PAGE_SIZE(%lu)\n",
+ max_readwrite_size,
+ PAGE_SIZE);
+ goto error;
+ }
+ sp->max_frmr_depth = sp->max_read_write_size / PAGE_SIZE;
+
+ /*
+ * Note nrep->credits_granted was already checked against 0 above.
+ */
+ atomic_set(&sc->send_io.credits.count, credits_granted);
+
+ /*
+ * Note nrep->max_fragmented_size was already checked against
+ * SMBDIRECT_MIN_FRAGMENTED_SIZE above.
+ */
+ sp->max_fragmented_send_size = max_fragmented_size;
+
+ /*
+ * Give recv_io back to the recv_io.free.list,
+ * so that the refill can also post it.
+ */
+ smbdirect_connection_put_recv_io(recv_io);
+
+ /*
+ * Prepare for receiving data_transfer messages
+ */
+ sc->recv_io.reassembly.full_packet_received = true;
+ sc->recv_io.expected = SMBDIRECT_EXPECT_DATA_TRANSFER;
+ list_for_each_entry(recv_io, &sc->recv_io.free.list, list)
+ recv_io->cqe.done = smbdirect_connection_recv_io_done;
+ recv_io = NULL;
+
+ ret = smbdirect_connection_create_mr_list(sc);
+ if (ret) {
+ smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
+ "smbdirect_connection_create_mr_list() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ goto error;
+ }
+
+ /*
+ * We should at least post 1 smbdirect_recv_io!
+ */
+ posted = smbdirect_connection_recv_io_refill(sc);
+ if (posted < 1) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "smbdirect_connection_recv_io_refill() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ goto error;
+ }
+
+ /*
+ * smbdirect_connection_negotiation_done()
+ * will setup all required things and wake up
+ * the waiter.
+ */
+ smbdirect_connection_negotiation_done(sc);
+
+ return;
+
+error:
+ /*
+ * recv_io.posted.refill_work is still disabled,
+ * so smbdirect_connection_put_recv_io() won't
+ * start it.
+ */
+ if (recv_io)
+ smbdirect_connection_put_recv_io(recv_io);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+}
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static int smbdirect_connect_sync(struct smbdirect_socket *sc,
+ const struct sockaddr *dst)
+{
+ int ret;
+
+ ret = smbdirect_connect(sc, dst);
+ if (ret) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "smbdirect_connect(%pISpsfc) failed %1pe\n",
+ dst, SMBDIRECT_DEBUG_ERR_PTR(ret));
+ return ret;
+ }
+
+ ret = smbdirect_connection_wait_for_connected(sc);
+ if (ret) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "wait for smbdirect_connect(%pISpsfc) failed %1pe\n",
+ dst, SMBDIRECT_DEBUG_ERR_PTR(ret));
+ return ret;
+ }
+
+ return 0;
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 051/127] smb: smbdirect: introduce smbdirect_accept_connect_request()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (49 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 050/127] smb: smbdirect: introduce smbdirect_connect[_sync]() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 052/127] smb: smbdirect: introduce smbdirect_socket_create_{kern,accepting}() and smbdirect_socket_release() Stefan Metzmacher
` (76 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This will be used by the server to handle new connections.
All rdma processing from rdma_accept() to RDMA_CM_EVENT_ESTABLISHED
as well as the waiting for the smbdirect negotiation request
and sending the negotiation response is done async
until we reach SMBDIRECT_SOCKET_CONNECTED.
Sync behaviour will be done by the server calling
smbdirect_conection_wait_for_connected() in order
to each SMBDIRECT_SOCKET_CONNECTED or an error.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/common/smbdirect/smbdirect_accept.c | 595 ++++++++++++++++++
.../common/smbdirect/smbdirect_all_c_files.c | 1 +
2 files changed, 596 insertions(+)
create mode 100644 fs/smb/common/smbdirect/smbdirect_accept.c
diff --git a/fs/smb/common/smbdirect/smbdirect_accept.c b/fs/smb/common/smbdirect/smbdirect_accept.c
new file mode 100644
index 000000000000..c44f89f9389f
--- /dev/null
+++ b/fs/smb/common/smbdirect/smbdirect_accept.c
@@ -0,0 +1,595 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2017, Microsoft Corporation.
+ * Copyright (C) 2018, LG Electronics.
+ * Copyright (c) 2025, Stefan Metzmacher
+ */
+
+#include "smbdirect_internal.h"
+
+static int smbdirect_accept_rdma_event_handler(struct rdma_cm_id *id,
+ struct rdma_cm_event *event);
+static int smbdirect_accept_init_params(struct smbdirect_socket *sc);
+static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc *wc);
+static void smbdirect_accept_negotiate_send_done(struct ib_cq *cq, struct ib_wc *wc);
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static int smbdirect_accept_connect_request(struct smbdirect_socket *sc,
+ const struct rdma_conn_param *param)
+{
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+ struct smbdirect_recv_io *recv_io;
+ u8 peer_initiator_depth;
+ u8 peer_responder_resources;
+ struct rdma_conn_param conn_param;
+ __be32 ird_ord_hdr[2];
+ int ret;
+
+ /*
+ * First set what the we as server are able to support
+ */
+ sp->initiator_depth = min_t(u8, sp->initiator_depth,
+ sc->ib.dev->attrs.max_qp_rd_atom);
+
+ peer_initiator_depth = param->initiator_depth;
+ peer_responder_resources = param->responder_resources;
+ smbdirect_connection_negotiate_rdma_resources(sc,
+ peer_initiator_depth,
+ peer_responder_resources,
+ param);
+
+ ret = smbdirect_accept_init_params(sc);
+ if (ret) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "smbdirect_accept_init_params() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ goto init_params_failed;
+ }
+
+ ret = smbdirect_connection_create_qp(sc);
+ if (ret) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "smbdirect_connection_create_qp() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ goto create_qp_failed;
+ }
+
+ ret = smbdirect_connection_create_mem_pools(sc);
+ if (ret) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "smbdirect_connection_create_mem_pools() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ goto create_mem_failed;
+ }
+
+ recv_io = smbdirect_connection_get_recv_io(sc);
+ if (WARN_ON_ONCE(!recv_io)) {
+ ret = -EINVAL;
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "smbdirect_connection_get_recv_io() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ goto get_recv_io_failed;
+ }
+ recv_io->cqe.done = smbdirect_accept_negotiate_recv_done;
+
+ /*
+ * Now post the recv_io buffer in order to get
+ * the negotiate request
+ */
+ sc->recv_io.expected = SMBDIRECT_EXPECT_NEGOTIATE_REQ;
+ ret = smbdirect_connection_post_recv_io(recv_io);
+ if (ret) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "smbdirect_connection_post_recv_io() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ goto post_recv_io_failed;
+ }
+ /*
+ * From here recv_io is known to the RDMA QP and needs ib_drain_qp and
+ * smbdirect_accept_negotiate_recv_done to cleanup...
+ */
+ recv_io = NULL;
+
+ WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_CREATED);
+ sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED;
+
+ /*
+ * We already negotiated sp->initiator_depth
+ * and sp->responder_resources above.
+ */
+ memset(&conn_param, 0, sizeof(conn_param));
+ conn_param.initiator_depth = sp->initiator_depth;
+ conn_param.responder_resources = sp->responder_resources;
+
+ if (sc->rdma.legacy_iwarp) {
+ ird_ord_hdr[0] = cpu_to_be32(conn_param.responder_resources);
+ ird_ord_hdr[1] = cpu_to_be32(conn_param.initiator_depth);
+ conn_param.private_data = ird_ord_hdr;
+ conn_param.private_data_len = sizeof(ird_ord_hdr);
+ } else {
+ conn_param.private_data = NULL;
+ conn_param.private_data_len = 0;
+ }
+ conn_param.retry_count = SMBDIRECT_RDMA_CM_RETRY;
+ conn_param.rnr_retry_count = SMBDIRECT_RDMA_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;
+ sc->rdma.expected_event = RDMA_CM_EVENT_ESTABLISHED;
+ sc->rdma.cm_id->event_handler = smbdirect_accept_rdma_event_handler;
+ ret = rdma_accept(sc->rdma.cm_id, &conn_param);
+ if (ret) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "rdma_accept() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ goto rdma_accept_failed;
+ }
+
+ /*
+ * start with the negotiate timeout and SMBDIRECT_KEEPALIVE_PENDING
+ * so that the timer will cause a disconnect.
+ */
+ INIT_DELAYED_WORK(&sc->idle.timer_work, smbdirect_connection_idle_timer_work);
+ sc->idle.keepalive = SMBDIRECT_KEEPALIVE_PENDING;
+ mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
+ msecs_to_jiffies(sp->negotiate_timeout_msec));
+
+ return 0;
+
+rdma_accept_failed:
+ /*
+ * smbdirect_connection_destroy_qp() calls ib_drain_qp(),
+ * so that smbdirect_accept_negotiate_recv_done() will
+ * call smbdirect_connection_put_recv_io()
+ */
+post_recv_io_failed:
+ if (recv_io)
+ smbdirect_connection_put_recv_io(recv_io);
+get_recv_io_failed:
+ smbdirect_connection_destroy_mem_pools(sc);
+create_mem_failed:
+ smbdirect_connection_destroy_qp(sc);
+create_qp_failed:
+init_params_failed:
+ return ret;
+}
+
+static int smbdirect_accept_init_params(struct smbdirect_socket *sc)
+{
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+ int max_send_sges;
+ unsigned int maxpages;
+
+ /* need 3 more sge. because a SMB_DIRECT header, SMB2 header,
+ * SMB2 response could be mapped.
+ */
+ max_send_sges = DIV_ROUND_UP(sp->max_send_size, PAGE_SIZE) + 3;
+ if (max_send_sges > SMBDIRECT_SEND_IO_MAX_SGE) {
+ pr_err("max_send_size %d is too large\n", sp->max_send_size);
+ return -EINVAL;
+ }
+
+ /*
+ * Initialize the local credits to post
+ * IB_WR_SEND[_WITH_INV].
+ */
+ atomic_set(&sc->send_io.lcredits.count, sp->send_credit_target);
+
+ maxpages = DIV_ROUND_UP(sp->max_read_write_size, PAGE_SIZE);
+ sc->rw_io.credits.max = rdma_rw_mr_factor(sc->ib.dev,
+ sc->rdma.cm_id->port_num,
+ maxpages);
+ sc->rw_io.credits.num_pages = DIV_ROUND_UP(maxpages, sc->rw_io.credits.max);
+ /* add one extra in order to handle unaligned pages */
+ sc->rw_io.credits.max += 1;
+
+ sc->recv_io.credits.target = 1;
+
+ atomic_set(&sc->rw_io.credits.count, sc->rw_io.credits.max);
+
+ return 0;
+}
+
+static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+ struct smbdirect_recv_io *recv_io =
+ container_of(wc->wr_cqe, struct smbdirect_recv_io, cqe);
+ struct smbdirect_socket *sc = recv_io->socket;
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+ struct smbdirect_negotiate_req *nreq;
+ u16 min_version;
+ u16 max_version;
+ u16 credits_requested;
+ u32 preferred_send_size;
+ u32 max_receive_size;
+ u32 max_fragmented_size;
+ struct smbdirect_send_io *send_io = NULL;
+ struct smbdirect_negotiate_resp *nrep;
+ struct ib_send_wr send_wr;
+ u32 ntstatus;
+ int posted;
+ int ret;
+
+ if (unlikely(wc->status != IB_WC_SUCCESS || WARN_ON_ONCE(wc->opcode != IB_WC_RECV))) {
+ if (wc->status != IB_WC_WR_FLUSH_ERR)
+ smbdirect_log_rdma_recv(sc, SMBDIRECT_LOG_ERR,
+ "wc->status=%s (%d) wc->opcode=%d\n",
+ ib_wc_status_msg(wc->status), wc->status, wc->opcode);
+ goto error;
+ }
+
+ smbdirect_log_rdma_recv(sc, SMBDIRECT_LOG_INFO,
+ "smbdirect_recv_io completed. status='%s (%d)', opcode=%d\n",
+ ib_wc_status_msg(wc->status), wc->status, wc->opcode);
+
+ WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_NEGOTIATE_NEEDED);
+ sc->status = SMBDIRECT_SOCKET_NEGOTIATE_RUNNING;
+
+ /*
+ * Reset timer to the keepalive interval in
+ * order to trigger our next keepalive message.
+ */
+ sc->idle.keepalive = SMBDIRECT_KEEPALIVE_NONE;
+ mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
+ msecs_to_jiffies(sp->keepalive_interval_msec));
+
+ ib_dma_sync_single_for_cpu(wc->qp->device,
+ recv_io->sge.addr,
+ recv_io->sge.length,
+ DMA_FROM_DEVICE);
+
+ if (wc->byte_len < sizeof(*nreq)) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "wc->byte_len=%u < %zu\n",
+ wc->byte_len, sizeof(*nreq));
+ goto error;
+ }
+
+ nreq = (struct smbdirect_negotiate_req *)recv_io->packet;
+ min_version = le16_to_cpu(nreq->min_version);
+ max_version = le16_to_cpu(nreq->max_version);
+ credits_requested = le16_to_cpu(nreq->credits_requested);
+ preferred_send_size = le32_to_cpu(nreq->preferred_send_size);
+ max_receive_size = le32_to_cpu(nreq->max_receive_size);
+ max_fragmented_size = le32_to_cpu(nreq->max_fragmented_size);
+
+ smbdirect_log_negotiate(sc, SMBDIRECT_LOG_INFO,
+ "ReqIn: %s%x, %s%x, %s%u, %s%u, %s%u, %s%u\n",
+ "MinVersion=0x",
+ le16_to_cpu(nreq->min_version),
+ "MaxVersion=0x",
+ le16_to_cpu(nreq->max_version),
+ "CreditsRequested=",
+ le16_to_cpu(nreq->credits_requested),
+ "PreferredSendSize=",
+ le32_to_cpu(nreq->preferred_send_size),
+ "MaxRecvSize=",
+ le32_to_cpu(nreq->max_receive_size),
+ "MaxFragmentedSize=",
+ le32_to_cpu(nreq->max_fragmented_size));
+
+ if (!(min_version <= SMBDIRECT_V1 && max_version >= SMBDIRECT_V1)) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "invalid: min_version=0x%x max_version=0x%x\n",
+ min_version, max_version);
+ ntstatus = 0xC00000bb; /* NT_STATUS_NOT_SUPPORTED */
+ goto not_supported;
+ }
+
+ if (credits_requested == 0) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "invalid: credits_requested == 0\n");
+ goto error;
+ }
+
+ if (max_receive_size < SMBDIRECT_MIN_RECEIVE_SIZE) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "invalid: max_receive_size=%u < %u\n",
+ max_receive_size,
+ SMBDIRECT_MIN_RECEIVE_SIZE);
+ goto error;
+ }
+
+ if (max_fragmented_size < SMBDIRECT_MIN_FRAGMENTED_SIZE) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "invalid: max_fragmented_size=%u < %u\n",
+ max_fragmented_size,
+ SMBDIRECT_MIN_FRAGMENTED_SIZE);
+ goto error;
+ }
+
+ /*
+ * At least the value of SMBDIRECT_MIN_RECEIVE_SIZE is used.
+ */
+ sp->max_recv_size = min_t(u32, sp->max_recv_size, preferred_send_size);
+ sp->max_recv_size = max_t(u32, sp->max_recv_size, SMBDIRECT_MIN_RECEIVE_SIZE);
+
+ /*
+ * We take the value from the peer, which is checked to be higher than 0,
+ * but we limit it to the max value we support in order to have
+ * the main logic simpler.
+ */
+ sc->recv_io.credits.target = credits_requested;
+ sc->recv_io.credits.target = min_t(u16, sc->recv_io.credits.target,
+ sp->recv_credit_max);
+
+ /*
+ * Note nreq->max_receive_size was already checked against
+ * SMBDIRECT_MIN_RECEIVE_SIZE above.
+ */
+ sp->max_send_size = min_t(u32, sp->max_send_size, max_receive_size);
+
+ /*
+ * Note nreq->max_fragmented_size was already checked against
+ * SMBDIRECT_MIN_FRAGMENTED_SIZE above.
+ */
+ sp->max_fragmented_send_size = max_fragmented_size;
+
+ /*
+ * Give recv_io back to the recv_io.free.list,
+ * so that the refill can also post it.
+ */
+ smbdirect_connection_put_recv_io(recv_io);
+
+ /*
+ * Prepare for receiving data_transfer messages
+ */
+ sc->recv_io.reassembly.full_packet_received = true;
+ sc->recv_io.expected = SMBDIRECT_EXPECT_DATA_TRANSFER;
+ list_for_each_entry(recv_io, &sc->recv_io.free.list, list)
+ recv_io->cqe.done = smbdirect_connection_recv_io_done;
+ recv_io = NULL;
+
+ /*
+ * We should at least post 1 smbdirect_recv_io!
+ */
+ posted = smbdirect_connection_recv_io_refill(sc);
+ if (posted < 1) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "smbdirect_connection_recv_io_refill() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(posted));
+ goto error;
+ }
+
+ /*
+ * The response will grant credits for all posted
+ * smbdirect_recv_io messages.
+ */
+ atomic_set(&sc->send_io.credits.count, posted);
+
+ ntstatus = 0; /* NT_STATUS_OK */
+
+not_supported:
+ send_io = smbdirect_connection_alloc_send_io(sc);
+ if (IS_ERR(send_io)) {
+ ret = PTR_ERR(send_io);
+ send_io = NULL;
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "smbdirect_connection_alloc_send_io() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ goto error;
+ }
+ send_io->cqe.done = smbdirect_accept_negotiate_send_done;
+
+ nrep = (struct smbdirect_negotiate_resp *)send_io->packet;
+ nrep->min_version = cpu_to_le16(SMBDIRECT_V1);
+ nrep->max_version = cpu_to_le16(SMBDIRECT_V1);
+ if (ntstatus == 0) {
+ nrep->negotiated_version = cpu_to_le16(SMBDIRECT_V1);
+ nrep->reserved = 0;
+ nrep->credits_requested = cpu_to_le16(sp->send_credit_target);
+ nrep->credits_granted = cpu_to_le16(posted);
+ nrep->status = cpu_to_le32(ntstatus);
+ nrep->max_readwrite_size = cpu_to_le32(sp->max_read_write_size);
+ nrep->preferred_send_size = cpu_to_le32(sp->max_send_size);
+ nrep->max_receive_size = cpu_to_le32(sp->max_recv_size);
+ nrep->max_fragmented_size = cpu_to_le32(sp->max_fragmented_recv_size);
+ } else {
+ nrep->negotiated_version = 0;
+ nrep->reserved = 0;
+ nrep->credits_requested = 0;
+ nrep->credits_granted = 0;
+ nrep->status = cpu_to_le32(ntstatus);
+ nrep->max_readwrite_size = 0;
+ nrep->preferred_send_size = 0;
+ nrep->max_receive_size = 0;
+ nrep->max_fragmented_size = 0;
+ }
+
+ smbdirect_log_negotiate(sc, SMBDIRECT_LOG_INFO,
+ "RepOut: %s%x, %s%x, %s%x, %s%u, %s%u, %s%x, %s%u, %s%u, %s%u, %s%u\n",
+ "MinVersion=0x",
+ le16_to_cpu(nrep->min_version),
+ "MaxVersion=0x",
+ le16_to_cpu(nrep->max_version),
+ "NegotiatedVersion=0x",
+ le16_to_cpu(nrep->negotiated_version),
+ "CreditsRequested=",
+ le16_to_cpu(nrep->credits_requested),
+ "CreditsGranted=",
+ le16_to_cpu(nrep->credits_granted),
+ "Status=0x",
+ le32_to_cpu(nrep->status),
+ "MaxReadWriteSize=",
+ le32_to_cpu(nrep->max_readwrite_size),
+ "PreferredSendSize=",
+ le32_to_cpu(nrep->preferred_send_size),
+ "MaxRecvSize=",
+ le32_to_cpu(nrep->max_receive_size),
+ "MaxFragmentedSize=",
+ le32_to_cpu(nrep->max_fragmented_size));
+
+ send_io->sge[0].addr = ib_dma_map_single(sc->ib.dev,
+ nrep,
+ sizeof(*nrep),
+ DMA_TO_DEVICE);
+ ret = ib_dma_mapping_error(sc->ib.dev, send_io->sge[0].addr);
+ if (ret) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "ib_dma_mapping_error() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ goto error;
+ }
+
+ send_io->sge[0].length = sizeof(*nrep);
+ send_io->sge[0].lkey = sc->ib.pd->local_dma_lkey;
+ send_io->num_sge = 1;
+
+ ib_dma_sync_single_for_device(sc->ib.dev,
+ send_io->sge[0].addr,
+ send_io->sge[0].length,
+ DMA_TO_DEVICE);
+
+ send_wr.next = NULL;
+ send_wr.wr_cqe = &send_io->cqe;
+ send_wr.sg_list = send_io->sge;
+ send_wr.num_sge = send_io->num_sge;
+ send_wr.opcode = IB_WR_SEND;
+ send_wr.send_flags = IB_SEND_SIGNALED;
+
+ ret = smbdirect_connection_post_send_wr(sc, &send_wr);
+ if (ret) {
+ /* if we reach here, post send failed */
+ smbdirect_log_rdma_send(sc, SMBDIRECT_LOG_ERR,
+ "smbdirect_connection_post_send_wr() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ goto error;
+ }
+
+ /*
+ * smbdirect_accept_negotiate_send_done
+ * will do all remaining work...
+ */
+ return;
+
+error:
+ /*
+ * recv_io.posted.refill_work is still disabled,
+ * so smbdirect_connection_put_recv_io() won't
+ * start it.
+ */
+ if (recv_io)
+ smbdirect_connection_put_recv_io(recv_io);
+ /*
+ * Note smbdirect_connection_free_send_io()
+ * does ib_dma_unmap_page()
+ */
+ if (send_io)
+ smbdirect_connection_free_send_io(send_io);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+}
+
+static void smbdirect_accept_negotiate_send_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+ struct smbdirect_send_io *send_io =
+ container_of(wc->wr_cqe, struct smbdirect_send_io, cqe);
+ struct smbdirect_socket *sc = send_io->socket;
+ struct smbdirect_negotiate_resp *nrep;
+ u32 ntstatus;
+
+ smbdirect_log_rdma_send(sc, SMBDIRECT_LOG_INFO,
+ "smbdirect_send_io completed. status='%s (%d)', opcode=%d\n",
+ ib_wc_status_msg(wc->status), wc->status, wc->opcode);
+
+ nrep = (struct smbdirect_negotiate_resp *)send_io->packet;
+ ntstatus = le32_to_cpu(nrep->status);
+
+ /* Note this frees wc->wr_cqe, but not wc */
+ smbdirect_connection_free_send_io(send_io);
+ atomic_dec(&sc->send_io.pending.count);
+
+ if (unlikely(wc->status != IB_WC_SUCCESS || WARN_ON_ONCE(wc->opcode != IB_WC_SEND))) {
+ if (wc->status != IB_WC_WR_FLUSH_ERR)
+ smbdirect_log_rdma_send(sc, SMBDIRECT_LOG_ERR,
+ "wc->status=%s (%d) wc->opcode=%d\n",
+ ib_wc_status_msg(wc->status), wc->status, wc->opcode);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+ return;
+ }
+
+ /*
+ * If we send a smbdirect_negotiate_resp without NT_STATUS_OK (0)
+ * we need to disconnect now.
+ *
+ * Otherwise smbdirect_connection_negotiation_done()
+ * will setup all required things and wake up
+ * the waiter.
+ */
+ if (ntstatus)
+ smbdirect_connection_schedule_disconnect(sc, -EOPNOTSUPP);
+ else
+ smbdirect_connection_negotiation_done(sc);
+}
+
+static int smbdirect_accept_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,
+ * as we might sleep.
+ *
+ * We didn't timeout so we cancel our idle timer,
+ * it will be scheduled again if needed.
+ */
+ WARN_ON_ONCE(in_interrupt());
+
+ if (event->status || event->event != sc->rdma.expected_event) {
+ int ret = -ECONNABORTED;
+
+ if (event->event == RDMA_CM_EVENT_REJECTED)
+ ret = -ECONNREFUSED;
+ 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));
+
+ smbdirect_connection_schedule_disconnect(sc, ret);
+ 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_ESTABLISHED:
+ smbdirect_connection_rdma_established(sc);
+
+ WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING);
+ sc->status = SMBDIRECT_SOCKET_NEGOTIATE_NEEDED;
+
+ /*
+ * wait for smbdirect_accept_negotiate_recv_done()
+ * to get the negotiate request.
+ */
+ return 0;
+
+ default:
+ break;
+ }
+
+ /*
+ * This is an internal error
+ */
+ WARN_ON_ONCE(sc->rdma.expected_event != RDMA_CM_EVENT_ESTABLISHED);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+ return 0;
+}
diff --git a/fs/smb/common/smbdirect/smbdirect_all_c_files.c b/fs/smb/common/smbdirect/smbdirect_all_c_files.c
index 257cf0cf92d0..ba79053d1fce 100644
--- a/fs/smb/common/smbdirect/smbdirect_all_c_files.c
+++ b/fs/smb/common/smbdirect/smbdirect_all_c_files.c
@@ -20,3 +20,4 @@
#include "smbdirect_rw.c"
#include "smbdirect_debug.c"
#include "smbdirect_connect.c"
+#include "smbdirect_accept.c"
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 052/127] smb: smbdirect: introduce smbdirect_socket_create_{kern,accepting}() and smbdirect_socket_release()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (50 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 051/127] smb: smbdirect: introduce smbdirect_accept_connect_request() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 053/127] smb: smbdirect: let smbdirect_internal.h define pr_fmt without SMBDIRECT_USE_INLINE_C_FILES Stefan Metzmacher
` (75 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This provides functions which also allocate and free struct
smbdirect_socket.
This allows callers to use the same flow as with
sock_create_kern()/sock_release().
The end goal would be to use sock_create_kern()/sock_release(), but the
first step will be to use smbdirect specific functions without any
struct socket nor struct sock.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 96 ++++++++++++++++++-
fs/smb/common/smbdirect/smbdirect_socket.h | 33 +++++++
2 files changed, 128 insertions(+), 1 deletion(-)
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index 34be36cf5d00..de87acdaf595 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -94,7 +94,6 @@ static int smbdirect_socket_rdma_event_handler(struct rdma_cm_id *id,
return 1;
}
-__maybe_unused /* this is temporary while this file is included in orders */
static int smbdirect_socket_init_new(struct net *net, struct smbdirect_socket *sc)
{
struct rdma_cm_id *id;
@@ -119,6 +118,31 @@ static int smbdirect_socket_init_new(struct net *net, struct smbdirect_socket *s
}
__maybe_unused /* this is temporary while this file is included in orders */
+static int smbdirect_socket_create_kern(struct net *net, struct smbdirect_socket **_sc)
+{
+ struct smbdirect_socket *sc;
+ int ret;
+
+ ret = -ENOMEM;
+ sc = kzalloc(sizeof(*sc), GFP_KERNEL);
+ if (!sc)
+ goto alloc_failed;
+
+ ret = smbdirect_socket_init_new(net, sc);
+ if (ret)
+ goto init_failed;
+
+ kref_init(&sc->refs.destroy);
+
+ *_sc = sc;
+ return 0;
+
+init_failed:
+ kfree(sc);
+alloc_failed:
+ return ret;
+}
+
static int smbdirect_socket_init_accepting(struct rdma_cm_id *id, struct smbdirect_socket *sc)
{
smbdirect_socket_init(sc);
@@ -134,6 +158,32 @@ static int smbdirect_socket_init_accepting(struct rdma_cm_id *id, struct smbdire
return 0;
}
+__maybe_unused /* this is temporary while this file is included in orders */
+static int smbdirect_socket_create_accepting(struct rdma_cm_id *id, struct smbdirect_socket **_sc)
+{
+ struct smbdirect_socket *sc;
+ int ret;
+
+ ret = -ENOMEM;
+ sc = kzalloc(sizeof(*sc), GFP_KERNEL);
+ if (!sc)
+ goto alloc_failed;
+
+ ret = smbdirect_socket_init_accepting(id, sc);
+ if (ret)
+ goto init_failed;
+
+ kref_init(&sc->refs.destroy);
+
+ *_sc = sc;
+ return 0;
+
+init_failed:
+ kfree(sc);
+alloc_failed:
+ return ret;
+}
+
__maybe_unused /* this is temporary while this file is included in orders */
static int smbdirect_socket_set_initial_parameters(struct smbdirect_socket *sc,
const struct smbdirect_socket_parameters *sp)
@@ -1251,6 +1301,50 @@ static void smbdirect_socket_shutdown(struct smbdirect_socket *sc)
smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
}
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_socket_release_disconnect(struct kref *kref)
+{
+ struct smbdirect_socket *sc =
+ container_of(kref, struct smbdirect_socket, refs.disconnect);
+
+ /*
+ * For now do a sync disconnect/destroy
+ */
+ smbdirect_connection_destroy_sync(sc);
+}
+
+static void smbdirect_socket_release_destroy(struct kref *kref)
+{
+ struct smbdirect_socket *sc =
+ container_of(kref, struct smbdirect_socket, refs.destroy);
+
+ /*
+ * Do a sync disconnect/destroy...
+ * hopefully a no-op, as it should be already
+ * in DESTROYED state, before we free the memory.
+ */
+ smbdirect_connection_destroy_sync(sc);
+ kfree(sc);
+}
+
+__maybe_unused /* this is temporary while this file is included in orders */
+static void smbdirect_socket_release(struct smbdirect_socket *sc)
+{
+ /*
+ * We expect only 1 disconnect reference
+ * and if it is already 0, it's a use after free!
+ */
+ WARN_ON_ONCE(kref_read(&sc->refs.disconnect) != 1);
+ WARN_ON(!kref_put(&sc->refs.disconnect, smbdirect_socket_release_disconnect));
+
+ /*
+ * This may not trigger smbdirect_socket_release_destroy(),
+ * if struct smbdirect_socket is embedded in another structure
+ * indicated by REFCOUNT_MAX.
+ */
+ kref_put(&sc->refs.destroy, smbdirect_socket_release_destroy);
+}
+
static void smbdirect_connection_idle_timer_work(struct work_struct *work)
{
struct smbdirect_socket *sc =
diff --git a/fs/smb/common/smbdirect/smbdirect_socket.h b/fs/smb/common/smbdirect/smbdirect_socket.h
index c930d7531965..e44ab31ee852 100644
--- a/fs/smb/common/smbdirect/smbdirect_socket.h
+++ b/fs/smb/common/smbdirect/smbdirect_socket.h
@@ -108,6 +108,36 @@ struct smbdirect_socket {
struct work_struct disconnect_work;
+ /*
+ * The reference counts.
+ */
+ struct {
+ /*
+ * This holds the references by the
+ * frontend, typically the smb layer.
+ *
+ * It is typically 1 and a disconnect
+ * will happen if it reaches 0.
+ */
+ struct kref disconnect;
+
+ /*
+ * This holds the reference by the
+ * backend, the code that manages
+ * the lifetime of the whole
+ * struct smbdirect_socket,
+ * if this reaches 0 it can will
+ * be freed.
+ *
+ * Can be REFCOUNT_MAX is part
+ * of another structure.
+ *
+ * This is equal or higher than
+ * the disconnect refcount.
+ */
+ struct kref destroy;
+ } refs;
+
/* RDMA related */
struct {
struct rdma_cm_id *cm_id;
@@ -491,6 +521,9 @@ 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);
+ kref_init(&sc->refs.disconnect);
+ sc->refs.destroy = (struct kref) KREF_INIT(REFCOUNT_MAX);
+
sc->rdma.expected_event = RDMA_CM_EVENT_INTERNAL;
sc->ib.poll_ctx = IB_POLL_UNBOUND_WORKQUEUE;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 053/127] smb: smbdirect: let smbdirect_internal.h define pr_fmt without SMBDIRECT_USE_INLINE_C_FILES
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (51 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 052/127] smb: smbdirect: introduce smbdirect_socket_create_{kern,accepting}() and smbdirect_socket_release() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 054/127] smb: smbdirect: introduce smbdirect_public.h with prototypes Stefan Metzmacher
` (74 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
When we move to smbdirect.ko we want log message prefixed with the
module name.
Note callers are still using smbdirect_socket_set_logging() in order
to redirect the per connection logging to their own log functions.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/common/smbdirect/smbdirect_internal.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/fs/smb/common/smbdirect/smbdirect_internal.h b/fs/smb/common/smbdirect/smbdirect_internal.h
index 0727b9fee879..f8fabddc3808 100644
--- a/fs/smb/common/smbdirect/smbdirect_internal.h
+++ b/fs/smb/common/smbdirect/smbdirect_internal.h
@@ -6,6 +6,10 @@
#ifndef __FS_SMB_COMMON_SMBDIRECT_INTERNAL_H__
#define __FS_SMB_COMMON_SMBDIRECT_INTERNAL_H__
+#ifndef SMBDIRECT_USE_INLINE_C_FILES
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#endif /* ! SMBDIRECT_USE_INLINE_C_FILES */
+
#include <linux/errname.h>
#include "smbdirect.h"
#include "smbdirect_pdu.h"
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 054/127] smb: smbdirect: introduce smbdirect_public.h with prototypes
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (52 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 053/127] smb: smbdirect: let smbdirect_internal.h define pr_fmt without SMBDIRECT_USE_INLINE_C_FILES Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 055/127] smb: smbdirect: introduce smbdirect_private.h " Stefan Metzmacher
` (73 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
smbdirect_public.h contains functions which will be still be
eported when we move to an smbdirect.ko.
For now this uses the SMBDIRECT_USE_INLINE_C_FILES code path
and marks all function as '__maybe_unused static',
but this will make further changes easier.
Note this generates the following things from checkpatch.pl,
so I passed --ignore=FILE_PATH_CHANGES,EXPORT_SYMBOL,COMPLEX_MACRO
ERROR: Macros with complex values should be enclosed in parentheses
#514: FILE: fs/smb/common/smbdirect/smbdirect_public.h:18:
+#define __SMBDIRECT_PUBLIC__ __maybe_unused static
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
#515: FILE: fs/smb/common/smbdirect/smbdirect_public.h:19:
+#define __SMBDIRECT_EXPORT_SYMBOL__(__sym)
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
#518: FILE: fs/smb/common/smbdirect/smbdirect_public.h:22:
+#define __SMBDIRECT_EXPORT_SYMBOL__(__sym) EXPORT_SYMBOL_FOR_MODULES(__sym, "cifs,ksmbd")
This is exactly what we want here, so we should ignore the
checkpatch.pl problems.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/common/smbdirect/smbdirect_accept.c | 7 +-
fs/smb/common/smbdirect/smbdirect_connect.c | 13 +-
.../common/smbdirect/smbdirect_connection.c | 133 ++++++++-------
fs/smb/common/smbdirect/smbdirect_debug.c | 9 +-
fs/smb/common/smbdirect/smbdirect_internal.h | 1 +
fs/smb/common/smbdirect/smbdirect_mr.c | 17 +-
fs/smb/common/smbdirect/smbdirect_public.h | 154 ++++++++++++++++++
fs/smb/common/smbdirect/smbdirect_rw.c | 13 +-
fs/smb/common/smbdirect/smbdirect_socket.h | 14 --
9 files changed, 263 insertions(+), 98 deletions(-)
create mode 100644 fs/smb/common/smbdirect/smbdirect_public.h
diff --git a/fs/smb/common/smbdirect/smbdirect_accept.c b/fs/smb/common/smbdirect/smbdirect_accept.c
index c44f89f9389f..0ed3f43a7397 100644
--- a/fs/smb/common/smbdirect/smbdirect_accept.c
+++ b/fs/smb/common/smbdirect/smbdirect_accept.c
@@ -13,9 +13,9 @@ static int smbdirect_accept_init_params(struct smbdirect_socket *sc);
static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc *wc);
static void smbdirect_accept_negotiate_send_done(struct ib_cq *cq, struct ib_wc *wc);
-__maybe_unused /* this is temporary while this file is included in orders */
-static int smbdirect_accept_connect_request(struct smbdirect_socket *sc,
- const struct rdma_conn_param *param)
+__SMBDIRECT_PUBLIC__
+int smbdirect_accept_connect_request(struct smbdirect_socket *sc,
+ const struct rdma_conn_param *param)
{
struct smbdirect_socket_parameters *sp = &sc->parameters;
struct smbdirect_recv_io *recv_io;
@@ -154,6 +154,7 @@ static int smbdirect_accept_connect_request(struct smbdirect_socket *sc,
init_params_failed:
return ret;
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_accept_connect_request);
static int smbdirect_accept_init_params(struct smbdirect_socket *sc)
{
diff --git a/fs/smb/common/smbdirect/smbdirect_connect.c b/fs/smb/common/smbdirect/smbdirect_connect.c
index 458566c99d2e..eb8e903c9fce 100644
--- a/fs/smb/common/smbdirect/smbdirect_connect.c
+++ b/fs/smb/common/smbdirect/smbdirect_connect.c
@@ -15,9 +15,8 @@ static int smbdirect_connect_negotiate_start(struct smbdirect_socket *sc);
static void smbdirect_connect_negotiate_send_done(struct ib_cq *cq, struct ib_wc *wc);
static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc *wc);
-__maybe_unused /* this is temporary while this file is included in orders */
-static int smbdirect_connect(struct smbdirect_socket *sc,
- const struct sockaddr *dst)
+__SMBDIRECT_PUBLIC__
+int smbdirect_connect(struct smbdirect_socket *sc, const struct sockaddr *dst)
{
const struct sockaddr *src = NULL;
union {
@@ -61,6 +60,7 @@ static int smbdirect_connect(struct smbdirect_socket *sc,
*/
return 0;
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_connect);
static int smbdirect_connect_setup_connection(struct smbdirect_socket *sc)
{
@@ -770,9 +770,9 @@ static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
}
-__maybe_unused /* this is temporary while this file is included in orders */
-static int smbdirect_connect_sync(struct smbdirect_socket *sc,
- const struct sockaddr *dst)
+__SMBDIRECT_PUBLIC__
+int smbdirect_connect_sync(struct smbdirect_socket *sc,
+ const struct sockaddr *dst)
{
int ret;
@@ -794,3 +794,4 @@ static int smbdirect_connect_sync(struct smbdirect_socket *sc,
return 0;
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_connect_sync);
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index de87acdaf595..b102e8014fe7 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -28,8 +28,8 @@ static void smbdirect_connection_send_immediate_work(struct work_struct *work);
static void smbdirect_connection_destroy_mr_list(struct smbdirect_socket *sc);
-__maybe_unused /* this is temporary while this file is included in orders */
-static bool smbdirect_frwr_is_supported(const struct ib_device_attr *attrs)
+__SMBDIRECT_PUBLIC__
+bool smbdirect_frwr_is_supported(const struct ib_device_attr *attrs)
{
/*
* Test if FRWR (Fast Registration Work Requests) is supported on the
@@ -43,6 +43,7 @@ static bool smbdirect_frwr_is_supported(const struct ib_device_attr *attrs)
return false;
return true;
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_frwr_is_supported);
__maybe_unused /* this is temporary while this file is included in orders */
static void smbdirect_socket_prepare_create(struct smbdirect_socket *sc,
@@ -117,8 +118,8 @@ static int smbdirect_socket_init_new(struct net *net, struct smbdirect_socket *s
return 0;
}
-__maybe_unused /* this is temporary while this file is included in orders */
-static int smbdirect_socket_create_kern(struct net *net, struct smbdirect_socket **_sc)
+__SMBDIRECT_PUBLIC__
+int smbdirect_socket_create_kern(struct net *net, struct smbdirect_socket **_sc)
{
struct smbdirect_socket *sc;
int ret;
@@ -142,6 +143,7 @@ static int smbdirect_socket_create_kern(struct net *net, struct smbdirect_socket
alloc_failed:
return ret;
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_socket_create_kern);
static int smbdirect_socket_init_accepting(struct rdma_cm_id *id, struct smbdirect_socket *sc)
{
@@ -158,8 +160,8 @@ static int smbdirect_socket_init_accepting(struct rdma_cm_id *id, struct smbdire
return 0;
}
-__maybe_unused /* this is temporary while this file is included in orders */
-static int smbdirect_socket_create_accepting(struct rdma_cm_id *id, struct smbdirect_socket **_sc)
+__SMBDIRECT_PUBLIC__
+int smbdirect_socket_create_accepting(struct rdma_cm_id *id, struct smbdirect_socket **_sc)
{
struct smbdirect_socket *sc;
int ret;
@@ -183,10 +185,11 @@ static int smbdirect_socket_create_accepting(struct rdma_cm_id *id, struct smbdi
alloc_failed:
return ret;
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_socket_create_accepting);
-__maybe_unused /* this is temporary while this file is included in orders */
-static int smbdirect_socket_set_initial_parameters(struct smbdirect_socket *sc,
- const struct smbdirect_socket_parameters *sp)
+__SMBDIRECT_PUBLIC__
+int smbdirect_socket_set_initial_parameters(struct smbdirect_socket *sc,
+ const struct smbdirect_socket_parameters *sp)
{
/*
* This is only allowed before connect or accept
@@ -208,18 +211,20 @@ static int smbdirect_socket_set_initial_parameters(struct smbdirect_socket *sc,
return 0;
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_socket_set_initial_parameters);
-__maybe_unused /* this is temporary while this file is included in orders */
-static const struct smbdirect_socket_parameters *
+__SMBDIRECT_PUBLIC__
+const struct smbdirect_socket_parameters *
smbdirect_socket_get_current_parameters(struct smbdirect_socket *sc)
{
return &sc->parameters;
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_socket_get_current_parameters);
-__maybe_unused /* this is temporary while this file is included in orders */
-static int smbdirect_socket_set_kernel_settings(struct smbdirect_socket *sc,
- enum ib_poll_context poll_ctx,
- gfp_t gfp_mask)
+__SMBDIRECT_PUBLIC__
+int smbdirect_socket_set_kernel_settings(struct smbdirect_socket *sc,
+ enum ib_poll_context poll_ctx,
+ gfp_t gfp_mask)
{
/*
* This is only allowed before connect or accept
@@ -239,10 +244,11 @@ static int smbdirect_socket_set_kernel_settings(struct smbdirect_socket *sc,
return 0;
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_socket_set_kernel_settings);
-__maybe_unused /* this is temporary while this file is included in orders */
-static int smbdirect_socket_set_custom_workqueue(struct smbdirect_socket *sc,
- struct workqueue_struct *workqueue)
+__SMBDIRECT_PUBLIC__
+int smbdirect_socket_set_custom_workqueue(struct smbdirect_socket *sc,
+ struct workqueue_struct *workqueue)
{
/*
* This is only allowed before connect or accept
@@ -261,26 +267,28 @@ static int smbdirect_socket_set_custom_workqueue(struct smbdirect_socket *sc,
return 0;
}
-
-__maybe_unused /* this is temporary while this file is included in orders */
-static void smbdirect_socket_set_logging(struct smbdirect_socket *sc,
- void *private_ptr,
- bool (*needed)(struct smbdirect_socket *sc,
- void *private_ptr,
- unsigned int lvl,
- unsigned int cls),
- void (*vaprintf)(struct smbdirect_socket *sc,
- const char *func,
- unsigned int line,
- void *private_ptr,
- unsigned int lvl,
- unsigned int cls,
- struct va_format *vaf))
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_socket_set_custom_workqueue);
+
+__SMBDIRECT_PUBLIC__
+void smbdirect_socket_set_logging(struct smbdirect_socket *sc,
+ void *private_ptr,
+ bool (*needed)(struct smbdirect_socket *sc,
+ void *private_ptr,
+ unsigned int lvl,
+ unsigned int cls),
+ void (*vaprintf)(struct smbdirect_socket *sc,
+ const char *func,
+ unsigned int line,
+ void *private_ptr,
+ unsigned int lvl,
+ unsigned int cls,
+ struct va_format *vaf))
{
sc->logging.private_ptr = private_ptr;
sc->logging.needed = needed;
sc->logging.vaprintf = vaprintf;
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_socket_set_logging);
__maybe_unused /* this is temporary while this file is included in orders */
static void smbdirect_connection_wake_up_all(struct smbdirect_socket *sc)
@@ -1095,16 +1103,17 @@ static void smbdirect_connection_disconnect_work(struct work_struct *work)
smbdirect_connection_wake_up_all(sc);
}
-__maybe_unused /* this is temporary while this file is included in orders */
-static bool smbdirect_connection_is_connected(struct smbdirect_socket *sc)
+__SMBDIRECT_PUBLIC__
+bool smbdirect_connection_is_connected(struct smbdirect_socket *sc)
{
if (unlikely(!sc || sc->first_error || sc->status != SMBDIRECT_SOCKET_CONNECTED))
return false;
return true;
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_connection_is_connected);
-__maybe_unused /* this is temporary while this file is included in orders */
-static int smbdirect_connection_wait_for_connected(struct smbdirect_socket *sc)
+__SMBDIRECT_PUBLIC__
+int smbdirect_connection_wait_for_connected(struct smbdirect_socket *sc)
{
struct smbdirect_socket_parameters *sp = &sc->parameters;
union {
@@ -1170,6 +1179,7 @@ static int smbdirect_connection_wait_for_connected(struct smbdirect_socket *sc)
return 0;
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_connection_wait_for_connected);
static void smbdirect_connection_destroy(struct smbdirect_socket *sc)
{
@@ -1295,11 +1305,12 @@ static void smbdirect_connection_destroy_sync(struct smbdirect_socket *sc)
SMBDIRECT_DEBUG_ERR_PTR(sc->first_error));
}
-__maybe_unused /* this is temporary while this file is included in orders */
-static void smbdirect_socket_shutdown(struct smbdirect_socket *sc)
+__SMBDIRECT_PUBLIC__
+void smbdirect_socket_shutdown(struct smbdirect_socket *sc)
{
smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_socket_shutdown);
__maybe_unused /* this is temporary while this file is included in orders */
static void smbdirect_socket_release_disconnect(struct kref *kref)
@@ -1327,8 +1338,8 @@ static void smbdirect_socket_release_destroy(struct kref *kref)
kfree(sc);
}
-__maybe_unused /* this is temporary while this file is included in orders */
-static void smbdirect_socket_release(struct smbdirect_socket *sc)
+__SMBDIRECT_PUBLIC__
+void smbdirect_socket_release(struct smbdirect_socket *sc)
{
/*
* We expect only 1 disconnect reference
@@ -1344,6 +1355,7 @@ static void smbdirect_socket_release(struct smbdirect_socket *sc)
*/
kref_put(&sc->refs.destroy, smbdirect_socket_release_destroy);
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_socket_release);
static void smbdirect_connection_idle_timer_work(struct work_struct *work)
{
@@ -1600,11 +1612,12 @@ static int smbdirect_connection_post_send_io(struct smbdirect_socket *sc,
return smbdirect_connection_post_send_wr(sc, &msg->wr);
}
-static int smbdirect_connection_send_single_iter(struct smbdirect_socket *sc,
- struct smbdirect_send_batch *batch,
- struct iov_iter *iter,
- unsigned int flags,
- u32 remaining_data_length)
+__SMBDIRECT_PUBLIC__
+int smbdirect_connection_send_single_iter(struct smbdirect_socket *sc,
+ struct smbdirect_send_batch *batch,
+ struct iov_iter *iter,
+ unsigned int flags,
+ u32 remaining_data_length)
{
const struct smbdirect_socket_parameters *sp = &sc->parameters;
struct smbdirect_send_io *msg;
@@ -1735,9 +1748,10 @@ static int smbdirect_connection_send_single_iter(struct smbdirect_socket *sc,
lcredit_failed:
return ret;
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_connection_send_single_iter);
-__maybe_unused /* this is temporary while this file is included in orders */
-static int smbdirect_connection_send_wait_zero_pending(struct smbdirect_socket *sc)
+__SMBDIRECT_PUBLIC__
+int smbdirect_connection_send_wait_zero_pending(struct smbdirect_socket *sc)
{
/*
* As an optimization, we don't wait for individual I/O to finish
@@ -1760,13 +1774,14 @@ static int smbdirect_connection_send_wait_zero_pending(struct smbdirect_socket *
return 0;
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_connection_send_wait_zero_pending);
-__maybe_unused /* this is temporary while this file is included in orders */
-static int smbdirect_connection_send_iter(struct smbdirect_socket *sc,
- struct iov_iter *iter,
- unsigned int flags,
- bool need_invalidate,
- unsigned int remote_key)
+__SMBDIRECT_PUBLIC__
+int smbdirect_connection_send_iter(struct smbdirect_socket *sc,
+ struct iov_iter *iter,
+ unsigned int flags,
+ bool need_invalidate,
+ unsigned int remote_key)
{
struct smbdirect_socket_parameters *sp = &sc->parameters;
struct smbdirect_send_batch batch;
@@ -1845,6 +1860,7 @@ static int smbdirect_connection_send_iter(struct smbdirect_socket *sc,
return total_count;
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_connection_send_iter);
static void smbdirect_connection_send_io_done(struct ib_cq *cq, struct ib_wc *wc)
{
@@ -2223,10 +2239,10 @@ static void smbdirect_connection_recv_io_refill_work(struct work_struct *work)
}
}
-__maybe_unused /* this is temporary while this file is included in orders */
-static int smbdirect_connection_recvmsg(struct smbdirect_socket *sc,
- struct msghdr *msg,
- unsigned int flags)
+__SMBDIRECT_PUBLIC__
+int smbdirect_connection_recvmsg(struct smbdirect_socket *sc,
+ struct msghdr *msg,
+ unsigned int flags)
{
struct smbdirect_recv_io *response;
struct smbdirect_data_transfer *data_transfer;
@@ -2373,6 +2389,7 @@ static int smbdirect_connection_recvmsg(struct smbdirect_socket *sc,
goto again;
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_connection_recvmsg);
static bool smbdirect_map_sges_single_page(struct smbdirect_map_sges *state,
struct page *page, size_t off, size_t len)
diff --git a/fs/smb/common/smbdirect/smbdirect_debug.c b/fs/smb/common/smbdirect/smbdirect_debug.c
index e7258e0d28a6..eac924164fd4 100644
--- a/fs/smb/common/smbdirect/smbdirect_debug.c
+++ b/fs/smb/common/smbdirect/smbdirect_debug.c
@@ -7,10 +7,10 @@
#include "smbdirect_internal.h"
#include <linux/seq_file.h>
-__maybe_unused /* this is temporary while this file is included in orders */
-static void smbdirect_connection_legacy_debug_proc_show(struct smbdirect_socket *sc,
- unsigned int rdma_readwrite_threshold,
- struct seq_file *m)
+__SMBDIRECT_PUBLIC__
+void smbdirect_connection_legacy_debug_proc_show(struct smbdirect_socket *sc,
+ unsigned int rdma_readwrite_threshold,
+ struct seq_file *m)
{
const struct smbdirect_socket_parameters *sp;
@@ -86,3 +86,4 @@ static void smbdirect_connection_legacy_debug_proc_show(struct smbdirect_socket
atomic_read(&sc->mr_io.ready.count),
atomic_read(&sc->mr_io.used.count));
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_connection_legacy_debug_proc_show);
diff --git a/fs/smb/common/smbdirect/smbdirect_internal.h b/fs/smb/common/smbdirect/smbdirect_internal.h
index f8fabddc3808..348de3ec92b4 100644
--- a/fs/smb/common/smbdirect/smbdirect_internal.h
+++ b/fs/smb/common/smbdirect/smbdirect_internal.h
@@ -13,6 +13,7 @@
#include <linux/errname.h>
#include "smbdirect.h"
#include "smbdirect_pdu.h"
+#include "smbdirect_public.h"
#include "smbdirect_socket.h"
#endif /* __FS_SMB_COMMON_SMBDIRECT_INTERNAL_H__ */
diff --git a/fs/smb/common/smbdirect/smbdirect_mr.c b/fs/smb/common/smbdirect/smbdirect_mr.c
index bca58eee783b..b4b43df50096 100644
--- a/fs/smb/common/smbdirect/smbdirect_mr.c
+++ b/fs/smb/common/smbdirect/smbdirect_mr.c
@@ -331,8 +331,8 @@ static int smbdirect_iter_to_sgt(struct iov_iter *iter,
* need_invalidate: true if this MR needs to be locally invalidated after I/O
* return value: the MR registered, NULL if failed.
*/
-__maybe_unused /* this is temporary while this file is included in orders */
-static struct smbdirect_mr_io *
+__SMBDIRECT_PUBLIC__
+struct smbdirect_mr_io *
smbdirect_connection_register_mr_io(struct smbdirect_socket *sc,
struct iov_iter *iter,
bool writing,
@@ -453,10 +453,11 @@ smbdirect_connection_register_mr_io(struct smbdirect_socket *sc,
mutex_unlock(&mr->mutex);
return NULL;
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_connection_register_mr_io);
-__maybe_unused /* this is temporary while this file is included in orders */
-static void smbdirect_mr_io_fill_buffer_descriptor(struct smbdirect_mr_io *mr,
- struct smbdirect_buffer_descriptor_v1 *v1)
+__SMBDIRECT_PUBLIC__
+void smbdirect_mr_io_fill_buffer_descriptor(struct smbdirect_mr_io *mr,
+ struct smbdirect_buffer_descriptor_v1 *v1)
{
mutex_lock(&mr->mutex);
if (mr->state == SMBDIRECT_MR_REGISTERED) {
@@ -470,6 +471,7 @@ static void smbdirect_mr_io_fill_buffer_descriptor(struct smbdirect_mr_io *mr,
}
mutex_unlock(&mr->mutex);
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_mr_io_fill_buffer_descriptor);
/*
* Deregister a MR after I/O is done
@@ -477,8 +479,8 @@ static void smbdirect_mr_io_fill_buffer_descriptor(struct smbdirect_mr_io *mr,
* and we have to locally invalidate the buffer to prevent data is being
* modified by remote peer after upper layer consumes it
*/
-__maybe_unused /* this is temporary while this file is included in orders */
-static void smbdirect_connection_deregister_mr_io(struct smbdirect_mr_io *mr)
+__SMBDIRECT_PUBLIC__
+void smbdirect_connection_deregister_mr_io(struct smbdirect_mr_io *mr)
{
struct smbdirect_socket *sc = mr->socket;
int ret = 0;
@@ -560,3 +562,4 @@ static void smbdirect_connection_deregister_mr_io(struct smbdirect_mr_io *mr)
if (!kref_put(&mr->kref, smbdirect_mr_io_free_locked))
mutex_unlock(&mr->mutex);
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_connection_deregister_mr_io);
diff --git a/fs/smb/common/smbdirect/smbdirect_public.h b/fs/smb/common/smbdirect/smbdirect_public.h
new file mode 100644
index 000000000000..a5b15fce840c
--- /dev/null
+++ b/fs/smb/common/smbdirect/smbdirect_public.h
@@ -0,0 +1,154 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2025, Stefan Metzmacher
+ */
+
+#ifndef __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_PUBLIC_H__
+#define __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_PUBLIC_H__
+
+struct smbdirect_buffer_descriptor_v1;
+struct smbdirect_socket_parameters;
+
+struct smbdirect_socket;
+struct smbdirect_send_batch;
+struct smbdirect_mr_io;
+
+#ifdef SMBDIRECT_USE_INLINE_C_FILES
+/* this is temporary while this file is included in others */
+#define __SMBDIRECT_PUBLIC__ __maybe_unused static
+#define __SMBDIRECT_EXPORT_SYMBOL__(__sym)
+#else
+#define __SMBDIRECT_PUBLIC__
+#define __SMBDIRECT_EXPORT_SYMBOL__(__sym) EXPORT_SYMBOL_FOR_MODULES(__sym, "cifs,ksmbd")
+#endif
+
+#include <rdma/rw.h>
+
+__SMBDIRECT_PUBLIC__
+bool smbdirect_frwr_is_supported(const struct ib_device_attr *attrs);
+
+__SMBDIRECT_PUBLIC__
+int smbdirect_socket_create_kern(struct net *net, struct smbdirect_socket **_sc);
+
+__SMBDIRECT_PUBLIC__
+int smbdirect_socket_create_accepting(struct rdma_cm_id *id, struct smbdirect_socket **_sc);
+
+__SMBDIRECT_PUBLIC__
+int smbdirect_socket_set_initial_parameters(struct smbdirect_socket *sc,
+ const struct smbdirect_socket_parameters *sp);
+
+__SMBDIRECT_PUBLIC__
+const struct smbdirect_socket_parameters *
+smbdirect_socket_get_current_parameters(struct smbdirect_socket *sc);
+
+__SMBDIRECT_PUBLIC__
+int smbdirect_socket_set_kernel_settings(struct smbdirect_socket *sc,
+ enum ib_poll_context poll_ctx,
+ gfp_t gfp_mask);
+
+__SMBDIRECT_PUBLIC__
+int smbdirect_socket_set_custom_workqueue(struct smbdirect_socket *sc,
+ struct workqueue_struct *workqueue);
+
+#define SMBDIRECT_LOG_ERR 0x0
+#define SMBDIRECT_LOG_INFO 0x1
+
+#define SMBDIRECT_LOG_OUTGOING 0x1
+#define SMBDIRECT_LOG_INCOMING 0x2
+#define SMBDIRECT_LOG_READ 0x4
+#define SMBDIRECT_LOG_WRITE 0x8
+#define SMBDIRECT_LOG_RDMA_SEND 0x10
+#define SMBDIRECT_LOG_RDMA_RECV 0x20
+#define SMBDIRECT_LOG_KEEP_ALIVE 0x40
+#define SMBDIRECT_LOG_RDMA_EVENT 0x80
+#define SMBDIRECT_LOG_RDMA_MR 0x100
+#define SMBDIRECT_LOG_RDMA_RW 0x200
+#define SMBDIRECT_LOG_NEGOTIATE 0x400
+__SMBDIRECT_PUBLIC__
+void smbdirect_socket_set_logging(struct smbdirect_socket *sc,
+ void *private_ptr,
+ bool (*needed)(struct smbdirect_socket *sc,
+ void *private_ptr,
+ unsigned int lvl,
+ unsigned int cls),
+ void (*vaprintf)(struct smbdirect_socket *sc,
+ const char *func,
+ unsigned int line,
+ void *private_ptr,
+ unsigned int lvl,
+ unsigned int cls,
+ struct va_format *vaf));
+
+__SMBDIRECT_PUBLIC__
+bool smbdirect_connection_is_connected(struct smbdirect_socket *sc);
+
+__SMBDIRECT_PUBLIC__
+int smbdirect_connection_wait_for_connected(struct smbdirect_socket *sc);
+
+__SMBDIRECT_PUBLIC__
+void smbdirect_socket_shutdown(struct smbdirect_socket *sc);
+
+__SMBDIRECT_PUBLIC__
+void smbdirect_socket_release(struct smbdirect_socket *sc);
+
+__SMBDIRECT_PUBLIC__
+int smbdirect_connection_send_single_iter(struct smbdirect_socket *sc,
+ struct smbdirect_send_batch *batch,
+ struct iov_iter *iter,
+ unsigned int flags,
+ u32 remaining_data_length);
+
+__SMBDIRECT_PUBLIC__
+int smbdirect_connection_send_wait_zero_pending(struct smbdirect_socket *sc);
+
+__SMBDIRECT_PUBLIC__
+int smbdirect_connection_send_iter(struct smbdirect_socket *sc,
+ struct iov_iter *iter,
+ unsigned int flags,
+ bool need_invalidate,
+ unsigned int remote_key);
+
+__SMBDIRECT_PUBLIC__
+int smbdirect_connection_recvmsg(struct smbdirect_socket *sc,
+ struct msghdr *msg,
+ unsigned int flags);
+
+__SMBDIRECT_PUBLIC__
+int smbdirect_connect(struct smbdirect_socket *sc,
+ const struct sockaddr *dst);
+
+__SMBDIRECT_PUBLIC__
+int smbdirect_connect_sync(struct smbdirect_socket *sc,
+ const struct sockaddr *dst);
+
+__SMBDIRECT_PUBLIC__
+int smbdirect_accept_connect_request(struct smbdirect_socket *sc,
+ const struct rdma_conn_param *param);
+
+__SMBDIRECT_PUBLIC__
+int smbdirect_connection_rdma_xmit(struct smbdirect_socket *sc,
+ void *buf, size_t buf_len,
+ struct smbdirect_buffer_descriptor_v1 *desc,
+ size_t desc_len,
+ bool is_read);
+
+__SMBDIRECT_PUBLIC__
+struct smbdirect_mr_io *
+smbdirect_connection_register_mr_io(struct smbdirect_socket *sc,
+ struct iov_iter *iter,
+ bool writing,
+ bool need_invalidate);
+
+__SMBDIRECT_PUBLIC__
+void smbdirect_mr_io_fill_buffer_descriptor(struct smbdirect_mr_io *mr,
+ struct smbdirect_buffer_descriptor_v1 *v1);
+
+__SMBDIRECT_PUBLIC__
+void smbdirect_connection_deregister_mr_io(struct smbdirect_mr_io *mr);
+
+__SMBDIRECT_PUBLIC__
+void smbdirect_connection_legacy_debug_proc_show(struct smbdirect_socket *sc,
+ unsigned int rdma_readwrite_threshold,
+ struct seq_file *m);
+
+#endif /* __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_PUBLIC_H__ */
diff --git a/fs/smb/common/smbdirect/smbdirect_rw.c b/fs/smb/common/smbdirect/smbdirect_rw.c
index 2f6a1e34e665..245d0d04bfc1 100644
--- a/fs/smb/common/smbdirect/smbdirect_rw.c
+++ b/fs/smb/common/smbdirect/smbdirect_rw.c
@@ -103,12 +103,12 @@ static void smbdirect_connection_rdma_write_done(struct ib_cq *cq, struct ib_wc
smbdirect_connection_rdma_rw_done(cq, wc, DMA_TO_DEVICE);
}
-__maybe_unused /* this is temporary while this file is included in orders */
-static int smbdirect_connection_rdma_xmit(struct smbdirect_socket *sc,
- void *buf, size_t buf_len,
- struct smbdirect_buffer_descriptor_v1 *desc,
- size_t desc_len,
- bool is_read)
+__SMBDIRECT_PUBLIC__
+int smbdirect_connection_rdma_xmit(struct smbdirect_socket *sc,
+ void *buf, size_t buf_len,
+ struct smbdirect_buffer_descriptor_v1 *desc,
+ size_t desc_len,
+ bool is_read)
{
struct smbdirect_socket_parameters *sp = &sc->parameters;
enum dma_data_direction direction = is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
@@ -251,3 +251,4 @@ static int smbdirect_connection_rdma_xmit(struct smbdirect_socket *sc,
kfree(msg);
goto out;
}
+__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_connection_rdma_xmit);
diff --git a/fs/smb/common/smbdirect/smbdirect_socket.h b/fs/smb/common/smbdirect/smbdirect_socket.h
index e44ab31ee852..65f25fc4b4a7 100644
--- a/fs/smb/common/smbdirect/smbdirect_socket.h
+++ b/fs/smb/common/smbdirect/smbdirect_socket.h
@@ -379,20 +379,6 @@ struct smbdirect_socket {
} statistics;
struct {
-#define SMBDIRECT_LOG_ERR 0x0
-#define SMBDIRECT_LOG_INFO 0x1
-
-#define SMBDIRECT_LOG_OUTGOING 0x1
-#define SMBDIRECT_LOG_INCOMING 0x2
-#define SMBDIRECT_LOG_READ 0x4
-#define SMBDIRECT_LOG_WRITE 0x8
-#define SMBDIRECT_LOG_RDMA_SEND 0x10
-#define SMBDIRECT_LOG_RDMA_RECV 0x20
-#define SMBDIRECT_LOG_KEEP_ALIVE 0x40
-#define SMBDIRECT_LOG_RDMA_EVENT 0x80
-#define SMBDIRECT_LOG_RDMA_MR 0x100
-#define SMBDIRECT_LOG_RDMA_RW 0x200
-#define SMBDIRECT_LOG_NEGOTIATE 0x400
void *private_ptr;
bool (*needed)(struct smbdirect_socket *sc,
void *private_ptr,
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 055/127] smb: smbdirect: introduce smbdirect_private.h with prototypes
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (53 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 054/127] smb: smbdirect: introduce smbdirect_public.h with prototypes Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 056/127] smb: smbdirect: introduce the basic smbdirect.ko Stefan Metzmacher
` (72 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This has prototypes of functions used between private .c files,
when they will be compiled alone into smbdirect.ko.
For now this uses the SMBDIRECT_USE_INLINE_C_FILES code path
and marks all function as '__maybe_unused static',
but this will make further changes easier.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
.../common/smbdirect/smbdirect_connection.c | 98 +++++++++----------
fs/smb/common/smbdirect/smbdirect_internal.h | 1 +
fs/smb/common/smbdirect/smbdirect_mr.c | 8 +-
fs/smb/common/smbdirect/smbdirect_private.h | 92 +++++++++++++++++
4 files changed, 145 insertions(+), 54 deletions(-)
create mode 100644 fs/smb/common/smbdirect/smbdirect_private.h
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index b102e8014fe7..ae9626888b5c 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -19,15 +19,10 @@ struct smbdirect_map_sges {
static ssize_t smbdirect_map_sges_from_iter(struct iov_iter *iter, size_t len,
struct smbdirect_map_sges *state);
-static void smbdirect_connection_schedule_disconnect(struct smbdirect_socket *sc,
- int error);
static void smbdirect_connection_disconnect_work(struct work_struct *work);
-static void smbdirect_connection_idle_timer_work(struct work_struct *work);
static void smbdirect_connection_recv_io_refill_work(struct work_struct *work);
static void smbdirect_connection_send_immediate_work(struct work_struct *work);
-static void smbdirect_connection_destroy_mr_list(struct smbdirect_socket *sc);
-
__SMBDIRECT_PUBLIC__
bool smbdirect_frwr_is_supported(const struct ib_device_attr *attrs)
{
@@ -95,7 +90,8 @@ static int smbdirect_socket_rdma_event_handler(struct rdma_cm_id *id,
return 1;
}
-static int smbdirect_socket_init_new(struct net *net, struct smbdirect_socket *sc)
+__SMBDIRECT_PRIVATE__
+int smbdirect_socket_init_new(struct net *net, struct smbdirect_socket *sc)
{
struct rdma_cm_id *id;
@@ -407,8 +403,8 @@ static int smbdirect_connection_rdma_event_handler(struct rdma_cm_id *id,
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_PRIVATE__
+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",
@@ -421,8 +417,8 @@ static void smbdirect_connection_rdma_established(struct smbdirect_socket *sc)
sc->rdma.expected_event = RDMA_CM_EVENT_DISCONNECTED;
}
-__maybe_unused /* this is temporary while this file is included in orders */
-static void smbdirect_connection_negotiation_done(struct smbdirect_socket *sc)
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_negotiation_done(struct smbdirect_socket *sc)
{
if (unlikely(sc->first_error))
return;
@@ -497,10 +493,8 @@ static u32 smbdirect_rdma_rw_send_wrs(struct ib_device *dev,
return factor * attr->cap.max_rdma_ctxs;
}
-static void smbdirect_connection_destroy_qp(struct smbdirect_socket *sc);
-
-__maybe_unused /* this is temporary while this file is included in orders */
-static int smbdirect_connection_create_qp(struct smbdirect_socket *sc)
+__SMBDIRECT_PRIVATE__
+int smbdirect_connection_create_qp(struct smbdirect_socket *sc)
{
struct smbdirect_socket_parameters *sp = &sc->parameters;
struct ib_qp_init_attr qp_attr;
@@ -657,7 +651,8 @@ static int smbdirect_connection_create_qp(struct smbdirect_socket *sc)
return ret;
}
-static void smbdirect_connection_destroy_qp(struct smbdirect_socket *sc)
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_destroy_qp(struct smbdirect_socket *sc)
{
if (sc->ib.qp) {
ib_drain_qp(sc->ib.qp);
@@ -678,10 +673,8 @@ static void smbdirect_connection_destroy_qp(struct smbdirect_socket *sc)
}
}
-static void smbdirect_connection_destroy_mem_pools(struct smbdirect_socket *sc);
-
-__maybe_unused /* this is temporary while this file is included in orders */
-static int smbdirect_connection_create_mem_pools(struct smbdirect_socket *sc)
+__SMBDIRECT_PRIVATE__
+int smbdirect_connection_create_mem_pools(struct smbdirect_socket *sc)
{
struct smbdirect_socket_parameters *sp = &sc->parameters;
char name[80];
@@ -758,7 +751,8 @@ static int smbdirect_connection_create_mem_pools(struct smbdirect_socket *sc)
return -ENOMEM;
}
-static void smbdirect_connection_destroy_mem_pools(struct smbdirect_socket *sc)
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_destroy_mem_pools(struct smbdirect_socket *sc)
{
struct smbdirect_recv_io *recv_io, *next_io;
@@ -785,8 +779,8 @@ static void smbdirect_connection_destroy_mem_pools(struct smbdirect_socket *sc)
sc->send_io.mem.cache = NULL;
}
-__maybe_unused /* this is temporary while this file is included in orders */
-static struct smbdirect_send_io *smbdirect_connection_alloc_send_io(struct smbdirect_socket *sc)
+__SMBDIRECT_PRIVATE__
+struct smbdirect_send_io *smbdirect_connection_alloc_send_io(struct smbdirect_socket *sc)
{
struct smbdirect_send_io *msg;
@@ -800,8 +794,8 @@ static struct smbdirect_send_io *smbdirect_connection_alloc_send_io(struct smbdi
return msg;
}
-__maybe_unused /* this is temporary while this file is included in orders */
-static void smbdirect_connection_free_send_io(struct smbdirect_send_io *msg)
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_free_send_io(struct smbdirect_send_io *msg)
{
struct smbdirect_socket *sc = msg->socket;
size_t i;
@@ -832,8 +826,8 @@ static void smbdirect_connection_free_send_io(struct smbdirect_send_io *msg)
mempool_free(msg, sc->send_io.mem.pool);
}
-__maybe_unused /* this is temporary while this file is included in orders */
-static struct smbdirect_recv_io *smbdirect_connection_get_recv_io(struct smbdirect_socket *sc)
+__SMBDIRECT_PRIVATE__
+struct smbdirect_recv_io *smbdirect_connection_get_recv_io(struct smbdirect_socket *sc)
{
struct smbdirect_recv_io *msg = NULL;
unsigned long flags;
@@ -851,8 +845,8 @@ static struct smbdirect_recv_io *smbdirect_connection_get_recv_io(struct smbdire
return msg;
}
-__maybe_unused /* this is temporary while this file is included in orders */
-static void smbdirect_connection_put_recv_io(struct smbdirect_recv_io *msg)
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_put_recv_io(struct smbdirect_recv_io *msg)
{
struct smbdirect_socket *sc = msg->socket;
unsigned long flags;
@@ -908,11 +902,11 @@ smbdirect_connection_reassembly_first_recv_io(struct smbdirect_socket *sc)
return msg;
}
-__maybe_unused /* this is temporary while this file is included in orders */
-static void smbdirect_connection_negotiate_rdma_resources(struct smbdirect_socket *sc,
- u8 peer_initiator_depth,
- u8 peer_responder_resources,
- const struct rdma_conn_param *param)
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_negotiate_rdma_resources(struct smbdirect_socket *sc,
+ u8 peer_initiator_depth,
+ u8 peer_responder_resources,
+ const struct rdma_conn_param *param)
{
struct smbdirect_socket_parameters *sp = &sc->parameters;
@@ -970,8 +964,9 @@ static void smbdirect_connection_negotiate_rdma_resources(struct smbdirect_socke
peer_responder_resources);
}
-static void smbdirect_connection_schedule_disconnect(struct smbdirect_socket *sc,
- int error)
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_schedule_disconnect(struct smbdirect_socket *sc,
+ int error)
{
/*
* make sure other work (than disconnect_work)
@@ -1266,8 +1261,8 @@ static void smbdirect_connection_destroy(struct smbdirect_socket *sc)
"rdma session destroyed\n");
}
-__maybe_unused /* this is temporary while this file is included in orders */
-static void smbdirect_connection_destroy_sync(struct smbdirect_socket *sc)
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_destroy_sync(struct smbdirect_socket *sc)
{
smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
"status=%s first_error=%1pe",
@@ -1357,7 +1352,8 @@ void smbdirect_socket_release(struct smbdirect_socket *sc)
}
__SMBDIRECT_EXPORT_SYMBOL__(smbdirect_socket_release);
-static void smbdirect_connection_idle_timer_work(struct work_struct *work)
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_idle_timer_work(struct work_struct *work)
{
struct smbdirect_socket *sc =
container_of(work, struct smbdirect_socket, idle.timer_work.work);
@@ -1388,11 +1384,11 @@ static void smbdirect_connection_idle_timer_work(struct work_struct *work)
queue_work(sc->workqueue, &sc->idle.immediate_work);
}
-__maybe_unused /* this is temporary while this file is included in orders */
-static int smbdirect_connection_wait_for_credits(struct smbdirect_socket *sc,
- wait_queue_head_t *waitq,
- atomic_t *total_credits,
- int needed)
+__SMBDIRECT_PRIVATE__
+int smbdirect_connection_wait_for_credits(struct smbdirect_socket *sc,
+ wait_queue_head_t *waitq,
+ atomic_t *total_credits,
+ int needed)
{
int ret;
@@ -1454,8 +1450,9 @@ static bool smbdirect_connection_request_keep_alive(struct smbdirect_socket *sc)
return false;
}
-static int smbdirect_connection_post_send_wr(struct smbdirect_socket *sc,
- struct ib_send_wr *wr)
+__SMBDIRECT_PRIVATE__
+int smbdirect_connection_post_send_wr(struct smbdirect_socket *sc,
+ struct ib_send_wr *wr)
{
int ret;
@@ -1925,8 +1922,8 @@ static void smbdirect_connection_send_immediate_work(struct work_struct *work)
}
}
-__maybe_unused /* this is temporary while this file is included in orders */
-static int smbdirect_connection_post_recv_io(struct smbdirect_recv_io *msg)
+__SMBDIRECT_PRIVATE__
+int smbdirect_connection_post_recv_io(struct smbdirect_recv_io *msg)
{
struct smbdirect_socket *sc = msg->socket;
struct smbdirect_socket_parameters *sp = &sc->parameters;
@@ -1967,8 +1964,8 @@ static int smbdirect_connection_post_recv_io(struct smbdirect_recv_io *msg)
return ret;
}
-__maybe_unused /* this is temporary while this file is included in orders */
-static void smbdirect_connection_recv_io_done(struct ib_cq *cq, struct ib_wc *wc)
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_recv_io_done(struct ib_cq *cq, struct ib_wc *wc)
{
struct smbdirect_recv_io *recv_io =
container_of(wc->wr_cqe, struct smbdirect_recv_io, cqe);
@@ -2134,7 +2131,8 @@ static void smbdirect_connection_recv_io_done(struct ib_cq *cq, struct ib_wc *wc
smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
}
-static int smbdirect_connection_recv_io_refill(struct smbdirect_socket *sc)
+__SMBDIRECT_PRIVATE__
+int smbdirect_connection_recv_io_refill(struct smbdirect_socket *sc)
{
int missing;
int posted = 0;
diff --git a/fs/smb/common/smbdirect/smbdirect_internal.h b/fs/smb/common/smbdirect/smbdirect_internal.h
index 348de3ec92b4..579f2ffb73da 100644
--- a/fs/smb/common/smbdirect/smbdirect_internal.h
+++ b/fs/smb/common/smbdirect/smbdirect_internal.h
@@ -15,5 +15,6 @@
#include "smbdirect_pdu.h"
#include "smbdirect_public.h"
#include "smbdirect_socket.h"
+#include "smbdirect_private.h"
#endif /* __FS_SMB_COMMON_SMBDIRECT_INTERNAL_H__ */
diff --git a/fs/smb/common/smbdirect/smbdirect_mr.c b/fs/smb/common/smbdirect/smbdirect_mr.c
index b4b43df50096..93b276ae3429 100644
--- a/fs/smb/common/smbdirect/smbdirect_mr.c
+++ b/fs/smb/common/smbdirect/smbdirect_mr.c
@@ -6,7 +6,6 @@
#include "smbdirect_internal.h"
-static void smbdirect_connection_destroy_mr_list(struct smbdirect_socket *sc);
static void smbdirect_connection_mr_io_recovery_work(struct work_struct *work);
/*
@@ -16,8 +15,8 @@ static void smbdirect_connection_mr_io_recovery_work(struct work_struct *work);
* Recovery is done in smbd_mr_recovery_work. The content of list entry changes
* as MRs are used and recovered for I/O, but the list links will not change
*/
-__maybe_unused /* this is temporary while this file is included in orders */
-static int smbdirect_connection_create_mr_list(struct smbdirect_socket *sc)
+__SMBDIRECT_PRIVATE__
+int smbdirect_connection_create_mr_list(struct smbdirect_socket *sc)
{
struct smbdirect_socket_parameters *sp = &sc->parameters;
struct smbdirect_mr_io *mr;
@@ -122,7 +121,8 @@ static void smbdirect_mr_io_free_locked(struct kref *kref)
kfree(mr);
}
-static void smbdirect_connection_destroy_mr_list(struct smbdirect_socket *sc)
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_destroy_mr_list(struct smbdirect_socket *sc)
{
struct smbdirect_mr_io *mr, *tmp;
LIST_HEAD(all_list);
diff --git a/fs/smb/common/smbdirect/smbdirect_private.h b/fs/smb/common/smbdirect/smbdirect_private.h
new file mode 100644
index 000000000000..2abb905ed8b8
--- /dev/null
+++ b/fs/smb/common/smbdirect/smbdirect_private.h
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2025 Stefan Metzmacher
+ */
+
+#ifndef __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_PRIVATE_H__
+#define __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_PRIVATE_H__
+
+#include <rdma/rw.h>
+
+#ifdef SMBDIRECT_USE_INLINE_C_FILES
+/* this is temporary while this file is included in others */
+#define __SMBDIRECT_PRIVATE__ __maybe_unused static
+#else
+#define __SMBDIRECT_PRIVATE__
+#endif
+
+__SMBDIRECT_PRIVATE__
+int smbdirect_socket_init_new(struct net *net, struct smbdirect_socket *sc);
+
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_rdma_established(struct smbdirect_socket *sc);
+
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_negotiation_done(struct smbdirect_socket *sc);
+
+__SMBDIRECT_PRIVATE__
+int smbdirect_connection_create_qp(struct smbdirect_socket *sc);
+
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_destroy_qp(struct smbdirect_socket *sc);
+
+__SMBDIRECT_PRIVATE__
+int smbdirect_connection_create_mem_pools(struct smbdirect_socket *sc);
+
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_destroy_mem_pools(struct smbdirect_socket *sc);
+
+__SMBDIRECT_PRIVATE__
+struct smbdirect_send_io *smbdirect_connection_alloc_send_io(struct smbdirect_socket *sc);
+
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_free_send_io(struct smbdirect_send_io *msg);
+
+__SMBDIRECT_PRIVATE__
+struct smbdirect_recv_io *smbdirect_connection_get_recv_io(struct smbdirect_socket *sc);
+
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_put_recv_io(struct smbdirect_recv_io *msg);
+
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_negotiate_rdma_resources(struct smbdirect_socket *sc,
+ u8 peer_initiator_depth,
+ u8 peer_responder_resources,
+ const struct rdma_conn_param *param);
+
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_schedule_disconnect(struct smbdirect_socket *sc,
+ int error);
+
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_destroy_sync(struct smbdirect_socket *sc);
+
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_idle_timer_work(struct work_struct *work);
+
+__SMBDIRECT_PRIVATE__
+int smbdirect_connection_wait_for_credits(struct smbdirect_socket *sc,
+ wait_queue_head_t *waitq,
+ atomic_t *total_credits,
+ int needed);
+
+__SMBDIRECT_PRIVATE__
+int smbdirect_connection_post_send_wr(struct smbdirect_socket *sc,
+ struct ib_send_wr *wr);
+
+__SMBDIRECT_PRIVATE__
+int smbdirect_connection_post_recv_io(struct smbdirect_recv_io *msg);
+
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_recv_io_done(struct ib_cq *cq, struct ib_wc *wc);
+
+__SMBDIRECT_PRIVATE__
+int smbdirect_connection_recv_io_refill(struct smbdirect_socket *sc);
+
+__SMBDIRECT_PRIVATE__
+int smbdirect_connection_create_mr_list(struct smbdirect_socket *sc);
+
+__SMBDIRECT_PRIVATE__
+void smbdirect_connection_destroy_mr_list(struct smbdirect_socket *sc);
+
+#endif /* __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_PRIVATE_H__ */
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 056/127] smb: smbdirect: introduce the basic smbdirect.ko
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (54 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 055/127] smb: smbdirect: introduce smbdirect_private.h " Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 057/127] smb: client: make use of smbdirect_socket_prepare_create() Stefan Metzmacher
` (71 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
David Howells
This exports the functions needed by cifs.ko and ksmbd.ko.
It doesn't yet provide a generic socket layer, but it
is a good start to introduce that on top.
It will be much easier after Davids refactoring
using MSG_SPLICE_PAGES, will make it easier to
use the socket layer without an additional copy.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: Namjae Jeon <linkinjeon@kernel.org>
Cc: David Howells <dhowells@redhat.com>
Cc: linux-cifs@vger.kernel.org
Cc: samba-technical@lists.samba.org
Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
fs/smb/Kconfig | 2 ++
fs/smb/common/Makefile | 1 +
fs/smb/common/smbdirect/Kconfig | 9 +++++++++
fs/smb/common/smbdirect/Makefile | 15 +++++++++++++++
fs/smb/common/smbdirect/smbdirect_main.c | 24 ++++++++++++++++++++++++
5 files changed, 51 insertions(+)
create mode 100644 fs/smb/common/smbdirect/Kconfig
create mode 100644 fs/smb/common/smbdirect/Makefile
create mode 100644 fs/smb/common/smbdirect/smbdirect_main.c
diff --git a/fs/smb/Kconfig b/fs/smb/Kconfig
index ef425789fa6a..065c0aa130e7 100644
--- a/fs/smb/Kconfig
+++ b/fs/smb/Kconfig
@@ -9,3 +9,5 @@ config SMBFS
tristate
default y if CIFS=y || SMB_SERVER=y
default m if CIFS=m || SMB_SERVER=m
+
+source "fs/smb/common/smbdirect/Kconfig"
diff --git a/fs/smb/common/Makefile b/fs/smb/common/Makefile
index 9e0730a385fb..e6ee65c31b5d 100644
--- a/fs/smb/common/Makefile
+++ b/fs/smb/common/Makefile
@@ -4,3 +4,4 @@
#
obj-$(CONFIG_SMBFS) += cifs_md4.o
+obj-$(CONFIG_SMB_COMMON_SMBDIRECT) += smbdirect/
diff --git a/fs/smb/common/smbdirect/Kconfig b/fs/smb/common/smbdirect/Kconfig
new file mode 100644
index 000000000000..d8d8cde23860
--- /dev/null
+++ b/fs/smb/common/smbdirect/Kconfig
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# smbdirect configuration
+
+config SMB_COMMON_SMBDIRECT
+ def_tristate n
+ depends on INFINIBAND && INFINIBAND_ADDR_TRANS
+ depends on m || INFINIBAND != m
+ select SG_POOL
diff --git a/fs/smb/common/smbdirect/Makefile b/fs/smb/common/smbdirect/Makefile
new file mode 100644
index 000000000000..251766424b6b
--- /dev/null
+++ b/fs/smb/common/smbdirect/Makefile
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Makefile for smbdirect support
+#
+
+obj-$(CONFIG_SMB_COMMON_SMBDIRECT) += smbdirect.o
+
+smbdirect-y := \
+ smbdirect_connection.o \
+ smbdirect_mr.o \
+ smbdirect_rw.o \
+ smbdirect_debug.o \
+ smbdirect_connect.o \
+ smbdirect_accept.o \
+ smbdirect_main.o
diff --git a/fs/smb/common/smbdirect/smbdirect_main.c b/fs/smb/common/smbdirect/smbdirect_main.c
new file mode 100644
index 000000000000..c9fc1e1de0ca
--- /dev/null
+++ b/fs/smb/common/smbdirect/smbdirect_main.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2025, Stefan Metzmacher
+ */
+
+#include "smbdirect_internal.h"
+#include <linux/module.h>
+
+static __init int smbdirect_init_module(void)
+{
+ pr_notice("subsystem loaded\n");
+ return 0;
+}
+
+static __exit void smbdirect_exit_module(void)
+{
+ pr_notice("subsystem unloaded\n");
+}
+
+module_init(smbdirect_init_module);
+module_exit(smbdirect_exit_module);
+
+MODULE_DESCRIPTION("smbdirect subsystem");
+MODULE_LICENSE("GPL");
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 057/127] smb: client: make use of smbdirect_socket_prepare_create()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (55 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 056/127] smb: smbdirect: introduce the basic smbdirect.ko Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 058/127] smb: client: make use of smbdirect_socket_set_logging() Stefan Metzmacher
` (70 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This prepares the use of functions from smbdirect_connection.c.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 35 +++++++++++++++++++++--------------
1 file changed, 21 insertions(+), 14 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 5ae22c8dea81..04a90fd0971c 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -1793,6 +1793,7 @@ static struct smbd_connection *_smbd_get_connection(
int rc;
struct smbd_connection *info;
struct smbdirect_socket *sc;
+ struct smbdirect_socket_parameters init_params = {};
struct smbdirect_socket_parameters *sp;
struct rdma_conn_param conn_param;
struct ib_qp_cap qp_cap;
@@ -1803,20 +1804,10 @@ static struct smbd_connection *_smbd_get_connection(
char wq_name[80];
struct workqueue_struct *workqueue;
- info = kzalloc(sizeof(struct smbd_connection), GFP_KERNEL);
- if (!info)
- return NULL;
- sc = &info->socket;
- scnprintf(wq_name, ARRAY_SIZE(wq_name), "smbd_%p", sc);
- workqueue = create_workqueue(wq_name);
- if (!workqueue)
- goto create_wq_failed;
- smbdirect_socket_init(sc);
- sc->workqueue = workqueue;
- sp = &sc->parameters;
-
- INIT_WORK(&sc->disconnect_work, smbd_disconnect_rdma_work);
-
+ /*
+ * Create the initial parameters
+ */
+ sp = &init_params;
sp->resolve_addr_timeout_msec = RDMA_RESOLVE_TIMEOUT;
sp->resolve_route_timeout_msec = RDMA_RESOLVE_TIMEOUT;
sp->rdma_connect_timeout_msec = RDMA_RESOLVE_TIMEOUT;
@@ -1832,6 +1823,22 @@ static struct smbd_connection *_smbd_get_connection(
sp->keepalive_interval_msec = smbd_keep_alive_interval * 1000;
sp->keepalive_timeout_msec = KEEPALIVE_RECV_TIMEOUT * 1000;
+ info = kzalloc(sizeof(struct smbd_connection), GFP_KERNEL);
+ if (!info)
+ return NULL;
+ sc = &info->socket;
+ scnprintf(wq_name, ARRAY_SIZE(wq_name), "smbd_%p", sc);
+ workqueue = create_workqueue(wq_name);
+ if (!workqueue)
+ goto create_wq_failed;
+ smbdirect_socket_prepare_create(sc, sp, workqueue);
+ /*
+ * from here we operate on the copy.
+ */
+ sp = &sc->parameters;
+
+ INIT_WORK(&sc->disconnect_work, smbd_disconnect_rdma_work);
+
rc = smbd_ia_open(sc, dstaddr, port);
if (rc) {
log_rdma_event(INFO, "smbd_ia_open rc=%d\n", rc);
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 058/127] smb: client: make use of smbdirect_socket_set_logging()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (56 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 057/127] smb: client: make use of smbdirect_socket_prepare_create() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 059/127] smb: client: make use of smbdirect_connection_wake_up_all() Stefan Metzmacher
` (69 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This will allow the logging to keep working as before,
when we move to common functions in the next commits.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 04a90fd0971c..08192d69617b 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -153,6 +153,43 @@ MODULE_PARM_DESC(smbd_logging_level,
*/
#include "../common/smbdirect/smbdirect_all_c_files.c"
+static bool smbd_logging_needed(struct smbdirect_socket *sc,
+ void *private_ptr,
+ unsigned int lvl,
+ unsigned int cls)
+{
+#define BUILD_BUG_SAME(x) BUILD_BUG_ON(x != SMBDIRECT_LOG_ ##x)
+ BUILD_BUG_SAME(ERR);
+ BUILD_BUG_SAME(INFO);
+#undef BUILD_BUG_SAME
+#define BUILD_BUG_SAME(x) BUILD_BUG_ON(x != SMBDIRECT_ ##x)
+ BUILD_BUG_SAME(LOG_OUTGOING);
+ BUILD_BUG_SAME(LOG_INCOMING);
+ BUILD_BUG_SAME(LOG_READ);
+ BUILD_BUG_SAME(LOG_WRITE);
+ BUILD_BUG_SAME(LOG_RDMA_SEND);
+ BUILD_BUG_SAME(LOG_RDMA_RECV);
+ BUILD_BUG_SAME(LOG_KEEP_ALIVE);
+ BUILD_BUG_SAME(LOG_RDMA_EVENT);
+ BUILD_BUG_SAME(LOG_RDMA_MR);
+#undef BUILD_BUG_SAME
+
+ if (lvl <= smbd_logging_level || cls & smbd_logging_class)
+ return true;
+ return false;
+}
+
+static void smbd_logging_vaprintf(struct smbdirect_socket *sc,
+ const char *func,
+ unsigned int line,
+ void *private_ptr,
+ unsigned int lvl,
+ unsigned int cls,
+ struct va_format *vaf)
+{
+ cifs_dbg(VFS, "%s:%u %pV", func, line, vaf);
+}
+
#define log_rdma(level, class, fmt, args...) \
do { \
if (level <= smbd_logging_level || class & smbd_logging_class) \
@@ -1832,6 +1869,7 @@ static struct smbd_connection *_smbd_get_connection(
if (!workqueue)
goto create_wq_failed;
smbdirect_socket_prepare_create(sc, sp, workqueue);
+ smbdirect_socket_set_logging(sc, NULL, smbd_logging_needed, smbd_logging_vaprintf);
/*
* from here we operate on the copy.
*/
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 059/127] smb: client: make use of smbdirect_connection_wake_up_all()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (57 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 058/127] smb: client: make use of smbdirect_socket_set_logging() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 060/127] smb: client: make use of smbdirect_connection_disconnect_work() Stefan Metzmacher
` (68 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This is a superset of smbd_disconnect_wake_up_all() and
calling wake_up_all(&sc->rw_io.credits.wait_queue); in addition
should not matter as it's not used on the client anyway.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 22 +++-------------------
1 file changed, 3 insertions(+), 19 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 08192d69617b..c6f2bb5fc262 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -213,22 +213,6 @@ 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.lcredits.wait_queue);
- 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 =
@@ -285,7 +269,7 @@ static void smbd_disconnect_rdma_work(struct work_struct *work)
* Wake up all waiters in all wait queues
* in order to notice the broken connection.
*/
- smbd_disconnect_wake_up_all(sc);
+ smbdirect_connection_wake_up_all(sc);
}
static void smbd_disconnect_rdma_connection(struct smbdirect_socket *sc)
@@ -347,7 +331,7 @@ static void smbd_disconnect_rdma_connection(struct smbdirect_socket *sc)
* Wake up all waiters in all wait queues
* in order to notice the broken connection.
*/
- smbd_disconnect_wake_up_all(sc);
+ smbdirect_connection_wake_up_all(sc);
queue_work(sc->workqueue, &sc->disconnect_work);
}
@@ -1655,7 +1639,7 @@ void smbd_destroy(struct TCP_Server_Info *server)
* Most likely this was already called via
* smbd_disconnect_rdma_work(), but call it again...
*/
- smbd_disconnect_wake_up_all(sc);
+ smbdirect_connection_wake_up_all(sc);
log_rdma_event(INFO, "cancelling recv_io.posted.refill_work\n");
disable_work_sync(&sc->recv_io.posted.refill_work);
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 060/127] smb: client: make use of smbdirect_connection_disconnect_work()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (58 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 059/127] smb: client: make use of smbdirect_connection_wake_up_all() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 061/127] smb: client: make use of smbdirect_connection_schedule_disconnect() Stefan Metzmacher
` (67 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
Note smbdirect_socket_prepare_create() already calls INIT_WORK()
with smbdirect_connection_disconnect_work.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 73 ++++-----------------------------------
1 file changed, 6 insertions(+), 67 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index c6f2bb5fc262..137fad17e5a1 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -213,65 +213,6 @@ do { \
#define log_rdma_mr(level, fmt, args...) \
log_rdma(level, LOG_RDMA_MR, fmt, ##args)
-static void smbd_disconnect_rdma_work(struct work_struct *work)
-{
- struct smbdirect_socket *sc =
- container_of(work, struct smbdirect_socket, disconnect_work);
-
- /*
- * make sure this and other work is not queued again
- * but here we don't block and avoid
- * disable[_delayed]_work_sync()
- */
- disable_work(&sc->disconnect_work);
- disable_work(&sc->recv_io.posted.refill_work);
- disable_work(&sc->mr_io.recovery_work);
- disable_work(&sc->idle.immediate_work);
- disable_delayed_work(&sc->idle.timer_work);
-
- if (sc->first_error == 0)
- sc->first_error = -ECONNABORTED;
-
- 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_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;
- }
-
- /*
- * Wake up all waiters in all wait queues
- * in order to notice the broken connection.
- */
- smbdirect_connection_wake_up_all(sc);
-}
-
static void smbd_disconnect_rdma_connection(struct smbdirect_socket *sc)
{
/*
@@ -366,14 +307,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;
- smbd_disconnect_rdma_work(&sc->disconnect_work);
+ smbdirect_connection_disconnect_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;
- smbd_disconnect_rdma_work(&sc->disconnect_work);
+ smbdirect_connection_disconnect_work(&sc->disconnect_work);
break;
case RDMA_CM_EVENT_ESTABLISHED:
@@ -468,7 +409,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;
- smbd_disconnect_rdma_work(&sc->disconnect_work);
+ smbdirect_connection_disconnect_work(&sc->disconnect_work);
break;
case RDMA_CM_EVENT_DEVICE_REMOVAL:
@@ -479,7 +420,7 @@ static int smbd_conn_upcall(
}
sc->status = SMBDIRECT_SOCKET_DISCONNECTED;
- smbd_disconnect_rdma_work(&sc->disconnect_work);
+ smbdirect_connection_disconnect_work(&sc->disconnect_work);
break;
default:
@@ -1625,7 +1566,7 @@ void smbd_destroy(struct TCP_Server_Info *server)
log_rdma_event(INFO, "destroying rdma session\n");
if (sc->status < SMBDIRECT_SOCKET_DISCONNECTING)
- smbd_disconnect_rdma_work(&sc->disconnect_work);
+ smbdirect_connection_disconnect_work(&sc->disconnect_work);
if (sc->status < SMBDIRECT_SOCKET_DISCONNECTED) {
log_rdma_event(INFO, "wait for transport being disconnected\n");
wait_event(sc->status_wait, sc->status == SMBDIRECT_SOCKET_DISCONNECTED);
@@ -1637,7 +1578,7 @@ void smbd_destroy(struct TCP_Server_Info *server)
* in order to notice the broken connection.
*
* Most likely this was already called via
- * smbd_disconnect_rdma_work(), but call it again...
+ * smbdirect_connection_disconnect_work(), but call it again...
*/
smbdirect_connection_wake_up_all(sc);
@@ -1859,8 +1800,6 @@ static struct smbd_connection *_smbd_get_connection(
*/
sp = &sc->parameters;
- INIT_WORK(&sc->disconnect_work, smbd_disconnect_rdma_work);
-
rc = smbd_ia_open(sc, dstaddr, port);
if (rc) {
log_rdma_event(INFO, "smbd_ia_open rc=%d\n", rc);
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 061/127] smb: client: make use of smbdirect_connection_schedule_disconnect()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (59 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 060/127] smb: client: make use of smbdirect_connection_disconnect_work() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 062/127] smb: client: make use of smbdirect_connection_{get,put}_recv_io() Stefan Metzmacher
` (66 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This removes smbd_disconnect_rdma_connection() which is basically
the same as smbdirect_connection_schedule_disconnect().
And we pass more useful errors than -ECONNABORTED if we have them.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 91 ++++++---------------------------------
1 file changed, 14 insertions(+), 77 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 137fad17e5a1..8b98ef1d41e1 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -213,70 +213,6 @@ do { \
#define log_rdma_mr(level, fmt, args...) \
log_rdma(level, LOG_RDMA_MR, fmt, ##args)
-static void smbd_disconnect_rdma_connection(struct smbdirect_socket *sc)
-{
- /*
- * make sure other work (than disconnect_work) is
- * not queued again but here we don't block and avoid
- * disable[_delayed]_work_sync()
- */
- disable_work(&sc->recv_io.posted.refill_work);
- disable_work(&sc->mr_io.recovery_work);
- disable_work(&sc->idle.immediate_work);
- disable_delayed_work(&sc->idle.timer_work);
-
- if (sc->first_error == 0)
- sc->first_error = -ECONNABORTED;
-
- switch (sc->status) {
- case SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED:
- case SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED:
- case SMBDIRECT_SOCKET_RDMA_CONNECT_FAILED:
- case SMBDIRECT_SOCKET_NEGOTIATE_FAILED:
- case SMBDIRECT_SOCKET_ERROR:
- case SMBDIRECT_SOCKET_DISCONNECTING:
- case SMBDIRECT_SOCKET_DISCONNECTED:
- case SMBDIRECT_SOCKET_DESTROYED:
- /*
- * Keep the current error status
- */
- break;
-
- case SMBDIRECT_SOCKET_RESOLVE_ADDR_NEEDED:
- case SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING:
- sc->status = SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED;
- break;
-
- case SMBDIRECT_SOCKET_RESOLVE_ROUTE_NEEDED:
- case SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING:
- sc->status = SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED;
- break;
-
- case SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED:
- case SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING:
- sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_FAILED;
- break;
-
- case SMBDIRECT_SOCKET_NEGOTIATE_NEEDED:
- case SMBDIRECT_SOCKET_NEGOTIATE_RUNNING:
- sc->status = SMBDIRECT_SOCKET_NEGOTIATE_FAILED;
- break;
-
- case SMBDIRECT_SOCKET_CREATED:
- case SMBDIRECT_SOCKET_CONNECTED:
- sc->status = SMBDIRECT_SOCKET_ERROR;
- break;
- }
-
- /*
- * Wake up all waiters in all wait queues
- * in order to notice the broken connection.
- */
- smbdirect_connection_wake_up_all(sc);
-
- queue_work(sc->workqueue, &sc->disconnect_work);
-}
-
/* Upcall from RDMA CM */
static int smbd_conn_upcall(
struct rdma_cm_id *id, struct rdma_cm_event *event)
@@ -444,7 +380,7 @@ smbd_qp_async_error_upcall(struct ib_event *event, void *context)
switch (event->event) {
case IB_EVENT_CQ_ERR:
case IB_EVENT_QP_FATAL:
- smbd_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
break;
default:
@@ -486,7 +422,7 @@ static void send_done(struct ib_cq *cq, struct ib_wc *wc)
if (wc->status != IB_WC_WR_FLUSH_ERR)
log_rdma_send(ERR, "wc->status=%s wc->opcode=%d\n",
ib_wc_status_msg(wc->status), wc->opcode);
- smbd_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
return;
}
@@ -672,7 +608,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;
- smbd_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
} else {
sc->status = SMBDIRECT_SOCKET_CONNECTED;
wake_up(&sc->status_wait);
@@ -769,7 +705,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
WARN_ON_ONCE(sc->recv_io.expected != SMBDIRECT_EXPECT_DATA_TRANSFER);
error:
put_receive_buffer(sc, response);
- smbd_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
}
static struct rdma_cm_id *smbd_create_id(
@@ -984,7 +920,7 @@ static int smbd_post_send_negotiate_req(struct smbdirect_socket *sc)
ib_dma_unmap_single(sc->ib.dev, request->sge[0].addr,
request->sge[0].length, DMA_TO_DEVICE);
- smbd_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, rc);
dma_mapping_failed:
mempool_free(request, sc->send_io.mem.pool);
@@ -1073,7 +1009,7 @@ static int smbd_post_send(struct smbdirect_socket *sc,
rc = ib_post_send(sc->ib.qp, &send_wr, NULL);
if (rc) {
log_rdma_send(ERR, "ib_post_send failed rc=%d\n", rc);
- smbd_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, rc);
rc = -EAGAIN;
}
@@ -1314,7 +1250,7 @@ static int smbd_post_recv(
ib_dma_unmap_single(sc->ib.dev, response->sge.addr,
response->sge.length, DMA_FROM_DEVICE);
response->sge.length = 0;
- smbd_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, rc);
log_rdma_recv(ERR, "ib_post_recv failed rc=%d\n", rc);
}
@@ -1525,7 +1461,7 @@ static void idle_connection_timer(struct work_struct *work)
log_keep_alive(ERR,
"error status sc->idle.keepalive=%d\n",
sc->idle.keepalive);
- smbd_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, -ETIMEDOUT);
return;
}
@@ -2284,7 +2220,7 @@ static void register_mr_done(struct ib_cq *cq, struct ib_wc *wc)
if (wc->status) {
log_rdma_mr(ERR, "status=%d\n", wc->status);
- smbd_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
}
}
@@ -2314,7 +2250,7 @@ static void smbd_mr_recovery_work(struct work_struct *work)
log_rdma_mr(ERR,
"ib_dereg_mr failed rc=%x\n",
rc);
- smbd_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, rc);
continue;
}
@@ -2322,10 +2258,11 @@ static void smbd_mr_recovery_work(struct work_struct *work)
sc->ib.pd, sc->mr_io.type,
sp->max_frmr_depth);
if (IS_ERR(smbdirect_mr->mr)) {
+ rc = PTR_ERR(smbdirect_mr->mr);
log_rdma_mr(ERR, "ib_alloc_mr failed mr_type=%x max_frmr_depth=%x\n",
sc->mr_io.type,
sp->max_frmr_depth);
- smbd_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, rc);
continue;
}
} else
@@ -2661,7 +2598,7 @@ struct smbdirect_mr_io *smbd_register_mr(struct smbd_connection *info,
if (atomic_dec_and_test(&sc->mr_io.used.count))
wake_up(&sc->mr_io.cleanup.wait_queue);
- smbd_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, rc);
/*
* get_mr() gave us a reference
@@ -2736,7 +2673,7 @@ void smbd_deregister_mr(struct smbdirect_mr_io *mr)
if (rc) {
log_rdma_mr(ERR, "ib_post_send failed rc=%x\n", rc);
smbd_mr_disable_locked(mr);
- smbd_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, rc);
goto done;
}
wait_for_completion(&mr->invalidate_done);
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 062/127] smb: client: make use of smbdirect_connection_{get,put}_recv_io()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (60 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 061/127] smb: client: make use of smbdirect_connection_schedule_disconnect() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 063/127] smb: client: make use of smbdirect_connection_reassembly_{append,first}_recv_io() Stefan Metzmacher
` (65 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
These are basically copies of {get,put}_receive_buffer().
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 78 ++++++---------------------------------
1 file changed, 11 insertions(+), 67 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 8b98ef1d41e1..d76b25fc80f1 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -23,11 +23,6 @@ const struct smbdirect_socket_parameters *smbd_get_parameters(struct smbd_connec
return &sc->parameters;
}
-static struct smbdirect_recv_io *get_receive_buffer(
- struct smbdirect_socket *sc);
-static void put_receive_buffer(
- struct smbdirect_socket *sc,
- struct smbdirect_recv_io *response);
static int allocate_receive_buffers(struct smbdirect_socket *sc, int num_buf);
static void destroy_receive_buffers(struct smbdirect_socket *sc);
@@ -531,7 +526,7 @@ static void smbd_post_send_credits(struct work_struct *work)
if (sc->recv_io.credits.target >
atomic_read(&sc->recv_io.credits.count)) {
while (true) {
- response = get_receive_buffer(sc);
+ response = smbdirect_connection_get_recv_io(sc);
if (!response)
break;
@@ -540,7 +535,7 @@ static void smbd_post_send_credits(struct work_struct *work)
if (rc) {
log_rdma_recv(ERR,
"post_recv failed rc=%d\n", rc);
- put_receive_buffer(sc, response);
+ smbdirect_connection_put_recv_io(response);
break;
}
@@ -604,7 +599,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
sc->recv_io.reassembly.full_packet_received = true;
negotiate_done =
process_negotiation_response(response, wc->byte_len);
- put_receive_buffer(sc, response);
+ smbdirect_connection_put_recv_io(response);
WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_NEGOTIATE_RUNNING);
if (!negotiate_done) {
sc->status = SMBDIRECT_SOCKET_NEGOTIATE_FAILED;
@@ -689,7 +684,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
enqueue_reassembly(sc, response, data_length);
wake_up(&sc->recv_io.reassembly.wait_queue);
} else
- put_receive_buffer(sc, response);
+ smbdirect_connection_put_recv_io(response);
return;
@@ -704,7 +699,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
log_rdma_recv(ERR, "unexpected response type=%d\n", sc->recv_io.expected);
WARN_ON_ONCE(sc->recv_io.expected != SMBDIRECT_EXPECT_DATA_TRANSFER);
error:
- put_receive_buffer(sc, response);
+ smbdirect_connection_put_recv_io(response);
smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
}
@@ -1262,7 +1257,7 @@ static int smbd_negotiate(struct smbdirect_socket *sc)
{
struct smbdirect_socket_parameters *sp = &sc->parameters;
int rc;
- struct smbdirect_recv_io *response = get_receive_buffer(sc);
+ struct smbdirect_recv_io *response = smbdirect_connection_get_recv_io(sc);
WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_NEGOTIATE_NEEDED);
sc->status = SMBDIRECT_SOCKET_NEGOTIATE_RUNNING;
@@ -1273,7 +1268,7 @@ static int smbd_negotiate(struct smbdirect_socket *sc)
rc, response->sge.addr,
response->sge.length, response->sge.lkey);
if (rc) {
- put_receive_buffer(sc, response);
+ smbdirect_connection_put_recv_io(response);
return rc;
}
@@ -1349,57 +1344,6 @@ static struct smbdirect_recv_io *_get_first_reassembly(struct smbdirect_socket *
return ret;
}
-/*
- * Get a receive buffer
- * For each remote send, we need to post a receive. The receive buffers are
- * pre-allocated in advance.
- * return value: the receive buffer, NULL if none is available
- */
-static struct smbdirect_recv_io *get_receive_buffer(struct smbdirect_socket *sc)
-{
- struct smbdirect_recv_io *ret = NULL;
- unsigned long flags;
-
- spin_lock_irqsave(&sc->recv_io.free.lock, flags);
- if (!list_empty(&sc->recv_io.free.list)) {
- ret = list_first_entry(
- &sc->recv_io.free.list,
- struct smbdirect_recv_io, list);
- list_del(&ret->list);
- sc->statistics.get_receive_buffer++;
- }
- spin_unlock_irqrestore(&sc->recv_io.free.lock, flags);
-
- return ret;
-}
-
-/*
- * Return a receive buffer
- * Upon returning of a receive buffer, we can post new receive and extend
- * more receive credits to remote peer. This is done immediately after a
- * receive buffer is returned.
- */
-static void put_receive_buffer(
- struct smbdirect_socket *sc, struct smbdirect_recv_io *response)
-{
- unsigned long flags;
-
- if (likely(response->sge.length != 0)) {
- ib_dma_unmap_single(sc->ib.dev,
- response->sge.addr,
- response->sge.length,
- DMA_FROM_DEVICE);
- response->sge.length = 0;
- }
-
- spin_lock_irqsave(&sc->recv_io.free.lock, flags);
- list_add_tail(&response->list, &sc->recv_io.free.list);
- sc->statistics.put_receive_buffer++;
- spin_unlock_irqrestore(&sc->recv_io.free.lock, flags);
-
- queue_work(sc->workqueue, &sc->recv_io.posted.refill_work);
-}
-
/* Preallocate all receive buffer on transport establishment */
static int allocate_receive_buffers(struct smbdirect_socket *sc, int num_buf)
{
@@ -1434,7 +1378,7 @@ static void destroy_receive_buffers(struct smbdirect_socket *sc)
{
struct smbdirect_recv_io *response;
- while ((response = get_receive_buffer(sc)))
+ while ((response = smbdirect_connection_get_recv_io(sc)))
mempool_free(response, sc->recv_io.mem.pool);
}
@@ -1540,7 +1484,7 @@ void smbd_destroy(struct TCP_Server_Info *server)
list_del(&response->list);
spin_unlock_irqrestore(
&sc->recv_io.reassembly.lock, flags);
- put_receive_buffer(sc, response);
+ smbdirect_connection_put_recv_io(response);
} else
spin_unlock_irqrestore(
&sc->recv_io.reassembly.lock, flags);
@@ -2079,9 +2023,9 @@ int smbd_recv(struct smbd_connection *info, struct msghdr *msg)
}
queue_removed++;
sc->statistics.dequeue_reassembly_queue++;
- put_receive_buffer(sc, response);
+ smbdirect_connection_put_recv_io(response);
offset = 0;
- log_read(INFO, "put_receive_buffer offset=0\n");
+ log_read(INFO, "smbdirect_connection_put_recv_io offset=0\n");
} else
offset += to_copy;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 063/127] smb: client: make use of smbdirect_connection_reassembly_{append,first}_recv_io()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (61 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 062/127] smb: client: make use of smbdirect_connection_{get,put}_recv_io() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 064/127] smb: client: make use of smbdirect_connection_idle_timer_work() Stefan Metzmacher
` (64 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
These are exact copies of enqueue_reassembly() and _get_first_reassembly().
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 63 +++------------------------------------
1 file changed, 4 insertions(+), 59 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index d76b25fc80f1..cf2f63696f85 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -26,12 +26,6 @@ const struct smbdirect_socket_parameters *smbd_get_parameters(struct smbd_connec
static int allocate_receive_buffers(struct smbdirect_socket *sc, int num_buf);
static void destroy_receive_buffers(struct smbdirect_socket *sc);
-static void enqueue_reassembly(
- struct smbdirect_socket *sc,
- struct smbdirect_recv_io *response, int data_length);
-static struct smbdirect_recv_io *_get_first_reassembly(
- struct smbdirect_socket *sc);
-
static int smbd_post_recv(
struct smbdirect_socket *sc,
struct smbdirect_recv_io *response);
@@ -681,7 +675,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
if (sc->recv_io.credits.target > old_recv_credit_target)
queue_work(sc->workqueue, &sc->recv_io.posted.refill_work);
- enqueue_reassembly(sc, response, data_length);
+ smbdirect_connection_reassembly_append_recv_io(sc, response, data_length);
wake_up(&sc->recv_io.reassembly.wait_queue);
} else
smbdirect_connection_put_recv_io(response);
@@ -1295,55 +1289,6 @@ static int smbd_negotiate(struct smbdirect_socket *sc)
return rc;
}
-/*
- * Implement Connection.FragmentReassemblyBuffer defined in [MS-SMBD] 3.1.1.1
- * This is a queue for reassembling upper layer payload and present to upper
- * layer. All the inncoming payload go to the reassembly queue, regardless of
- * if reassembly is required. The uuper layer code reads from the queue for all
- * incoming payloads.
- * Put a received packet to the reassembly queue
- * response: the packet received
- * data_length: the size of payload in this packet
- */
-static void enqueue_reassembly(
- struct smbdirect_socket *sc,
- struct smbdirect_recv_io *response,
- int data_length)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags);
- list_add_tail(&response->list, &sc->recv_io.reassembly.list);
- sc->recv_io.reassembly.queue_length++;
- /*
- * Make sure reassembly_data_length is updated after list and
- * reassembly_queue_length are updated. On the dequeue side
- * reassembly_data_length is checked without a lock to determine
- * if reassembly_queue_length and list is up to date
- */
- virt_wmb();
- sc->recv_io.reassembly.data_length += data_length;
- spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags);
- sc->statistics.enqueue_reassembly_queue++;
-}
-
-/*
- * Get the first entry at the front of reassembly queue
- * Caller is responsible for locking
- * return value: the first entry if any, NULL if queue is empty
- */
-static struct smbdirect_recv_io *_get_first_reassembly(struct smbdirect_socket *sc)
-{
- struct smbdirect_recv_io *ret = NULL;
-
- if (!list_empty(&sc->recv_io.reassembly.list)) {
- ret = list_first_entry(
- &sc->recv_io.reassembly.list,
- struct smbdirect_recv_io, list);
- }
- return ret;
-}
-
/* Preallocate all receive buffer on transport establishment */
static int allocate_receive_buffers(struct smbdirect_socket *sc, int num_buf)
{
@@ -1479,7 +1424,7 @@ void smbd_destroy(struct TCP_Server_Info *server)
log_rdma_event(INFO, "drain the reassembly queue\n");
do {
spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags);
- response = _get_first_reassembly(sc);
+ response = smbdirect_connection_reassembly_first_recv_io(sc);
if (response) {
list_del(&response->list);
spin_unlock_irqrestore(
@@ -1960,7 +1905,7 @@ int smbd_recv(struct smbd_connection *info, struct msghdr *msg)
/*
* Need to make sure reassembly_data_length is read before
* reading reassembly_queue_length and calling
- * _get_first_reassembly. This call is lock free
+ * smbdirect_connection_reassembly_first_recv_io. This call is lock free
* as we never read at the end of the queue which are being
* updated in SOFTIRQ as more data is received
*/
@@ -1970,7 +1915,7 @@ int smbd_recv(struct smbd_connection *info, struct msghdr *msg)
to_read = size;
offset = sc->recv_io.reassembly.first_entry_offset;
while (data_read < size) {
- response = _get_first_reassembly(sc);
+ response = smbdirect_connection_reassembly_first_recv_io(sc);
data_transfer = smbdirect_recv_io_payload(response);
data_length = le32_to_cpu(data_transfer->data_length);
remaining_data_length =
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 064/127] smb: client: make use of smbdirect_connection_idle_timer_work()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (62 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 063/127] smb: client: make use of smbdirect_connection_reassembly_{append,first}_recv_io() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 065/127] smb: client: make use of smbdirect_frwr_is_supported() Stefan Metzmacher
` (63 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This is basically a copy of idle_connection_timer().
Note smbdirect_socket_prepare_create() already calls INIT_DELAYED_WORK().
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 30 ------------------------------
1 file changed, 30 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index cf2f63696f85..e61f41fd020b 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -1339,35 +1339,6 @@ static void send_immediate_empty_message(struct work_struct *work)
smbd_post_send_empty(sc);
}
-/* Implement idle connection timer [MS-SMBD] 3.1.6.2 */
-static void idle_connection_timer(struct work_struct *work)
-{
- struct smbdirect_socket *sc =
- container_of(work, struct smbdirect_socket, idle.timer_work.work);
- struct smbdirect_socket_parameters *sp = &sc->parameters;
-
- if (sc->idle.keepalive != SMBDIRECT_KEEPALIVE_NONE) {
- log_keep_alive(ERR,
- "error status sc->idle.keepalive=%d\n",
- sc->idle.keepalive);
- smbdirect_connection_schedule_disconnect(sc, -ETIMEDOUT);
- return;
- }
-
- if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
- return;
-
- /*
- * Now use the keepalive timeout (instead of keepalive interval)
- * in order to wait for a response
- */
- sc->idle.keepalive = SMBDIRECT_KEEPALIVE_PENDING;
- mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
- msecs_to_jiffies(sp->keepalive_timeout_msec));
- log_keep_alive(INFO, "schedule send of empty idle message\n");
- queue_work(sc->workqueue, &sc->idle.immediate_work);
-}
-
/*
* Destroy the transport and related RDMA and memory resources
* Need to go through all the pending counters and make sure on one is using
@@ -1771,7 +1742,6 @@ static struct smbd_connection *_smbd_get_connection(
}
INIT_WORK(&sc->idle.immediate_work, send_immediate_empty_message);
- INIT_DELAYED_WORK(&sc->idle.timer_work, idle_connection_timer);
/*
* start with the negotiate timeout and SMBDIRECT_KEEPALIVE_PENDING
* so that the timer will cause a disconnect.
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 065/127] smb: client: make use of smbdirect_frwr_is_supported()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (63 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 064/127] smb: client: make use of smbdirect_connection_idle_timer_work() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 066/127] smb: client: make use of smbdirect_connection_{alloc,free}_send_io() Stefan Metzmacher
` (62 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This an exact copy of frwr_is_supported().
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 16 +---------------
1 file changed, 1 insertion(+), 15 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index e61f41fd020b..ab8ce4c46bd6 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -783,20 +783,6 @@ static struct rdma_cm_id *smbd_create_id(
return ERR_PTR(rc);
}
-/*
- * Test if FRWR (Fast Registration Work Requests) is supported on the device
- * This implementation requires FRWR on RDMA read/write
- * return value: true if it is supported
- */
-static bool frwr_is_supported(struct ib_device_attr *attrs)
-{
- if (!(attrs->device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS))
- return false;
- if (attrs->max_fast_reg_page_list_len == 0)
- return false;
- return true;
-}
-
static int smbd_ia_open(
struct smbdirect_socket *sc,
struct sockaddr *dstaddr, int port)
@@ -814,7 +800,7 @@ static int smbd_ia_open(
}
sc->ib.dev = sc->rdma.cm_id->device;
- if (!frwr_is_supported(&sc->ib.dev->attrs)) {
+ if (!smbdirect_frwr_is_supported(&sc->ib.dev->attrs)) {
log_rdma_event(ERR, "Fast Registration Work Requests (FRWR) is not supported\n");
log_rdma_event(ERR, "Device capability flags = %llx max_fast_reg_page_list_len = %u\n",
sc->ib.dev->attrs.device_cap_flags,
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 066/127] smb: client: make use of smbdirect_connection_{alloc,free}_send_io()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (64 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 065/127] smb: client: make use of smbdirect_frwr_is_supported() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 067/127] smb: client: make use of smbdirect_connection_send_io_done() Stefan Metzmacher
` (61 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This simplifies the code and allows us to share more code in common
with the server.
The only difference is that we use ib_dma_unmap_page() for all sges,
this simplifies the logic and doesn't matter as
ib_dma_unmap_single() and ib_dma_unmap_page() both operate
on dma_addr_t and dma_unmap_single_attrs() is just an
alias for dma_unmap_page_attrs().
We already had such an inconsistency before
as we called ib_dma_unmap_single(), while we mapped
using ib_dma_map_page() in smb_set_sge().
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 42 ++++++++++++---------------------------
1 file changed, 13 insertions(+), 29 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index ab8ce4c46bd6..1eed0686a34d 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -390,7 +390,6 @@ static inline void *smbdirect_recv_io_payload(struct smbdirect_recv_io *response
/* Called when a RDMA send is done */
static void send_done(struct ib_cq *cq, struct ib_wc *wc)
{
- int i;
struct smbdirect_send_io *request =
container_of(wc->wr_cqe, struct smbdirect_send_io, cqe);
struct smbdirect_socket *sc = request->socket;
@@ -399,12 +398,8 @@ static void send_done(struct ib_cq *cq, struct ib_wc *wc)
log_rdma_send(INFO, "smbdirect_send_io 0x%p completed wc->status=%s\n",
request, ib_wc_status_msg(wc->status));
- for (i = 0; i < request->num_sge; i++)
- ib_dma_unmap_single(sc->ib.dev,
- request->sge[i].addr,
- request->sge[i].length,
- DMA_TO_DEVICE);
- mempool_free(request, sc->send_io.mem.pool);
+ /* Note this frees wc->wr_cqe, but not wc */
+ smbdirect_connection_free_send_io(request);
lcredits += 1;
if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_SEND) {
@@ -835,15 +830,13 @@ static int smbd_post_send_negotiate_req(struct smbdirect_socket *sc)
{
struct smbdirect_socket_parameters *sp = &sc->parameters;
struct ib_send_wr send_wr;
- int rc = -ENOMEM;
+ int rc;
struct smbdirect_send_io *request;
struct smbdirect_negotiate_req *packet;
- request = mempool_alloc(sc->send_io.mem.pool, GFP_KERNEL);
- if (!request)
- return rc;
-
- request->socket = sc;
+ request = smbdirect_connection_alloc_send_io(sc);
+ if (IS_ERR(request))
+ return PTR_ERR(request);
packet = smbdirect_send_io_payload(request);
packet->min_version = cpu_to_le16(SMBDIRECT_V1);
@@ -855,7 +848,6 @@ static int smbd_post_send_negotiate_req(struct smbdirect_socket *sc)
packet->max_fragmented_size =
cpu_to_le32(sp->max_fragmented_recv_size);
- request->num_sge = 1;
request->sge[0].addr = ib_dma_map_single(
sc->ib.dev, (void *)packet,
sizeof(*packet), DMA_TO_DEVICE);
@@ -866,6 +858,7 @@ static int smbd_post_send_negotiate_req(struct smbdirect_socket *sc)
request->sge[0].length = sizeof(*packet);
request->sge[0].lkey = sc->ib.pd->local_dma_lkey;
+ request->num_sge = 1;
ib_dma_sync_single_for_device(
sc->ib.dev, request->sge[0].addr,
@@ -892,13 +885,11 @@ static int smbd_post_send_negotiate_req(struct smbdirect_socket *sc)
/* if we reach here, post send failed */
log_rdma_send(ERR, "ib_post_send failed rc=%d\n", rc);
atomic_dec(&sc->send_io.pending.count);
- ib_dma_unmap_single(sc->ib.dev, request->sge[0].addr,
- request->sge[0].length, DMA_TO_DEVICE);
smbdirect_connection_schedule_disconnect(sc, rc);
dma_mapping_failed:
- mempool_free(request, sc->send_io.mem.pool);
+ smbdirect_connection_free_send_io(request);
return rc;
}
@@ -996,7 +987,7 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
int *_remaining_data_length)
{
struct smbdirect_socket_parameters *sp = &sc->parameters;
- int i, rc;
+ int rc;
int header_length;
int data_length;
struct smbdirect_send_io *request;
@@ -1039,13 +1030,12 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
goto wait_credit;
}
- request = mempool_alloc(sc->send_io.mem.pool, GFP_KERNEL);
- if (!request) {
- rc = -ENOMEM;
+ request = smbdirect_connection_alloc_send_io(sc);
+ if (IS_ERR(request)) {
+ rc = PTR_ERR(request);
goto err_alloc;
}
- request->socket = sc;
memset(request->sge, 0, sizeof(request->sge));
/* Map the packet to DMA */
@@ -1135,13 +1125,7 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
wake_up(&sc->send_io.pending.dec_wait_queue);
err_dma:
- for (i = 0; i < request->num_sge; i++)
- if (request->sge[i].addr)
- ib_dma_unmap_single(sc->ib.dev,
- request->sge[i].addr,
- request->sge[i].length,
- DMA_TO_DEVICE);
- mempool_free(request, sc->send_io.mem.pool);
+ smbdirect_connection_free_send_io(request);
/* roll back the granted receive credits */
atomic_sub(new_credits, &sc->recv_io.credits.count);
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 067/127] smb: client: make use of smbdirect_connection_send_io_done()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (65 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 066/127] smb: client: make use of smbdirect_connection_{alloc,free}_send_io() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 068/127] smb: client: make use of smbdirect_connection_{create,destroy}_mem_pools() Stefan Metzmacher
` (60 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This handles freeing of siblings too, which is used on
the client yet, but that might follow later.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 36 ++----------------------------------
1 file changed, 2 insertions(+), 34 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 1eed0686a34d..ba6f88e8f33c 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -387,38 +387,6 @@ static inline void *smbdirect_recv_io_payload(struct smbdirect_recv_io *response
return (void *)response->packet;
}
-/* Called when a RDMA send is done */
-static void send_done(struct ib_cq *cq, struct ib_wc *wc)
-{
- struct smbdirect_send_io *request =
- container_of(wc->wr_cqe, struct smbdirect_send_io, cqe);
- struct smbdirect_socket *sc = request->socket;
- int lcredits = 0;
-
- log_rdma_send(INFO, "smbdirect_send_io 0x%p completed wc->status=%s\n",
- request, ib_wc_status_msg(wc->status));
-
- /* Note this frees wc->wr_cqe, but not wc */
- smbdirect_connection_free_send_io(request);
- lcredits += 1;
-
- if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_SEND) {
- if (wc->status != IB_WC_WR_FLUSH_ERR)
- log_rdma_send(ERR, "wc->status=%s wc->opcode=%d\n",
- ib_wc_status_msg(wc->status), wc->opcode);
- smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
- return;
- }
-
- atomic_add(lcredits, &sc->send_io.lcredits.count);
- wake_up(&sc->send_io.lcredits.wait_queue);
-
- if (atomic_dec_and_test(&sc->send_io.pending.count))
- wake_up(&sc->send_io.pending.zero_wait_queue);
-
- wake_up(&sc->send_io.pending.dec_wait_queue);
-}
-
static void dump_smbdirect_negotiate_resp(struct smbdirect_negotiate_resp *resp)
{
log_rdma_event(INFO, "resp message min_version %u max_version %u negotiated_version %u credits_requested %u credits_granted %u status %u max_readwrite_size %u preferred_send_size %u max_receive_size %u max_fragmented_size %u\n",
@@ -864,7 +832,7 @@ static int smbd_post_send_negotiate_req(struct smbdirect_socket *sc)
sc->ib.dev, request->sge[0].addr,
request->sge[0].length, DMA_TO_DEVICE);
- request->cqe.done = send_done;
+ request->cqe.done = smbdirect_connection_send_io_done;
send_wr.next = NULL;
send_wr.wr_cqe = &request->cqe;
@@ -963,7 +931,7 @@ static int smbd_post_send(struct smbdirect_socket *sc,
DMA_TO_DEVICE);
}
- request->cqe.done = send_done;
+ request->cqe.done = smbdirect_connection_send_io_done;
send_wr.next = NULL;
send_wr.wr_cqe = &request->cqe;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 068/127] smb: client: make use of smbdirect_connection_{create,destroy}_mem_pools()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (66 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 067/127] smb: client: make use of smbdirect_connection_send_io_done() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 069/127] smb: client: make use of smbdirect_map_sges_from_iter() Stefan Metzmacher
` (59 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
The main logical differences are the following:
We now don't use smbdirect_connection_get_recv_io() on cleanup,
instead it uses list_for_each_entry_safe()...
For the smbdirect_recv_io payload we expose the whole payload including
the smbdirect_data_transfer header as documentation says data_offset = 0
and data_length != 0 would be valid, while the existing client code
requires data_offset >= 24.
The smbdirect_send_io cache includes header space for
sizeof(struct smbdirect_negotiate_resp) = 32 bytes
instead of sizeof(struct smbdirect_data_transfer) = 24 bytes.
If this ever becomes a problem, we can allocate separate
space for the smbdirect_negotiate_resp in the server.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 129 +-------------------------------------
1 file changed, 3 insertions(+), 126 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index ba6f88e8f33c..689b691557c2 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -23,9 +23,6 @@ const struct smbdirect_socket_parameters *smbd_get_parameters(struct smbd_connec
return &sc->parameters;
}
-static int allocate_receive_buffers(struct smbdirect_socket *sc, int num_buf);
-static void destroy_receive_buffers(struct smbdirect_socket *sc);
-
static int smbd_post_recv(
struct smbdirect_socket *sc,
struct smbdirect_recv_io *response);
@@ -1227,44 +1224,6 @@ static int smbd_negotiate(struct smbdirect_socket *sc)
return rc;
}
-/* Preallocate all receive buffer on transport establishment */
-static int allocate_receive_buffers(struct smbdirect_socket *sc, int num_buf)
-{
- struct smbdirect_recv_io *response;
- int i;
-
- for (i = 0; i < num_buf; i++) {
- response = mempool_alloc(sc->recv_io.mem.pool, GFP_KERNEL);
- if (!response)
- goto allocate_failed;
-
- response->socket = sc;
- response->sge.length = 0;
- list_add_tail(&response->list, &sc->recv_io.free.list);
- }
-
- return 0;
-
-allocate_failed:
- while (!list_empty(&sc->recv_io.free.list)) {
- response = list_first_entry(
- &sc->recv_io.free.list,
- struct smbdirect_recv_io, list);
- list_del(&response->list);
-
- mempool_free(response, sc->recv_io.mem.pool);
- }
- return -ENOMEM;
-}
-
-static void destroy_receive_buffers(struct smbdirect_socket *sc)
-{
- struct smbdirect_recv_io *response;
-
- while ((response = smbdirect_connection_get_recv_io(sc)))
- mempool_free(response, sc->recv_io.mem.pool);
-}
-
static void send_immediate_empty_message(struct work_struct *work)
{
struct smbdirect_socket *sc =
@@ -1345,9 +1304,6 @@ void smbd_destroy(struct TCP_Server_Info *server)
} while (response);
sc->recv_io.reassembly.data_length = 0;
- log_rdma_event(INFO, "free receive buffers\n");
- destroy_receive_buffers(sc);
-
log_rdma_event(INFO, "freeing mr list\n");
destroy_mr_list(sc);
@@ -1357,11 +1313,7 @@ void smbd_destroy(struct TCP_Server_Info *server)
rdma_destroy_id(sc->rdma.cm_id);
/* free mempools */
- mempool_destroy(sc->send_io.mem.pool);
- kmem_cache_destroy(sc->send_io.mem.cache);
-
- mempool_destroy(sc->recv_io.mem.pool);
- kmem_cache_destroy(sc->recv_io.mem.cache);
+ smbdirect_connection_destroy_mem_pools(sc);
sc->status = SMBDIRECT_SOCKET_DESTROYED;
@@ -1407,81 +1359,6 @@ int smbd_reconnect(struct TCP_Server_Info *server)
return -ENOENT;
}
-static void destroy_caches(struct smbdirect_socket *sc)
-{
- destroy_receive_buffers(sc);
- mempool_destroy(sc->recv_io.mem.pool);
- kmem_cache_destroy(sc->recv_io.mem.cache);
- mempool_destroy(sc->send_io.mem.pool);
- kmem_cache_destroy(sc->send_io.mem.cache);
-}
-
-#define MAX_NAME_LEN 80
-static int allocate_caches(struct smbdirect_socket *sc)
-{
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- char name[MAX_NAME_LEN];
- int rc;
-
- if (WARN_ON_ONCE(sp->max_recv_size < sizeof(struct smbdirect_data_transfer)))
- return -ENOMEM;
-
- scnprintf(name, MAX_NAME_LEN, "smbdirect_send_io_%p", sc);
- sc->send_io.mem.cache =
- kmem_cache_create(
- name,
- sizeof(struct smbdirect_send_io) +
- sizeof(struct smbdirect_data_transfer),
- 0, SLAB_HWCACHE_ALIGN, NULL);
- if (!sc->send_io.mem.cache)
- return -ENOMEM;
-
- sc->send_io.mem.pool =
- mempool_create(sp->send_credit_target, mempool_alloc_slab,
- mempool_free_slab, sc->send_io.mem.cache);
- if (!sc->send_io.mem.pool)
- goto out1;
-
- scnprintf(name, MAX_NAME_LEN, "smbdirect_recv_io_%p", sc);
-
- struct kmem_cache_args response_args = {
- .align = __alignof__(struct smbdirect_recv_io),
- .useroffset = (offsetof(struct smbdirect_recv_io, packet) +
- sizeof(struct smbdirect_data_transfer)),
- .usersize = sp->max_recv_size - sizeof(struct smbdirect_data_transfer),
- };
- sc->recv_io.mem.cache =
- kmem_cache_create(name,
- sizeof(struct smbdirect_recv_io) + sp->max_recv_size,
- &response_args, SLAB_HWCACHE_ALIGN);
- if (!sc->recv_io.mem.cache)
- goto out2;
-
- sc->recv_io.mem.pool =
- mempool_create(sp->recv_credit_max, mempool_alloc_slab,
- mempool_free_slab, sc->recv_io.mem.cache);
- if (!sc->recv_io.mem.pool)
- goto out3;
-
- rc = allocate_receive_buffers(sc, sp->recv_credit_max);
- if (rc) {
- log_rdma_event(ERR, "failed to allocate receive buffers\n");
- goto out4;
- }
-
- return 0;
-
-out4:
- mempool_destroy(sc->recv_io.mem.pool);
-out3:
- kmem_cache_destroy(sc->recv_io.mem.cache);
-out2:
- mempool_destroy(sc->send_io.mem.pool);
-out1:
- kmem_cache_destroy(sc->send_io.mem.cache);
- return -ENOMEM;
-}
-
/* Create a SMBD connection, called by upper layer */
static struct smbd_connection *_smbd_get_connection(
struct TCP_Server_Info *server, struct sockaddr *dstaddr, int port)
@@ -1673,7 +1550,7 @@ static struct smbd_connection *_smbd_get_connection(
log_rdma_event(INFO, "rdma_connect connected\n");
- rc = allocate_caches(sc);
+ rc = smbdirect_connection_create_mem_pools(sc);
if (rc) {
log_rdma_event(ERR, "cache allocation failed\n");
goto allocate_cache_failed;
@@ -1712,7 +1589,7 @@ static struct smbd_connection *_smbd_get_connection(
negotiation_failed:
disable_delayed_work_sync(&sc->idle.timer_work);
- destroy_caches(sc);
+ smbdirect_connection_destroy_mem_pools(sc);
sc->status = SMBDIRECT_SOCKET_NEGOTIATE_FAILED;
rdma_disconnect(sc->rdma.cm_id);
wait_event(sc->status_wait,
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 069/127] smb: client: make use of smbdirect_map_sges_from_iter()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (67 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 068/127] smb: client: make use of smbdirect_connection_{create,destroy}_mem_pools() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 070/127] smb: client: make use of smbdirect_connection_qp_event_handler() Stefan Metzmacher
` (58 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This is basically a copy of smb_extract_iter_to_rdma() moved
to common code.
Before we had the inconsistency we called ib_dma_unmap_single(),
while we mapped using ib_dma_map_page() in smb_set_sge().
Now ib_dma_unmap_page() is used for consistency.
It doesn't really matter as ib_dma_unmap_single() and
ib_dma_unmap_page() both operate
on dma_addr_t and dma_unmap_single_attrs() is just an
alias for dma_unmap_page_attrs().
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 241 +-------------------------------------
1 file changed, 5 insertions(+), 236 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 689b691557c2..19971f7c4670 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -32,17 +32,6 @@ static int smbd_post_send_empty(struct smbdirect_socket *sc);
static void destroy_mr_list(struct smbdirect_socket *sc);
static int allocate_mr_list(struct smbdirect_socket *sc);
-struct smb_extract_to_rdma {
- struct ib_sge *sge;
- unsigned int nr_sge;
- unsigned int max_sge;
- struct ib_device *device;
- u32 local_dma_lkey;
- enum dma_data_direction direction;
-};
-static ssize_t smb_extract_iter_to_rdma(struct iov_iter *iter, size_t len,
- struct smb_extract_to_rdma *rdma);
-
/* Port numbers for SMBD transport */
#define SMB_PORT 445
#define SMBD_PORT 5445
@@ -1025,9 +1014,9 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
/* Fill in the data payload to find out how much data we can add */
if (iter) {
- struct smb_extract_to_rdma extract = {
- .nr_sge = request->num_sge,
- .max_sge = SMBDIRECT_SEND_IO_MAX_SGE,
+ struct smbdirect_map_sges extract = {
+ .num_sge = request->num_sge,
+ .max_sge = ARRAY_SIZE(request->sge),
.sge = request->sge,
.device = sc->ib.dev,
.local_dma_lkey = sc->ib.pd->local_dma_lkey,
@@ -1036,12 +1025,11 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
size_t payload_len = umin(*_remaining_data_length,
sp->max_send_size - sizeof(*packet));
- rc = smb_extract_iter_to_rdma(iter, payload_len,
- &extract);
+ rc = smbdirect_map_sges_from_iter(iter, payload_len, &extract);
if (rc < 0)
goto err_dma;
data_length = rc;
- request->num_sge = extract.nr_sge;
+ request->num_sge = extract.num_sge;
*_remaining_data_length -= data_length;
} else {
data_length = 0;
@@ -2397,222 +2385,3 @@ void smbd_deregister_mr(struct smbdirect_mr_io *mr)
if (!kref_put(&mr->kref, smbd_mr_free_locked))
mutex_unlock(&mr->mutex);
}
-
-static bool smb_set_sge(struct smb_extract_to_rdma *rdma,
- struct page *lowest_page, size_t off, size_t len)
-{
- struct ib_sge *sge = &rdma->sge[rdma->nr_sge];
- u64 addr;
-
- addr = ib_dma_map_page(rdma->device, lowest_page,
- off, len, rdma->direction);
- if (ib_dma_mapping_error(rdma->device, addr))
- return false;
-
- sge->addr = addr;
- sge->length = len;
- sge->lkey = rdma->local_dma_lkey;
- rdma->nr_sge++;
- return true;
-}
-
-/*
- * Extract page fragments from a BVEC-class iterator and add them to an RDMA
- * element list. The pages are not pinned.
- */
-static ssize_t smb_extract_bvec_to_rdma(struct iov_iter *iter,
- struct smb_extract_to_rdma *rdma,
- ssize_t maxsize)
-{
- const struct bio_vec *bv = iter->bvec;
- unsigned long start = iter->iov_offset;
- unsigned int i;
- ssize_t ret = 0;
-
- for (i = 0; i < iter->nr_segs; i++) {
- size_t off, len;
-
- len = bv[i].bv_len;
- if (start >= len) {
- start -= len;
- continue;
- }
-
- len = min_t(size_t, maxsize, len - start);
- off = bv[i].bv_offset + start;
-
- if (!smb_set_sge(rdma, bv[i].bv_page, off, len))
- return -EIO;
-
- ret += len;
- maxsize -= len;
- if (rdma->nr_sge >= rdma->max_sge || maxsize <= 0)
- break;
- start = 0;
- }
-
- if (ret > 0)
- iov_iter_advance(iter, ret);
- return ret;
-}
-
-/*
- * Extract fragments from a KVEC-class iterator and add them to an RDMA list.
- * This can deal with vmalloc'd buffers as well as kmalloc'd or static buffers.
- * The pages are not pinned.
- */
-static ssize_t smb_extract_kvec_to_rdma(struct iov_iter *iter,
- struct smb_extract_to_rdma *rdma,
- ssize_t maxsize)
-{
- const struct kvec *kv = iter->kvec;
- unsigned long start = iter->iov_offset;
- unsigned int i;
- ssize_t ret = 0;
-
- for (i = 0; i < iter->nr_segs; i++) {
- struct page *page;
- unsigned long kaddr;
- size_t off, len, seg;
-
- len = kv[i].iov_len;
- if (start >= len) {
- start -= len;
- continue;
- }
-
- kaddr = (unsigned long)kv[i].iov_base + start;
- off = kaddr & ~PAGE_MASK;
- len = min_t(size_t, maxsize, len - start);
- kaddr &= PAGE_MASK;
-
- maxsize -= len;
- do {
- seg = min_t(size_t, len, PAGE_SIZE - off);
-
- if (is_vmalloc_or_module_addr((void *)kaddr))
- page = vmalloc_to_page((void *)kaddr);
- else
- page = virt_to_page((void *)kaddr);
-
- if (!smb_set_sge(rdma, page, off, seg))
- return -EIO;
-
- ret += seg;
- len -= seg;
- kaddr += PAGE_SIZE;
- off = 0;
- } while (len > 0 && rdma->nr_sge < rdma->max_sge);
-
- if (rdma->nr_sge >= rdma->max_sge || maxsize <= 0)
- break;
- start = 0;
- }
-
- if (ret > 0)
- iov_iter_advance(iter, ret);
- return ret;
-}
-
-/*
- * Extract folio fragments from a FOLIOQ-class iterator and add them to an RDMA
- * list. The folios are not pinned.
- */
-static ssize_t smb_extract_folioq_to_rdma(struct iov_iter *iter,
- struct smb_extract_to_rdma *rdma,
- ssize_t maxsize)
-{
- const struct folio_queue *folioq = iter->folioq;
- unsigned int slot = iter->folioq_slot;
- ssize_t ret = 0;
- size_t offset = iter->iov_offset;
-
- BUG_ON(!folioq);
-
- if (slot >= folioq_nr_slots(folioq)) {
- folioq = folioq->next;
- if (WARN_ON_ONCE(!folioq))
- return -EIO;
- slot = 0;
- }
-
- do {
- struct folio *folio = folioq_folio(folioq, slot);
- size_t fsize = folioq_folio_size(folioq, slot);
-
- if (offset < fsize) {
- size_t part = umin(maxsize, fsize - offset);
-
- if (!smb_set_sge(rdma, folio_page(folio, 0), offset, part))
- return -EIO;
-
- offset += part;
- ret += part;
- maxsize -= part;
- }
-
- if (offset >= fsize) {
- offset = 0;
- slot++;
- if (slot >= folioq_nr_slots(folioq)) {
- if (!folioq->next) {
- WARN_ON_ONCE(ret < iter->count);
- break;
- }
- folioq = folioq->next;
- slot = 0;
- }
- }
- } while (rdma->nr_sge < rdma->max_sge && maxsize > 0);
-
- iter->folioq = folioq;
- iter->folioq_slot = slot;
- iter->iov_offset = offset;
- iter->count -= ret;
- return ret;
-}
-
-/*
- * Extract page fragments from up to the given amount of the source iterator
- * and build up an RDMA list that refers to all of those bits. The RDMA list
- * is appended to, up to the maximum number of elements set in the parameter
- * block.
- *
- * The extracted page fragments are not pinned or ref'd in any way; if an
- * IOVEC/UBUF-type iterator is to be used, it should be converted to a
- * BVEC-type iterator and the pages pinned, ref'd or otherwise held in some
- * way.
- */
-static ssize_t smb_extract_iter_to_rdma(struct iov_iter *iter, size_t len,
- struct smb_extract_to_rdma *rdma)
-{
- ssize_t ret;
- int before = rdma->nr_sge;
-
- switch (iov_iter_type(iter)) {
- case ITER_BVEC:
- ret = smb_extract_bvec_to_rdma(iter, rdma, len);
- break;
- case ITER_KVEC:
- ret = smb_extract_kvec_to_rdma(iter, rdma, len);
- break;
- case ITER_FOLIOQ:
- ret = smb_extract_folioq_to_rdma(iter, rdma, len);
- break;
- default:
- WARN_ON_ONCE(1);
- return -EIO;
- }
-
- if (ret < 0) {
- while (rdma->nr_sge > before) {
- struct ib_sge *sge = &rdma->sge[rdma->nr_sge--];
-
- ib_dma_unmap_single(rdma->device, sge->addr, sge->length,
- rdma->direction);
- sge->addr = 0;
- }
- }
-
- return ret;
-}
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 070/127] smb: client: make use of smbdirect_connection_qp_event_handler()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (68 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 069/127] smb: client: make use of smbdirect_map_sges_from_iter() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 071/127] smb: client: make use of smbdirect_connection_negotiate_rdma_resources() Stefan Metzmacher
` (57 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This is a copy of smbd_qp_async_error_upcall()...
It will allow more code to be moved to common functions
soon.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 22 +---------------------
1 file changed, 1 insertion(+), 21 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 19971f7c4670..9326023c4afc 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -343,26 +343,6 @@ static int smbd_conn_upcall(
return 0;
}
-/* Upcall from RDMA QP */
-static void
-smbd_qp_async_error_upcall(struct ib_event *event, void *context)
-{
- struct smbdirect_socket *sc = context;
-
- log_rdma_event(ERR, "%s on device %s socket %p\n",
- ib_event_msg(event->event), event->device->name, sc);
-
- switch (event->event) {
- case IB_EVENT_CQ_ERR:
- case IB_EVENT_QP_FATAL:
- smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
- break;
-
- default:
- break;
- }
-}
-
static inline void *smbdirect_send_io_payload(struct smbdirect_send_io *request)
{
return (void *)request->packet;
@@ -1478,7 +1458,7 @@ static struct smbd_connection *_smbd_get_connection(
}
memset(&qp_attr, 0, sizeof(qp_attr));
- qp_attr.event_handler = smbd_qp_async_error_upcall;
+ qp_attr.event_handler = smbdirect_connection_qp_event_handler;
qp_attr.qp_context = sc;
qp_attr.cap = qp_cap;
qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 071/127] smb: client: make use of smbdirect_connection_negotiate_rdma_resources()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (69 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 070/127] smb: client: make use of smbdirect_connection_qp_event_handler() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 072/127] smb: client: make use of smbdirect_connection_{create,destroy}_qp() Stefan Metzmacher
` (56 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
It's good to have this logic in a central place, it will allow us
share more code soon.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 59 +++------------------------------------
1 file changed, 4 insertions(+), 55 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 9326023c4afc..b2d94411ecc2 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -193,7 +193,6 @@ static int smbd_conn_upcall(
struct rdma_cm_id *id, struct rdma_cm_event *event)
{
struct smbdirect_socket *sc = id->context;
- struct smbdirect_socket_parameters *sp = &sc->parameters;
const char *event_name = rdma_event_msg(event->event);
u8 peer_initiator_depth;
u8 peer_responder_resources;
@@ -254,60 +253,10 @@ static int smbd_conn_upcall(
peer_initiator_depth = event->param.conn.initiator_depth;
peer_responder_resources = event->param.conn.responder_resources;
}
- if (rdma_protocol_iwarp(id->device, id->port_num) &&
- event->param.conn.private_data_len == 8) {
- /*
- * Legacy clients with only iWarp MPA v1 support
- * need a private blob in order to negotiate
- * the IRD/ORD values.
- */
- const __be32 *ird_ord_hdr = event->param.conn.private_data;
- u32 ird32 = be32_to_cpu(ird_ord_hdr[0]);
- u32 ord32 = be32_to_cpu(ird_ord_hdr[1]);
-
- /*
- * cifs.ko sends the legacy IRD/ORD negotiation
- * event if iWarp MPA v2 was used.
- *
- * Here we check that the values match and only
- * mark the client as legacy if they don't match.
- */
- if ((u32)event->param.conn.initiator_depth != ird32 ||
- (u32)event->param.conn.responder_resources != ord32) {
- /*
- * There are broken clients (old cifs.ko)
- * using little endian and also
- * struct rdma_conn_param only uses u8
- * for initiator_depth and responder_resources,
- * so we truncate the value to U8_MAX.
- *
- * smb_direct_accept_client() will then
- * do the real negotiation in order to
- * select the minimum between client and
- * server.
- */
- ird32 = min_t(u32, ird32, U8_MAX);
- ord32 = min_t(u32, ord32, U8_MAX);
-
- sc->rdma.legacy_iwarp = true;
- peer_initiator_depth = (u8)ird32;
- peer_responder_resources = (u8)ord32;
- }
- }
-
- /*
- * negotiate the value by using the minimum
- * between client and server if the client provided
- * non 0 values.
- */
- if (peer_initiator_depth != 0)
- sp->initiator_depth =
- min_t(u8, sp->initiator_depth,
- peer_initiator_depth);
- if (peer_responder_resources != 0)
- sp->responder_resources =
- min_t(u8, sp->responder_resources,
- peer_responder_resources);
+ smbdirect_connection_negotiate_rdma_resources(sc,
+ peer_initiator_depth,
+ peer_responder_resources,
+ &event->param.conn);
WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING);
sc->status = SMBDIRECT_SOCKET_NEGOTIATE_NEEDED;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 072/127] smb: client: make use of smbdirect_connection_{create,destroy}_qp()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (70 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 071/127] smb: client: make use of smbdirect_connection_negotiate_rdma_resources() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 073/127] smb: client: initialize recv_io->cqe.done = recv_done just once Stefan Metzmacher
` (55 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
It's good a use common code for this and it will allow us
to share more code in the next steps.
Calling ib_drain_qp() twice is ok.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 105 +++-----------------------------------
1 file changed, 7 insertions(+), 98 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index b2d94411ecc2..59ab8489ad9f 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -1195,10 +1195,8 @@ void smbd_destroy(struct TCP_Server_Info *server)
log_rdma_event(INFO, "cancelling recv_io.posted.refill_work\n");
disable_work_sync(&sc->recv_io.posted.refill_work);
- log_rdma_event(INFO, "destroying qp\n");
+ log_rdma_event(INFO, "drain qp\n");
ib_drain_qp(sc->ib.qp);
- rdma_destroy_qp(sc->rdma.cm_id);
- sc->ib.qp = NULL;
log_rdma_event(INFO, "cancelling idle timer\n");
disable_delayed_work_sync(&sc->idle.timer_work);
@@ -1224,9 +1222,8 @@ void smbd_destroy(struct TCP_Server_Info *server)
log_rdma_event(INFO, "freeing mr list\n");
destroy_mr_list(sc);
- ib_free_cq(sc->ib.send_cq);
- ib_free_cq(sc->ib.recv_cq);
- ib_dealloc_pd(sc->ib.pd);
+ log_rdma_event(INFO, "destroying qp\n");
+ smbdirect_connection_destroy_qp(sc);
rdma_destroy_id(sc->rdma.cm_id);
/* free mempools */
@@ -1286,8 +1283,6 @@ static struct smbd_connection *_smbd_get_connection(
struct smbdirect_socket_parameters init_params = {};
struct smbdirect_socket_parameters *sp;
struct rdma_conn_param conn_param;
- struct ib_qp_cap qp_cap;
- struct ib_qp_init_attr qp_attr;
struct sockaddr_in *addr_in = (struct sockaddr_in *) dstaddr;
struct ib_port_immutable port_immutable;
__be32 ird_ord_hdr[2];
@@ -1323,6 +1318,7 @@ static struct smbd_connection *_smbd_get_connection(
goto create_wq_failed;
smbdirect_socket_prepare_create(sc, sp, workqueue);
smbdirect_socket_set_logging(sc, NULL, smbd_logging_needed, smbd_logging_vaprintf);
+ sc->ib.poll_ctx = IB_POLL_SOFTIRQ;
/*
* from here we operate on the copy.
*/
@@ -1334,94 +1330,17 @@ static struct smbd_connection *_smbd_get_connection(
goto create_id_failed;
}
- if (sp->send_credit_target > sc->ib.dev->attrs.max_cqe ||
- sp->send_credit_target > sc->ib.dev->attrs.max_qp_wr) {
- log_rdma_event(ERR, "consider lowering send_credit_target = %d. Possible CQE overrun, device reporting max_cqe %d max_qp_wr %d\n",
- sp->send_credit_target,
- sc->ib.dev->attrs.max_cqe,
- sc->ib.dev->attrs.max_qp_wr);
- goto config_failed;
- }
-
- if (sp->recv_credit_max > sc->ib.dev->attrs.max_cqe ||
- sp->recv_credit_max > sc->ib.dev->attrs.max_qp_wr) {
- log_rdma_event(ERR, "consider lowering receive_credit_max = %d. Possible CQE overrun, device reporting max_cqe %d max_qp_wr %d\n",
- sp->recv_credit_max,
- sc->ib.dev->attrs.max_cqe,
- sc->ib.dev->attrs.max_qp_wr);
- goto config_failed;
- }
-
- if (sc->ib.dev->attrs.max_send_sge < SMBDIRECT_SEND_IO_MAX_SGE ||
- sc->ib.dev->attrs.max_recv_sge < SMBDIRECT_RECV_IO_MAX_SGE) {
- log_rdma_event(ERR,
- "device %.*s max_send_sge/max_recv_sge = %d/%d too small\n",
- IB_DEVICE_NAME_MAX,
- sc->ib.dev->name,
- sc->ib.dev->attrs.max_send_sge,
- sc->ib.dev->attrs.max_recv_sge);
- goto config_failed;
- }
-
sp->responder_resources =
min_t(u8, sp->responder_resources,
sc->ib.dev->attrs.max_qp_rd_atom);
log_rdma_mr(INFO, "responder_resources=%d\n",
sp->responder_resources);
- /*
- * We use allocate sp->responder_resources * 2 MRs
- * and each MR needs WRs for REG and INV, so
- * we use '* 4'.
- *
- * +1 for ib_drain_qp()
- */
- memset(&qp_cap, 0, sizeof(qp_cap));
- qp_cap.max_send_wr = sp->send_credit_target + sp->responder_resources * 4 + 1;
- qp_cap.max_recv_wr = sp->recv_credit_max + 1;
- qp_cap.max_send_sge = SMBDIRECT_SEND_IO_MAX_SGE;
- qp_cap.max_recv_sge = SMBDIRECT_RECV_IO_MAX_SGE;
-
- sc->ib.pd = ib_alloc_pd(sc->ib.dev, 0);
- if (IS_ERR(sc->ib.pd)) {
- rc = PTR_ERR(sc->ib.pd);
- sc->ib.pd = NULL;
- log_rdma_event(ERR, "ib_alloc_pd() returned %d\n", rc);
- goto alloc_pd_failed;
- }
-
- sc->ib.send_cq =
- ib_alloc_cq_any(sc->ib.dev, sc,
- qp_cap.max_send_wr, IB_POLL_SOFTIRQ);
- if (IS_ERR(sc->ib.send_cq)) {
- sc->ib.send_cq = NULL;
- goto alloc_cq_failed;
- }
-
- sc->ib.recv_cq =
- ib_alloc_cq_any(sc->ib.dev, sc,
- qp_cap.max_recv_wr, IB_POLL_SOFTIRQ);
- if (IS_ERR(sc->ib.recv_cq)) {
- sc->ib.recv_cq = NULL;
- goto alloc_cq_failed;
- }
-
- memset(&qp_attr, 0, sizeof(qp_attr));
- qp_attr.event_handler = smbdirect_connection_qp_event_handler;
- qp_attr.qp_context = sc;
- qp_attr.cap = qp_cap;
- qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR;
- qp_attr.qp_type = IB_QPT_RC;
- qp_attr.send_cq = sc->ib.send_cq;
- qp_attr.recv_cq = sc->ib.recv_cq;
- qp_attr.port_num = ~0;
-
- rc = rdma_create_qp(sc->rdma.cm_id, sc->ib.pd, &qp_attr);
+ rc = smbdirect_connection_create_qp(sc);
if (rc) {
- log_rdma_event(ERR, "rdma_create_qp failed %i\n", rc);
+ log_rdma_event(ERR, "smbdirect_connection_create_qp failed %i\n", rc);
goto create_qp_failed;
}
- sc->ib.qp = sc->rdma.cm_id->qp;
memset(&conn_param, 0, sizeof(conn_param));
conn_param.initiator_depth = sp->initiator_depth;
@@ -1514,19 +1433,9 @@ static struct smbd_connection *_smbd_get_connection(
allocate_cache_failed:
rdma_connect_failed:
- rdma_destroy_qp(sc->rdma.cm_id);
+ smbdirect_connection_destroy_qp(sc);
create_qp_failed:
-alloc_cq_failed:
- if (sc->ib.send_cq)
- ib_free_cq(sc->ib.send_cq);
- if (sc->ib.recv_cq)
- ib_free_cq(sc->ib.recv_cq);
-
- ib_dealloc_pd(sc->ib.pd);
-
-alloc_pd_failed:
-config_failed:
rdma_destroy_id(sc->rdma.cm_id);
create_id_failed:
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 073/127] smb: client: initialize recv_io->cqe.done = recv_done just once
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (71 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 072/127] smb: client: make use of smbdirect_connection_{create,destroy}_qp() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 074/127] smb: client: make use of smbdirect_connection_post_recv_io() Stefan Metzmacher
` (54 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
smbdirect_recv_io structures are pre-allocated so we can set the
callback function just once.
This will make it easy to move smbd_post_recv() to common code
soon.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 59ab8489ad9f..60582394ba29 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -1079,8 +1079,6 @@ static int smbd_post_recv(
response->sge.length = sp->max_recv_size;
response->sge.lkey = sc->ib.pd->local_dma_lkey;
- response->cqe.done = recv_done;
-
recv_wr.wr_cqe = &response->cqe;
recv_wr.next = NULL;
recv_wr.sg_list = &response->sge;
@@ -1288,6 +1286,7 @@ static struct smbd_connection *_smbd_get_connection(
__be32 ird_ord_hdr[2];
char wq_name[80];
struct workqueue_struct *workqueue;
+ struct smbdirect_recv_io *recv_io;
/*
* Create the initial parameters
@@ -1392,6 +1391,9 @@ static struct smbd_connection *_smbd_get_connection(
goto allocate_cache_failed;
}
+ list_for_each_entry(recv_io, &sc->recv_io.free.list, list)
+ recv_io->cqe.done = recv_done;
+
INIT_WORK(&sc->idle.immediate_work, send_immediate_empty_message);
/*
* start with the negotiate timeout and SMBDIRECT_KEEPALIVE_PENDING
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 074/127] smb: client: make use of smbdirect_connection_post_recv_io()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (72 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 073/127] smb: client: initialize recv_io->cqe.done = recv_done just once Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 075/127] smb: client: make use of smbdirect_connection_recv_io_refill_work() Stefan Metzmacher
` (53 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
The only difference is that smbdirect_connection_post_recv_io()
returns early if the connection is already broken.
And that the error code from ib_dma_mapping_error() (currently only -ENOMEM
is possible) is returned instead of -EIO.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 46 ++-------------------------------------
1 file changed, 2 insertions(+), 44 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 60582394ba29..9dfee81396c7 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -23,10 +23,6 @@ const struct smbdirect_socket_parameters *smbd_get_parameters(struct smbd_connec
return &sc->parameters;
}
-static int smbd_post_recv(
- struct smbdirect_socket *sc,
- struct smbdirect_recv_io *response);
-
static int smbd_post_send_empty(struct smbdirect_socket *sc);
static void destroy_mr_list(struct smbdirect_socket *sc);
@@ -403,7 +399,7 @@ static void smbd_post_send_credits(struct work_struct *work)
break;
response->first_segment = false;
- rc = smbd_post_recv(sc, response);
+ rc = smbdirect_connection_post_recv_io(response);
if (rc) {
log_rdma_recv(ERR,
"post_recv failed rc=%d\n", rc);
@@ -1058,44 +1054,6 @@ static int smbd_post_send_full_iter(struct smbdirect_socket *sc,
return rc;
}
-/*
- * Post a receive request to the transport
- * The remote peer can only send data when a receive request is posted
- * The interaction is controlled by send/receive credit system
- */
-static int smbd_post_recv(
- struct smbdirect_socket *sc, struct smbdirect_recv_io *response)
-{
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- struct ib_recv_wr recv_wr;
- int rc = -EIO;
-
- response->sge.addr = ib_dma_map_single(
- sc->ib.dev, response->packet,
- sp->max_recv_size, DMA_FROM_DEVICE);
- if (ib_dma_mapping_error(sc->ib.dev, response->sge.addr))
- return rc;
-
- response->sge.length = sp->max_recv_size;
- response->sge.lkey = sc->ib.pd->local_dma_lkey;
-
- recv_wr.wr_cqe = &response->cqe;
- recv_wr.next = NULL;
- recv_wr.sg_list = &response->sge;
- recv_wr.num_sge = 1;
-
- rc = ib_post_recv(sc->ib.qp, &recv_wr, NULL);
- if (rc) {
- ib_dma_unmap_single(sc->ib.dev, response->sge.addr,
- response->sge.length, DMA_FROM_DEVICE);
- response->sge.length = 0;
- smbdirect_connection_schedule_disconnect(sc, rc);
- log_rdma_recv(ERR, "ib_post_recv failed rc=%d\n", rc);
- }
-
- return rc;
-}
-
/* Perform SMBD negotiate according to [MS-SMBD] 3.1.5.2 */
static int smbd_negotiate(struct smbdirect_socket *sc)
{
@@ -1107,7 +1065,7 @@ static int smbd_negotiate(struct smbdirect_socket *sc)
sc->status = SMBDIRECT_SOCKET_NEGOTIATE_RUNNING;
sc->recv_io.expected = SMBDIRECT_EXPECT_NEGOTIATE_REP;
- rc = smbd_post_recv(sc, response);
+ rc = smbdirect_connection_post_recv_io(response);
log_rdma_event(INFO, "smbd_post_recv rc=%d iov.addr=0x%llx iov.length=%u iov.lkey=0x%x\n",
rc, response->sge.addr,
response->sge.length, response->sge.lkey);
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 075/127] smb: client: make use of smbdirect_connection_recv_io_refill_work()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (73 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 074/127] smb: client: make use of smbdirect_connection_post_recv_io() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 076/127] smb: client: make use of functions from smbdirect_mr.c Stefan Metzmacher
` (52 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
Steve French
This is basically a copy of smbd_post_send_credits(), but
there are several improvements compared to the existing function:
We calculate the number of missing posted buffers by getting the
difference between recv_io.credits.target and recv_io.posted.count.
Instead of the difference between recv_io.credits.target
and recv_io.credits.count, because recv_io.credits.count is
only updated once a message is send to the peer.
It was not really a problem before, because we have
a fixed number smbdirect_recv_io buffers, so the
loop terminated when smbdirect_connection_get_recv_io()
returns NULL.
But using recv_io.posted.count makes it easier to
understand.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 41 +--------------------------------------
1 file changed, 1 insertion(+), 40 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 9dfee81396c7..41149203e4ff 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -380,45 +380,6 @@ static bool process_negotiation_response(
return true;
}
-static void smbd_post_send_credits(struct work_struct *work)
-{
- int rc;
- struct smbdirect_recv_io *response;
- struct smbdirect_socket *sc =
- container_of(work, struct smbdirect_socket, recv_io.posted.refill_work);
-
- if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
- return;
- }
-
- if (sc->recv_io.credits.target >
- atomic_read(&sc->recv_io.credits.count)) {
- while (true) {
- response = smbdirect_connection_get_recv_io(sc);
- if (!response)
- break;
-
- response->first_segment = false;
- rc = smbdirect_connection_post_recv_io(response);
- if (rc) {
- log_rdma_recv(ERR,
- "post_recv failed rc=%d\n", rc);
- smbdirect_connection_put_recv_io(response);
- break;
- }
-
- atomic_inc(&sc->recv_io.posted.count);
- }
- }
-
- /* Promptly send an immediate packet as defined in [MS-SMBD] 3.1.1.1 */
- if (atomic_read(&sc->recv_io.credits.count) <
- sc->recv_io.credits.target - 1) {
- log_keep_alive(INFO, "schedule send of an empty message\n");
- queue_work(sc->workqueue, &sc->idle.immediate_work);
- }
-}
-
/* Called from softirq, when recv is done */
static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
{
@@ -1361,7 +1322,7 @@ static struct smbd_connection *_smbd_get_connection(
mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
msecs_to_jiffies(sp->negotiate_timeout_msec));
- INIT_WORK(&sc->recv_io.posted.refill_work, smbd_post_send_credits);
+ INIT_WORK(&sc->recv_io.posted.refill_work, smbdirect_connection_recv_io_refill_work);
rc = smbd_negotiate(sc);
if (rc) {
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 076/127] smb: client: make use of functions from smbdirect_mr.c
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (74 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 075/127] smb: client: make use of smbdirect_connection_recv_io_refill_work() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 077/127] smb: client: make use of smbdirect_connection_destroy_sync() Stefan Metzmacher
` (51 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
The copied code only got new names, some indentation/formatting changes,
some variable names are changed too.
They also only use struct smbdirect_socket instead of
struct smbd_connection.
But the logic is still the same.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 496 +-------------------------------------
1 file changed, 4 insertions(+), 492 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 41149203e4ff..0e393f6ab835 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -25,9 +25,6 @@ const struct smbdirect_socket_parameters *smbd_get_parameters(struct smbd_connec
static int smbd_post_send_empty(struct smbdirect_socket *sc);
-static void destroy_mr_list(struct smbdirect_socket *sc);
-static int allocate_mr_list(struct smbdirect_socket *sc);
-
/* Port numbers for SMBD transport */
#define SMB_PORT 445
#define SMBD_PORT 5445
@@ -1137,7 +1134,7 @@ void smbd_destroy(struct TCP_Server_Info *server)
sc->recv_io.reassembly.data_length = 0;
log_rdma_event(INFO, "freeing mr list\n");
- destroy_mr_list(sc);
+ smbdirect_connection_destroy_mr_list(sc);
log_rdma_event(INFO, "destroying qp\n");
smbdirect_connection_destroy_qp(sc);
@@ -1330,7 +1327,7 @@ static struct smbd_connection *_smbd_get_connection(
goto negotiation_failed;
}
- rc = allocate_mr_list(sc);
+ rc = smbdirect_connection_create_mr_list(sc);
if (rc) {
log_rdma_mr(ERR, "memory registration allocation failed\n");
goto allocate_mr_failed;
@@ -1633,292 +1630,6 @@ int smbd_send(struct TCP_Server_Info *server,
return rc;
}
-static void register_mr_done(struct ib_cq *cq, struct ib_wc *wc)
-{
- struct smbdirect_mr_io *mr =
- container_of(wc->wr_cqe, struct smbdirect_mr_io, cqe);
- struct smbdirect_socket *sc = mr->socket;
-
- if (wc->status) {
- log_rdma_mr(ERR, "status=%d\n", wc->status);
- smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
- }
-}
-
-/*
- * The work queue function that recovers MRs
- * We need to call ib_dereg_mr() and ib_alloc_mr() before this MR can be used
- * again. Both calls are slow, so finish them in a workqueue. This will not
- * block I/O path.
- * There is one workqueue that recovers MRs, there is no need to lock as the
- * I/O requests calling smbd_register_mr will never update the links in the
- * mr_list.
- */
-static void smbd_mr_recovery_work(struct work_struct *work)
-{
- struct smbdirect_socket *sc =
- container_of(work, struct smbdirect_socket, mr_io.recovery_work);
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- struct smbdirect_mr_io *smbdirect_mr;
- int rc;
-
- list_for_each_entry(smbdirect_mr, &sc->mr_io.all.list, list) {
- if (smbdirect_mr->state == SMBDIRECT_MR_ERROR) {
-
- /* recover this MR entry */
- rc = ib_dereg_mr(smbdirect_mr->mr);
- if (rc) {
- log_rdma_mr(ERR,
- "ib_dereg_mr failed rc=%x\n",
- rc);
- smbdirect_connection_schedule_disconnect(sc, rc);
- continue;
- }
-
- smbdirect_mr->mr = ib_alloc_mr(
- sc->ib.pd, sc->mr_io.type,
- sp->max_frmr_depth);
- if (IS_ERR(smbdirect_mr->mr)) {
- rc = PTR_ERR(smbdirect_mr->mr);
- log_rdma_mr(ERR, "ib_alloc_mr failed mr_type=%x max_frmr_depth=%x\n",
- sc->mr_io.type,
- sp->max_frmr_depth);
- smbdirect_connection_schedule_disconnect(sc, rc);
- continue;
- }
- } else
- /* This MR is being used, don't recover it */
- continue;
-
- smbdirect_mr->state = SMBDIRECT_MR_READY;
-
- /* smbdirect_mr->state is updated by this function
- * and is read and updated by I/O issuing CPUs trying
- * to get a MR, the call to atomic_inc_return
- * implicates a memory barrier and guarantees this
- * value is updated before waking up any calls to
- * get_mr() from the I/O issuing CPUs
- */
- if (atomic_inc_return(&sc->mr_io.ready.count) == 1)
- wake_up(&sc->mr_io.ready.wait_queue);
- }
-}
-
-static void smbd_mr_disable_locked(struct smbdirect_mr_io *mr)
-{
- struct smbdirect_socket *sc = mr->socket;
-
- lockdep_assert_held(&mr->mutex);
-
- if (mr->state == SMBDIRECT_MR_DISABLED)
- return;
-
- if (mr->mr)
- ib_dereg_mr(mr->mr);
- if (mr->sgt.nents)
- ib_dma_unmap_sg(sc->ib.dev, mr->sgt.sgl, mr->sgt.nents, mr->dir);
- kfree(mr->sgt.sgl);
-
- mr->mr = NULL;
- mr->sgt.sgl = NULL;
- mr->sgt.nents = 0;
-
- mr->state = SMBDIRECT_MR_DISABLED;
-}
-
-static void smbd_mr_free_locked(struct kref *kref)
-{
- struct smbdirect_mr_io *mr =
- container_of(kref, struct smbdirect_mr_io, kref);
-
- lockdep_assert_held(&mr->mutex);
-
- /*
- * smbd_mr_disable_locked() should already be called!
- */
- if (WARN_ON_ONCE(mr->state != SMBDIRECT_MR_DISABLED))
- smbd_mr_disable_locked(mr);
-
- mutex_unlock(&mr->mutex);
- mutex_destroy(&mr->mutex);
- kfree(mr);
-}
-
-static void destroy_mr_list(struct smbdirect_socket *sc)
-{
- struct smbdirect_mr_io *mr, *tmp;
- LIST_HEAD(all_list);
- unsigned long flags;
-
- disable_work_sync(&sc->mr_io.recovery_work);
-
- spin_lock_irqsave(&sc->mr_io.all.lock, flags);
- list_splice_tail_init(&sc->mr_io.all.list, &all_list);
- spin_unlock_irqrestore(&sc->mr_io.all.lock, flags);
-
- list_for_each_entry_safe(mr, tmp, &all_list, list) {
- mutex_lock(&mr->mutex);
-
- smbd_mr_disable_locked(mr);
- list_del(&mr->list);
- mr->socket = NULL;
-
- /*
- * No kref_put_mutex() as it's already locked.
- *
- * If smbd_mr_free_locked() is called
- * and the mutex is unlocked and mr is gone,
- * in that case kref_put() returned 1.
- *
- * If kref_put() returned 0 we know that
- * smbd_mr_free_locked() didn't
- * run. Not by us nor by anyone else, as we
- * still hold the mutex, so we need to unlock.
- *
- * If the mr is still registered it will
- * be dangling (detached from the connection
- * waiting for smbd_deregister_mr() to be
- * called in order to free the memory.
- */
- if (!kref_put(&mr->kref, smbd_mr_free_locked))
- mutex_unlock(&mr->mutex);
- }
-}
-
-/*
- * Allocate MRs used for RDMA read/write
- * The number of MRs will not exceed hardware capability in responder_resources
- * All MRs are kept in mr_list. The MR can be recovered after it's used
- * Recovery is done in smbd_mr_recovery_work. The content of list entry changes
- * as MRs are used and recovered for I/O, but the list links will not change
- */
-static int allocate_mr_list(struct smbdirect_socket *sc)
-{
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- struct smbdirect_mr_io *mr;
- int ret;
- u32 i;
-
- if (sp->responder_resources == 0) {
- log_rdma_mr(ERR, "responder_resources negotiated as 0\n");
- return -EINVAL;
- }
-
- /* Allocate more MRs (2x) than hardware responder_resources */
- for (i = 0; i < sp->responder_resources * 2; i++) {
- mr = kzalloc(sizeof(*mr), GFP_KERNEL);
- if (!mr) {
- ret = -ENOMEM;
- goto kzalloc_mr_failed;
- }
-
- kref_init(&mr->kref);
- mutex_init(&mr->mutex);
-
- mr->mr = ib_alloc_mr(sc->ib.pd,
- sc->mr_io.type,
- sp->max_frmr_depth);
- if (IS_ERR(mr->mr)) {
- ret = PTR_ERR(mr->mr);
- log_rdma_mr(ERR, "ib_alloc_mr failed mr_type=%x max_frmr_depth=%x\n",
- sc->mr_io.type, sp->max_frmr_depth);
- goto ib_alloc_mr_failed;
- }
-
- mr->sgt.sgl = kcalloc(sp->max_frmr_depth,
- sizeof(struct scatterlist),
- GFP_KERNEL);
- if (!mr->sgt.sgl) {
- ret = -ENOMEM;
- log_rdma_mr(ERR, "failed to allocate sgl\n");
- goto kcalloc_sgl_failed;
- }
- mr->state = SMBDIRECT_MR_READY;
- mr->socket = sc;
-
- list_add_tail(&mr->list, &sc->mr_io.all.list);
- atomic_inc(&sc->mr_io.ready.count);
- }
-
- INIT_WORK(&sc->mr_io.recovery_work, smbd_mr_recovery_work);
-
- return 0;
-
-kcalloc_sgl_failed:
- ib_dereg_mr(mr->mr);
-ib_alloc_mr_failed:
- mutex_destroy(&mr->mutex);
- kfree(mr);
-kzalloc_mr_failed:
- destroy_mr_list(sc);
- return ret;
-}
-
-/*
- * Get a MR from mr_list. This function waits until there is at least one
- * MR available in the list. It may access the list while the
- * smbd_mr_recovery_work is recovering the MR list. This doesn't need a lock
- * as they never modify the same places. However, there may be several CPUs
- * issuing I/O trying to get MR at the same time, mr_list_lock is used to
- * protect this situation.
- */
-static struct smbdirect_mr_io *get_mr(struct smbdirect_socket *sc)
-{
- struct smbdirect_mr_io *ret;
- unsigned long flags;
- int rc;
-again:
- rc = wait_event_interruptible(sc->mr_io.ready.wait_queue,
- atomic_read(&sc->mr_io.ready.count) ||
- sc->status != SMBDIRECT_SOCKET_CONNECTED);
- if (rc) {
- log_rdma_mr(ERR, "wait_event_interruptible rc=%x\n", rc);
- return NULL;
- }
-
- if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
- log_rdma_mr(ERR, "sc->status=%x\n", sc->status);
- return NULL;
- }
-
- spin_lock_irqsave(&sc->mr_io.all.lock, flags);
- list_for_each_entry(ret, &sc->mr_io.all.list, list) {
- if (ret->state == SMBDIRECT_MR_READY) {
- ret->state = SMBDIRECT_MR_REGISTERED;
- kref_get(&ret->kref);
- spin_unlock_irqrestore(&sc->mr_io.all.lock, flags);
- atomic_dec(&sc->mr_io.ready.count);
- atomic_inc(&sc->mr_io.used.count);
- return ret;
- }
- }
-
- spin_unlock_irqrestore(&sc->mr_io.all.lock, flags);
- /*
- * It is possible that we could fail to get MR because other processes may
- * try to acquire a MR at the same time. If this is the case, retry it.
- */
- goto again;
-}
-
-/*
- * Transcribe the pages from an iterator into an MR scatterlist.
- */
-static int smbd_iter_to_mr(struct iov_iter *iter,
- struct sg_table *sgt,
- unsigned int max_sg)
-{
- int ret;
-
- memset(sgt->sgl, 0, max_sg * sizeof(struct scatterlist));
-
- ret = extract_iter_to_sg(iter, iov_iter_count(iter), sgt, max_sg, 0);
- WARN_ON(ret < 0);
- if (sgt->nents > 0)
- sg_mark_end(&sgt->sgl[sgt->nents - 1]);
- return ret;
-}
-
/*
* Register memory for RDMA read/write
* iter: the buffer to register memory with
@@ -1931,131 +1642,8 @@ struct smbdirect_mr_io *smbd_register_mr(struct smbd_connection *info,
bool writing, bool need_invalidate)
{
struct smbdirect_socket *sc = &info->socket;
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- struct smbdirect_mr_io *mr;
- int rc, num_pages;
- struct ib_reg_wr *reg_wr;
-
- num_pages = iov_iter_npages(iter, sp->max_frmr_depth + 1);
- if (num_pages > sp->max_frmr_depth) {
- log_rdma_mr(ERR, "num_pages=%d max_frmr_depth=%d\n",
- num_pages, sp->max_frmr_depth);
- WARN_ON_ONCE(1);
- return NULL;
- }
-
- mr = get_mr(sc);
- if (!mr) {
- log_rdma_mr(ERR, "get_mr returning NULL\n");
- return NULL;
- }
-
- mutex_lock(&mr->mutex);
-
- mr->dir = writing ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
- mr->need_invalidate = need_invalidate;
- mr->sgt.nents = 0;
- mr->sgt.orig_nents = 0;
-
- log_rdma_mr(INFO, "num_pages=0x%x count=0x%zx depth=%u\n",
- num_pages, iov_iter_count(iter), sp->max_frmr_depth);
- smbd_iter_to_mr(iter, &mr->sgt, sp->max_frmr_depth);
-
- rc = ib_dma_map_sg(sc->ib.dev, mr->sgt.sgl, mr->sgt.nents, mr->dir);
- if (!rc) {
- log_rdma_mr(ERR, "ib_dma_map_sg num_pages=%x dir=%x rc=%x\n",
- num_pages, mr->dir, rc);
- goto dma_map_error;
- }
-
- rc = ib_map_mr_sg(mr->mr, mr->sgt.sgl, mr->sgt.nents, NULL, PAGE_SIZE);
- if (rc != mr->sgt.nents) {
- log_rdma_mr(ERR,
- "ib_map_mr_sg failed rc = %d nents = %x\n",
- rc, mr->sgt.nents);
- goto map_mr_error;
- }
-
- ib_update_fast_reg_key(mr->mr, ib_inc_rkey(mr->mr->rkey));
- reg_wr = &mr->wr;
- reg_wr->wr.opcode = IB_WR_REG_MR;
- mr->cqe.done = register_mr_done;
- reg_wr->wr.wr_cqe = &mr->cqe;
- reg_wr->wr.num_sge = 0;
- reg_wr->wr.send_flags = IB_SEND_SIGNALED;
- reg_wr->mr = mr->mr;
- reg_wr->key = mr->mr->rkey;
- reg_wr->access = writing ?
- IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE :
- IB_ACCESS_REMOTE_READ;
-
- /*
- * There is no need for waiting for complemtion on ib_post_send
- * on IB_WR_REG_MR. Hardware enforces a barrier and order of execution
- * on the next ib_post_send when we actually send I/O to remote peer
- */
- rc = ib_post_send(sc->ib.qp, ®_wr->wr, NULL);
- if (!rc) {
- /*
- * get_mr() gave us a reference
- * via kref_get(&mr->kref), we keep that and let
- * the caller use smbd_deregister_mr()
- * to remove it again.
- */
- mutex_unlock(&mr->mutex);
- return mr;
- }
-
- log_rdma_mr(ERR, "ib_post_send failed rc=%x reg_wr->key=%x\n",
- rc, reg_wr->key);
-
- /* If all failed, attempt to recover this MR by setting it SMBDIRECT_MR_ERROR*/
-map_mr_error:
- ib_dma_unmap_sg(sc->ib.dev, mr->sgt.sgl, mr->sgt.nents, mr->dir);
-
-dma_map_error:
- mr->sgt.nents = 0;
- mr->state = SMBDIRECT_MR_ERROR;
- if (atomic_dec_and_test(&sc->mr_io.used.count))
- wake_up(&sc->mr_io.cleanup.wait_queue);
-
- smbdirect_connection_schedule_disconnect(sc, rc);
- /*
- * get_mr() gave us a reference
- * via kref_get(&mr->kref), we need to remove it again
- * on error.
- *
- * No kref_put_mutex() as it's already locked.
- *
- * If smbd_mr_free_locked() is called
- * and the mutex is unlocked and mr is gone,
- * in that case kref_put() returned 1.
- *
- * If kref_put() returned 0 we know that
- * smbd_mr_free_locked() didn't
- * run. Not by us nor by anyone else, as we
- * still hold the mutex, so we need to unlock.
- */
- if (!kref_put(&mr->kref, smbd_mr_free_locked))
- mutex_unlock(&mr->mutex);
-
- return NULL;
-}
-
-static void local_inv_done(struct ib_cq *cq, struct ib_wc *wc)
-{
- struct smbdirect_mr_io *smbdirect_mr;
- struct ib_cqe *cqe;
-
- cqe = wc->wr_cqe;
- smbdirect_mr = container_of(cqe, struct smbdirect_mr_io, cqe);
- smbdirect_mr->state = SMBDIRECT_MR_INVALIDATED;
- if (wc->status != IB_WC_SUCCESS) {
- log_rdma_mr(ERR, "invalidate failed status=%x\n", wc->status);
- smbdirect_mr->state = SMBDIRECT_MR_ERROR;
- }
- complete(&smbdirect_mr->invalidate_done);
+ return smbdirect_connection_register_mr_io(sc, iter, writing, need_invalidate);
}
/*
@@ -2066,81 +1654,5 @@ static void local_inv_done(struct ib_cq *cq, struct ib_wc *wc)
*/
void smbd_deregister_mr(struct smbdirect_mr_io *mr)
{
- struct smbdirect_socket *sc = mr->socket;
-
- mutex_lock(&mr->mutex);
- if (mr->state == SMBDIRECT_MR_DISABLED)
- goto put_kref;
-
- if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
- smbd_mr_disable_locked(mr);
- goto put_kref;
- }
-
- if (mr->need_invalidate) {
- struct ib_send_wr *wr = &mr->inv_wr;
- int rc;
-
- /* Need to finish local invalidation before returning */
- wr->opcode = IB_WR_LOCAL_INV;
- mr->cqe.done = local_inv_done;
- wr->wr_cqe = &mr->cqe;
- wr->num_sge = 0;
- wr->ex.invalidate_rkey = mr->mr->rkey;
- wr->send_flags = IB_SEND_SIGNALED;
-
- init_completion(&mr->invalidate_done);
- rc = ib_post_send(sc->ib.qp, wr, NULL);
- if (rc) {
- log_rdma_mr(ERR, "ib_post_send failed rc=%x\n", rc);
- smbd_mr_disable_locked(mr);
- smbdirect_connection_schedule_disconnect(sc, rc);
- goto done;
- }
- wait_for_completion(&mr->invalidate_done);
- mr->need_invalidate = false;
- } else
- /*
- * For remote invalidation, just set it to SMBDIRECT_MR_INVALIDATED
- * and defer to mr_recovery_work to recover the MR for next use
- */
- mr->state = SMBDIRECT_MR_INVALIDATED;
-
- if (mr->sgt.nents) {
- ib_dma_unmap_sg(sc->ib.dev, mr->sgt.sgl, mr->sgt.nents, mr->dir);
- mr->sgt.nents = 0;
- }
-
- if (mr->state == SMBDIRECT_MR_INVALIDATED) {
- mr->state = SMBDIRECT_MR_READY;
- if (atomic_inc_return(&sc->mr_io.ready.count) == 1)
- wake_up(&sc->mr_io.ready.wait_queue);
- } else
- /*
- * Schedule the work to do MR recovery for future I/Os MR
- * recovery is slow and don't want it to block current I/O
- */
- queue_work(sc->workqueue, &sc->mr_io.recovery_work);
-
-done:
- if (atomic_dec_and_test(&sc->mr_io.used.count))
- wake_up(&sc->mr_io.cleanup.wait_queue);
-
-put_kref:
- /*
- * No kref_put_mutex() as it's already locked.
- *
- * If smbd_mr_free_locked() is called
- * and the mutex is unlocked and mr is gone,
- * in that case kref_put() returned 1.
- *
- * If kref_put() returned 0 we know that
- * smbd_mr_free_locked() didn't
- * run. Not by us nor by anyone else, as we
- * still hold the mutex, so we need to unlock
- * and keep the mr in SMBDIRECT_MR_READY or
- * SMBDIRECT_MR_ERROR state.
- */
- if (!kref_put(&mr->kref, smbd_mr_free_locked))
- mutex_unlock(&mr->mutex);
+ smbdirect_connection_deregister_mr_io(mr);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 077/127] smb: client: make use of smbdirect_connection_destroy_sync()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (75 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 076/127] smb: client: make use of functions from smbdirect_mr.c Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 078/127] smb: client: make use of smbdirect_connection_recvmsg() Stefan Metzmacher
` (50 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This is basically the same logic as before, but we now
use common code, which will also be used by the server soon.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 63 +--------------------------------------
1 file changed, 1 insertion(+), 62 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 0e393f6ab835..7d786d119184 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -1076,8 +1076,6 @@ void smbd_destroy(struct TCP_Server_Info *server)
{
struct smbd_connection *info = server->smbd_conn;
struct smbdirect_socket *sc;
- struct smbdirect_recv_io *response;
- unsigned long flags;
if (!info) {
log_rdma_event(INFO, "rdma session already destroyed\n");
@@ -1085,68 +1083,9 @@ void smbd_destroy(struct TCP_Server_Info *server)
}
sc = &info->socket;
- log_rdma_event(INFO, "cancelling and disable disconnect_work\n");
- disable_work_sync(&sc->disconnect_work);
-
- log_rdma_event(INFO, "destroying rdma session\n");
- if (sc->status < SMBDIRECT_SOCKET_DISCONNECTING)
- smbdirect_connection_disconnect_work(&sc->disconnect_work);
- if (sc->status < SMBDIRECT_SOCKET_DISCONNECTED) {
- log_rdma_event(INFO, "wait for transport being disconnected\n");
- wait_event(sc->status_wait, sc->status == SMBDIRECT_SOCKET_DISCONNECTED);
- log_rdma_event(INFO, "waited for transport being disconnected\n");
- }
-
- /*
- * Wake up all waiters in all wait queues
- * in order to notice the broken connection.
- *
- * Most likely this was already called via
- * smbdirect_connection_disconnect_work(), but call it again...
- */
- smbdirect_connection_wake_up_all(sc);
-
- log_rdma_event(INFO, "cancelling recv_io.posted.refill_work\n");
- disable_work_sync(&sc->recv_io.posted.refill_work);
-
- log_rdma_event(INFO, "drain qp\n");
- ib_drain_qp(sc->ib.qp);
-
- log_rdma_event(INFO, "cancelling idle timer\n");
- disable_delayed_work_sync(&sc->idle.timer_work);
- log_rdma_event(INFO, "cancelling send immediate work\n");
- disable_work_sync(&sc->idle.immediate_work);
-
- /* It's not possible for upper layer to get to reassembly */
- log_rdma_event(INFO, "drain the reassembly queue\n");
- do {
- spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags);
- response = smbdirect_connection_reassembly_first_recv_io(sc);
- if (response) {
- list_del(&response->list);
- spin_unlock_irqrestore(
- &sc->recv_io.reassembly.lock, flags);
- smbdirect_connection_put_recv_io(response);
- } else
- spin_unlock_irqrestore(
- &sc->recv_io.reassembly.lock, flags);
- } while (response);
- sc->recv_io.reassembly.data_length = 0;
-
- log_rdma_event(INFO, "freeing mr list\n");
- smbdirect_connection_destroy_mr_list(sc);
-
- log_rdma_event(INFO, "destroying qp\n");
- smbdirect_connection_destroy_qp(sc);
- rdma_destroy_id(sc->rdma.cm_id);
-
- /* free mempools */
- smbdirect_connection_destroy_mem_pools(sc);
-
- sc->status = SMBDIRECT_SOCKET_DESTROYED;
+ smbdirect_connection_destroy_sync(sc);
destroy_workqueue(sc->workqueue);
- log_rdma_event(INFO, "rdma session destroyed\n");
kfree(info);
server->smbd_conn = NULL;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 078/127] smb: client: make use of smbdirect_connection_recvmsg()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (76 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 077/127] smb: client: make use of smbdirect_connection_destroy_sync() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 079/127] smb: client: let smbd_post_send() make use of request->wr Stefan Metzmacher
` (49 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This is basically the same as it was copied before...
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 131 +-------------------------------------
1 file changed, 1 insertion(+), 130 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 7d786d119184..2860f9c5502c 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -1347,137 +1347,8 @@ struct smbd_connection *smbd_get_connection(
int smbd_recv(struct smbd_connection *info, struct msghdr *msg)
{
struct smbdirect_socket *sc = &info->socket;
- struct smbdirect_recv_io *response;
- struct smbdirect_data_transfer *data_transfer;
- size_t size = iov_iter_count(&msg->msg_iter);
- int to_copy, to_read, data_read, offset;
- u32 data_length, remaining_data_length, data_offset;
- int rc;
-
- if (WARN_ON_ONCE(iov_iter_rw(&msg->msg_iter) == WRITE))
- return -EINVAL; /* It's a bug in upper layer to get there */
-
-again:
- /*
- * No need to hold the reassembly queue lock all the time as we are
- * the only one reading from the front of the queue. The transport
- * may add more entries to the back of the queue at the same time
- */
- log_read(INFO, "size=%zd sc->recv_io.reassembly.data_length=%d\n", size,
- sc->recv_io.reassembly.data_length);
- if (sc->recv_io.reassembly.data_length >= size) {
- int queue_length;
- int queue_removed = 0;
- unsigned long flags;
-
- /*
- * Need to make sure reassembly_data_length is read before
- * reading reassembly_queue_length and calling
- * smbdirect_connection_reassembly_first_recv_io. This call is lock free
- * as we never read at the end of the queue which are being
- * updated in SOFTIRQ as more data is received
- */
- virt_rmb();
- queue_length = sc->recv_io.reassembly.queue_length;
- data_read = 0;
- to_read = size;
- offset = sc->recv_io.reassembly.first_entry_offset;
- while (data_read < size) {
- response = smbdirect_connection_reassembly_first_recv_io(sc);
- data_transfer = smbdirect_recv_io_payload(response);
- data_length = le32_to_cpu(data_transfer->data_length);
- remaining_data_length =
- le32_to_cpu(
- data_transfer->remaining_data_length);
- data_offset = le32_to_cpu(data_transfer->data_offset);
-
- /*
- * The upper layer expects RFC1002 length at the
- * beginning of the payload. Return it to indicate
- * the total length of the packet. This minimize the
- * change to upper layer packet processing logic. This
- * will be eventually remove when an intermediate
- * transport layer is added
- */
- if (response->first_segment && size == 4) {
- unsigned int rfc1002_len =
- data_length + remaining_data_length;
- __be32 rfc1002_hdr = cpu_to_be32(rfc1002_len);
- if (copy_to_iter(&rfc1002_hdr, sizeof(rfc1002_hdr),
- &msg->msg_iter) != sizeof(rfc1002_hdr))
- return -EFAULT;
- data_read = 4;
- response->first_segment = false;
- log_read(INFO, "returning rfc1002 length %d\n",
- rfc1002_len);
- goto read_rfc1002_done;
- }
-
- to_copy = min_t(int, data_length - offset, to_read);
- if (copy_to_iter((char *)data_transfer + data_offset + offset,
- to_copy, &msg->msg_iter) != to_copy)
- return -EFAULT;
-
- /* move on to the next buffer? */
- if (to_copy == data_length - offset) {
- queue_length--;
- /*
- * No need to lock if we are not at the
- * end of the queue
- */
- if (queue_length)
- list_del(&response->list);
- else {
- spin_lock_irqsave(
- &sc->recv_io.reassembly.lock, flags);
- list_del(&response->list);
- spin_unlock_irqrestore(
- &sc->recv_io.reassembly.lock, flags);
- }
- queue_removed++;
- sc->statistics.dequeue_reassembly_queue++;
- smbdirect_connection_put_recv_io(response);
- offset = 0;
- log_read(INFO, "smbdirect_connection_put_recv_io offset=0\n");
- } else
- offset += to_copy;
-
- to_read -= to_copy;
- data_read += to_copy;
-
- log_read(INFO, "_get_first_reassembly memcpy %d bytes data_transfer_length-offset=%d after that to_read=%d data_read=%d offset=%d\n",
- to_copy, data_length - offset,
- to_read, data_read, offset);
- }
-
- spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags);
- sc->recv_io.reassembly.data_length -= data_read;
- sc->recv_io.reassembly.queue_length -= queue_removed;
- spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags);
-
- sc->recv_io.reassembly.first_entry_offset = offset;
- log_read(INFO, "returning to thread data_read=%d reassembly_data_length=%d first_entry_offset=%d\n",
- data_read, sc->recv_io.reassembly.data_length,
- sc->recv_io.reassembly.first_entry_offset);
-read_rfc1002_done:
- return data_read;
- }
-
- log_read(INFO, "wait_event on more data\n");
- rc = wait_event_interruptible(
- sc->recv_io.reassembly.wait_queue,
- sc->recv_io.reassembly.data_length >= size ||
- sc->status != SMBDIRECT_SOCKET_CONNECTED);
- /* Don't return any data if interrupted */
- if (rc)
- return rc;
-
- if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
- log_read(ERR, "disconnected\n");
- return -ECONNABORTED;
- }
- goto again;
+ return smbdirect_connection_recvmsg(sc, msg, 0);
}
/*
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 079/127] smb: client: let smbd_post_send() make use of request->wr
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (77 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 078/127] smb: client: make use of smbdirect_connection_recvmsg() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 080/127] smb: client: make use of smbdirect_connection_grant_recv_credits() Stefan Metzmacher
` (48 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
We don't need a stack variable in addition.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 2860f9c5502c..e2f93d4af0a7 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -786,7 +786,6 @@ static int manage_keep_alive_before_sending(struct smbdirect_socket *sc)
static int smbd_post_send(struct smbdirect_socket *sc,
struct smbdirect_send_io *request)
{
- struct ib_send_wr send_wr;
int rc, i;
for (i = 0; i < request->num_sge; i++) {
@@ -802,14 +801,14 @@ static int smbd_post_send(struct smbdirect_socket *sc,
request->cqe.done = smbdirect_connection_send_io_done;
- send_wr.next = NULL;
- send_wr.wr_cqe = &request->cqe;
- send_wr.sg_list = request->sge;
- send_wr.num_sge = request->num_sge;
- send_wr.opcode = IB_WR_SEND;
- send_wr.send_flags = IB_SEND_SIGNALED;
+ request->wr.next = NULL;
+ request->wr.wr_cqe = &request->cqe;
+ request->wr.sg_list = request->sge;
+ request->wr.num_sge = request->num_sge;
+ request->wr.opcode = IB_WR_SEND;
+ request->wr.send_flags = IB_SEND_SIGNALED;
- rc = ib_post_send(sc->ib.qp, &send_wr, NULL);
+ rc = ib_post_send(sc->ib.qp, &request->wr, NULL);
if (rc) {
log_rdma_send(ERR, "ib_post_send failed rc=%d\n", rc);
smbdirect_connection_schedule_disconnect(sc, rc);
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 080/127] smb: client: make use of smbdirect_connection_grant_recv_credits()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (78 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 079/127] smb: client: let smbd_post_send() make use of request->wr Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 081/127] smb: client: make use of smbdirect_connection_request_keep_alive() Stefan Metzmacher
` (47 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This already calls atomic_add(new_credits, &sc->recv_io.credits.count),
so there's no need to do it in the caller anymore.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 31 ++-----------------------------
1 file changed, 2 insertions(+), 29 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index e2f93d4af0a7..cb1e7dee9be7 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -730,32 +730,6 @@ static int smbd_post_send_negotiate_req(struct smbdirect_socket *sc)
return rc;
}
-/*
- * Extend the credits to remote peer
- * This implements [MS-SMBD] 3.1.5.9
- * The idea is that we should extend credits to remote peer as quickly as
- * it's allowed, to maintain data flow. We allocate as much receive
- * buffer as possible, and extend the receive credits to remote peer
- * return value: the new credtis being granted.
- */
-static int manage_credits_prior_sending(struct smbdirect_socket *sc)
-{
- int new_credits;
-
- if (atomic_read(&sc->recv_io.credits.count) >= sc->recv_io.credits.target)
- return 0;
-
- new_credits = atomic_read(&sc->recv_io.posted.count);
- if (new_credits == 0)
- return 0;
-
- new_credits -= atomic_read(&sc->recv_io.credits.count);
- if (new_credits <= 0)
- return 0;
-
- return new_credits;
-}
-
/*
* Check if we need to send a KEEP_ALIVE message
* The idle connection timer triggers a KEEP_ALIVE message when expires
@@ -828,7 +802,7 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
int data_length;
struct smbdirect_send_io *request;
struct smbdirect_data_transfer *packet;
- int new_credits = 0;
+ u16 new_credits = 0;
wait_lcredit:
/* Wait for local send credits */
@@ -920,8 +894,7 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
/* Fill in the packet header */
packet->credits_requested = cpu_to_le16(sp->send_credit_target);
- new_credits = manage_credits_prior_sending(sc);
- atomic_add(new_credits, &sc->recv_io.credits.count);
+ new_credits = smbdirect_connection_grant_recv_credits(sc);
packet->credits_granted = cpu_to_le16(new_credits);
packet->flags = 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 081/127] smb: client: make use of smbdirect_connection_request_keep_alive()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (79 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 080/127] smb: client: make use of smbdirect_connection_grant_recv_credits() Stefan Metzmacher
@ 2025-10-29 13:20 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 082/127] smb: client: change smbd_post_send_empty() to void return Stefan Metzmacher
` (46 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:20 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This will help to share more common code soon.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 28 +---------------------------
1 file changed, 1 insertion(+), 27 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index cb1e7dee9be7..ef2f957d0e86 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -730,32 +730,6 @@ static int smbd_post_send_negotiate_req(struct smbdirect_socket *sc)
return rc;
}
-/*
- * Check if we need to send a KEEP_ALIVE message
- * The idle connection timer triggers a KEEP_ALIVE message when expires
- * SMBDIRECT_FLAG_RESPONSE_REQUESTED is set in the message flag to have peer send
- * back a response.
- * return value:
- * 1 if SMBDIRECT_FLAG_RESPONSE_REQUESTED needs to be set
- * 0: otherwise
- */
-static int manage_keep_alive_before_sending(struct smbdirect_socket *sc)
-{
- struct smbdirect_socket_parameters *sp = &sc->parameters;
-
- if (sc->idle.keepalive == SMBDIRECT_KEEPALIVE_PENDING) {
- sc->idle.keepalive = SMBDIRECT_KEEPALIVE_SENT;
- /*
- * Now use the keepalive timeout (instead of keepalive interval)
- * in order to wait for a response
- */
- mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
- msecs_to_jiffies(sp->keepalive_timeout_msec));
- return 1;
- }
- return 0;
-}
-
/* Post the send request */
static int smbd_post_send(struct smbdirect_socket *sc,
struct smbdirect_send_io *request)
@@ -898,7 +872,7 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
packet->credits_granted = cpu_to_le16(new_credits);
packet->flags = 0;
- if (manage_keep_alive_before_sending(sc))
+ if (smbdirect_connection_request_keep_alive(sc))
packet->flags |= cpu_to_le16(SMBDIRECT_FLAG_RESPONSE_REQUESTED);
packet->reserved = 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 082/127] smb: client: change smbd_post_send_empty() to void return
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (80 preceding siblings ...)
2025-10-29 13:20 ` [PATCH v2 081/127] smb: client: make use of smbdirect_connection_request_keep_alive() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 083/127] smb: client: let smbd_post_send_iter() get remaining_length and return data_length Stefan Metzmacher
` (45 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
The caller doesn't check, so we better call
smbdirect_connection_schedule_disconnect() to handle the error.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index ef2f957d0e86..b94fa3bec5c5 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -23,8 +23,6 @@ const struct smbdirect_socket_parameters *smbd_get_parameters(struct smbd_connec
return &sc->parameters;
}
-static int smbd_post_send_empty(struct smbdirect_socket *sc);
-
/* Port numbers for SMBD transport */
#define SMB_PORT 445
#define SMBD_PORT 5445
@@ -929,12 +927,17 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
* Empty message is used to extend credits to peer to for keep live
* while there is no upper layer payload to send at the time
*/
-static int smbd_post_send_empty(struct smbdirect_socket *sc)
+static void smbd_post_send_empty(struct smbdirect_socket *sc)
{
int remaining_data_length = 0;
+ int ret;
sc->statistics.send_empty++;
- return smbd_post_send_iter(sc, NULL, &remaining_data_length);
+ ret = smbd_post_send_iter(sc, NULL, &remaining_data_length);
+ if (ret < 0) {
+ log_rdma_send(ERR, "smbd_post_send_iter failed ret=%d\n", ret);
+ smbdirect_connection_schedule_disconnect(sc, ret);
+ }
}
static int smbd_post_send_full_iter(struct smbdirect_socket *sc,
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 083/127] smb: client: let smbd_post_send_iter() get remaining_length and return data_length
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (81 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 082/127] smb: client: change smbd_post_send_empty() to void return Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 084/127] smb: client: let smbd_post_send_full_iter() " Stefan Metzmacher
` (44 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This lets the logic be like smb_direct_post_send_data(), so
we can share common code in the next steps.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 35 +++++++++++++++++++++--------------
1 file changed, 21 insertions(+), 14 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index b94fa3bec5c5..34404a1d3e58 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -766,7 +766,7 @@ static int smbd_post_send(struct smbdirect_socket *sc,
static int smbd_post_send_iter(struct smbdirect_socket *sc,
struct iov_iter *iter,
- int *_remaining_data_length)
+ u32 remaining_data_length)
{
struct smbdirect_socket_parameters *sp = &sc->parameters;
int rc;
@@ -776,6 +776,18 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
struct smbdirect_data_transfer *packet;
u16 new_credits = 0;
+ if (iter) {
+ header_length = sizeof(struct smbdirect_data_transfer);
+ if (WARN_ON_ONCE(remaining_data_length == 0 ||
+ iov_iter_count(iter) > remaining_data_length))
+ return -EINVAL;
+ } else {
+ /* If this is a packet without payload, don't send padding */
+ header_length = offsetof(struct smbdirect_data_transfer, padding);
+ if (WARN_ON_ONCE(remaining_data_length))
+ return -EINVAL;
+ }
+
wait_lcredit:
/* Wait for local send credits */
rc = wait_event_interruptible(sc->send_io.lcredits.wait_queue,
@@ -820,12 +832,6 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
memset(request->sge, 0, sizeof(request->sge));
- /* Map the packet to DMA */
- header_length = sizeof(struct smbdirect_data_transfer);
- /* If this is a packet without payload, don't send padding */
- if (!iter)
- header_length = offsetof(struct smbdirect_data_transfer, padding);
-
packet = smbdirect_send_io_payload(request);
request->sge[0].addr = ib_dma_map_single(sc->ib.dev,
(void *)packet,
@@ -850,7 +856,7 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
.local_dma_lkey = sc->ib.pd->local_dma_lkey,
.direction = DMA_TO_DEVICE,
};
- size_t payload_len = umin(*_remaining_data_length,
+ size_t payload_len = umin(iov_iter_count(iter),
sp->max_send_size - sizeof(*packet));
rc = smbdirect_map_sges_from_iter(iter, payload_len, &extract);
@@ -858,7 +864,7 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
goto err_dma;
data_length = rc;
request->num_sge = extract.num_sge;
- *_remaining_data_length -= data_length;
+ remaining_data_length -= data_length;
} else {
data_length = 0;
}
@@ -879,7 +885,7 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
else
packet->data_offset = cpu_to_le32(24);
packet->data_length = cpu_to_le32(data_length);
- packet->remaining_data_length = cpu_to_le32(*_remaining_data_length);
+ packet->remaining_data_length = cpu_to_le32(remaining_data_length);
packet->padding = 0;
log_outgoing(INFO, "credits_requested=%d credits_granted=%d data_offset=%d data_length=%d remaining_data_length=%d\n",
@@ -897,7 +903,7 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
rc = smbd_post_send(sc, request);
if (!rc)
- return 0;
+ return data_length;
if (atomic_dec_and_test(&sc->send_io.pending.count))
wake_up(&sc->send_io.pending.zero_wait_queue);
@@ -929,11 +935,10 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc,
*/
static void smbd_post_send_empty(struct smbdirect_socket *sc)
{
- int remaining_data_length = 0;
int ret;
sc->statistics.send_empty++;
- ret = smbd_post_send_iter(sc, NULL, &remaining_data_length);
+ ret = smbd_post_send_iter(sc, NULL, 0);
if (ret < 0) {
log_rdma_send(ERR, "smbd_post_send_iter failed ret=%d\n", ret);
smbdirect_connection_schedule_disconnect(sc, ret);
@@ -953,9 +958,11 @@ static int smbd_post_send_full_iter(struct smbdirect_socket *sc,
*/
while (iov_iter_count(iter) > 0) {
- rc = smbd_post_send_iter(sc, iter, _remaining_data_length);
+ rc = smbd_post_send_iter(sc, iter, *_remaining_data_length);
if (rc < 0)
break;
+ *_remaining_data_length -= rc;
+ rc = 0;
}
return rc;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 084/127] smb: client: let smbd_post_send_full_iter() get remaining_length and return data_length
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (82 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 083/127] smb: client: let smbd_post_send_iter() get remaining_length and return data_length Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 085/127] smb: client: make use of smbdirect_connection_send_{single_iter,immediate_work}() Stefan Metzmacher
` (43 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This will simplify further changes in order to share
more common code in future.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 34404a1d3e58..fb3cf25b78f8 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -947,9 +947,9 @@ static void smbd_post_send_empty(struct smbdirect_socket *sc)
static int smbd_post_send_full_iter(struct smbdirect_socket *sc,
struct iov_iter *iter,
- int *_remaining_data_length)
+ u32 remaining_data_length)
{
- int rc = 0;
+ int bytes = 0;
/*
* smbd_post_send_iter() respects the
@@ -958,14 +958,16 @@ static int smbd_post_send_full_iter(struct smbdirect_socket *sc,
*/
while (iov_iter_count(iter) > 0) {
- rc = smbd_post_send_iter(sc, iter, *_remaining_data_length);
+ int rc;
+
+ rc = smbd_post_send_iter(sc, iter, remaining_data_length);
if (rc < 0)
- break;
- *_remaining_data_length -= rc;
- rc = 0;
+ return rc;
+ remaining_data_length -= rc;
+ bytes += rc;
}
- return rc;
+ return bytes;
}
/* Perform SMBD negotiate according to [MS-SMBD] 3.1.5.2 */
@@ -1365,16 +1367,20 @@ int smbd_send(struct TCP_Server_Info *server,
klen += rqst->rq_iov[i].iov_len;
iov_iter_kvec(&iter, ITER_SOURCE, rqst->rq_iov, rqst->rq_nvec, klen);
- rc = smbd_post_send_full_iter(sc, &iter, &remaining_data_length);
+ rc = smbd_post_send_full_iter(sc, &iter, remaining_data_length);
if (rc < 0)
break;
+ remaining_data_length -= rc;
+ rc = 0;
if (iov_iter_count(&rqst->rq_iter) > 0) {
/* And then the data pages if there are any */
rc = smbd_post_send_full_iter(sc, &rqst->rq_iter,
- &remaining_data_length);
+ remaining_data_length);
if (rc < 0)
break;
+ remaining_data_length -= rc;
+ rc = 0;
}
} while (++rqst_idx < num_rqst);
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 085/127] smb: client: make use of smbdirect_connection_send_{single_iter,immediate_work}()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (83 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 084/127] smb: client: let smbd_post_send_full_iter() " Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 086/127] smb: client: introduce and use smbd_mr_fill_buffer_descriptor() Stefan Metzmacher
` (42 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
David Howells
With this the low level send functions are in common,
we'll have to do some more changes in generic smb code
in order to use smbdirect_connection_send_iter() instead
of looping around smbdirect_connection_send_single_iter().
David's cleanups will allow us to use
smbdirect_connection_send_iter().
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: Namjae Jeon <linkinjeon@kernel.org>
Cc: David Howells <dhowells@redhat.com>
Cc: linux-cifs@vger.kernel.org
Cc: samba-technical@lists.samba.org
Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
fs/smb/client/smbdirect.c | 253 +++-----------------------------------
1 file changed, 15 insertions(+), 238 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index fb3cf25b78f8..1e17daaac227 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -728,223 +728,6 @@ static int smbd_post_send_negotiate_req(struct smbdirect_socket *sc)
return rc;
}
-/* Post the send request */
-static int smbd_post_send(struct smbdirect_socket *sc,
- struct smbdirect_send_io *request)
-{
- int rc, i;
-
- for (i = 0; i < request->num_sge; i++) {
- log_rdma_send(INFO,
- "rdma_request sge[%d] addr=0x%llx length=%u\n",
- i, request->sge[i].addr, request->sge[i].length);
- ib_dma_sync_single_for_device(
- sc->ib.dev,
- request->sge[i].addr,
- request->sge[i].length,
- DMA_TO_DEVICE);
- }
-
- request->cqe.done = smbdirect_connection_send_io_done;
-
- request->wr.next = NULL;
- request->wr.wr_cqe = &request->cqe;
- request->wr.sg_list = request->sge;
- request->wr.num_sge = request->num_sge;
- request->wr.opcode = IB_WR_SEND;
- request->wr.send_flags = IB_SEND_SIGNALED;
-
- rc = ib_post_send(sc->ib.qp, &request->wr, NULL);
- if (rc) {
- log_rdma_send(ERR, "ib_post_send failed rc=%d\n", rc);
- smbdirect_connection_schedule_disconnect(sc, rc);
- rc = -EAGAIN;
- }
-
- return rc;
-}
-
-static int smbd_post_send_iter(struct smbdirect_socket *sc,
- struct iov_iter *iter,
- u32 remaining_data_length)
-{
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- int rc;
- int header_length;
- int data_length;
- struct smbdirect_send_io *request;
- struct smbdirect_data_transfer *packet;
- u16 new_credits = 0;
-
- if (iter) {
- header_length = sizeof(struct smbdirect_data_transfer);
- if (WARN_ON_ONCE(remaining_data_length == 0 ||
- iov_iter_count(iter) > remaining_data_length))
- return -EINVAL;
- } else {
- /* If this is a packet without payload, don't send padding */
- header_length = offsetof(struct smbdirect_data_transfer, padding);
- if (WARN_ON_ONCE(remaining_data_length))
- return -EINVAL;
- }
-
-wait_lcredit:
- /* Wait for local send credits */
- rc = wait_event_interruptible(sc->send_io.lcredits.wait_queue,
- atomic_read(&sc->send_io.lcredits.count) > 0 ||
- sc->status != SMBDIRECT_SOCKET_CONNECTED);
- if (rc)
- goto err_wait_lcredit;
-
- if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
- log_outgoing(ERR, "disconnected not sending on wait_credit\n");
- rc = -EAGAIN;
- goto err_wait_lcredit;
- }
- if (unlikely(atomic_dec_return(&sc->send_io.lcredits.count) < 0)) {
- atomic_inc(&sc->send_io.lcredits.count);
- goto wait_lcredit;
- }
-
-wait_credit:
- /* Wait for send credits. A SMBD packet needs one credit */
- rc = wait_event_interruptible(sc->send_io.credits.wait_queue,
- atomic_read(&sc->send_io.credits.count) > 0 ||
- sc->status != SMBDIRECT_SOCKET_CONNECTED);
- if (rc)
- goto err_wait_credit;
-
- if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
- log_outgoing(ERR, "disconnected not sending on wait_credit\n");
- rc = -EAGAIN;
- goto err_wait_credit;
- }
- if (unlikely(atomic_dec_return(&sc->send_io.credits.count) < 0)) {
- atomic_inc(&sc->send_io.credits.count);
- goto wait_credit;
- }
-
- request = smbdirect_connection_alloc_send_io(sc);
- if (IS_ERR(request)) {
- rc = PTR_ERR(request);
- goto err_alloc;
- }
-
- memset(request->sge, 0, sizeof(request->sge));
-
- packet = smbdirect_send_io_payload(request);
- request->sge[0].addr = ib_dma_map_single(sc->ib.dev,
- (void *)packet,
- header_length,
- DMA_TO_DEVICE);
- if (ib_dma_mapping_error(sc->ib.dev, request->sge[0].addr)) {
- rc = -EIO;
- goto err_dma;
- }
-
- request->sge[0].length = header_length;
- request->sge[0].lkey = sc->ib.pd->local_dma_lkey;
- request->num_sge = 1;
-
- /* Fill in the data payload to find out how much data we can add */
- if (iter) {
- struct smbdirect_map_sges extract = {
- .num_sge = request->num_sge,
- .max_sge = ARRAY_SIZE(request->sge),
- .sge = request->sge,
- .device = sc->ib.dev,
- .local_dma_lkey = sc->ib.pd->local_dma_lkey,
- .direction = DMA_TO_DEVICE,
- };
- size_t payload_len = umin(iov_iter_count(iter),
- sp->max_send_size - sizeof(*packet));
-
- rc = smbdirect_map_sges_from_iter(iter, payload_len, &extract);
- if (rc < 0)
- goto err_dma;
- data_length = rc;
- request->num_sge = extract.num_sge;
- remaining_data_length -= data_length;
- } else {
- data_length = 0;
- }
-
- /* Fill in the packet header */
- packet->credits_requested = cpu_to_le16(sp->send_credit_target);
-
- new_credits = smbdirect_connection_grant_recv_credits(sc);
- packet->credits_granted = cpu_to_le16(new_credits);
-
- packet->flags = 0;
- if (smbdirect_connection_request_keep_alive(sc))
- packet->flags |= cpu_to_le16(SMBDIRECT_FLAG_RESPONSE_REQUESTED);
-
- packet->reserved = 0;
- if (!data_length)
- packet->data_offset = 0;
- else
- packet->data_offset = cpu_to_le32(24);
- packet->data_length = cpu_to_le32(data_length);
- packet->remaining_data_length = cpu_to_le32(remaining_data_length);
- packet->padding = 0;
-
- log_outgoing(INFO, "credits_requested=%d credits_granted=%d data_offset=%d data_length=%d remaining_data_length=%d\n",
- le16_to_cpu(packet->credits_requested),
- le16_to_cpu(packet->credits_granted),
- le32_to_cpu(packet->data_offset),
- le32_to_cpu(packet->data_length),
- le32_to_cpu(packet->remaining_data_length));
-
- /*
- * Now that we got a local and a remote credit
- * we add us as pending
- */
- atomic_inc(&sc->send_io.pending.count);
-
- rc = smbd_post_send(sc, request);
- if (!rc)
- return data_length;
-
- if (atomic_dec_and_test(&sc->send_io.pending.count))
- wake_up(&sc->send_io.pending.zero_wait_queue);
-
- wake_up(&sc->send_io.pending.dec_wait_queue);
-
-err_dma:
- smbdirect_connection_free_send_io(request);
-
- /* roll back the granted receive credits */
- atomic_sub(new_credits, &sc->recv_io.credits.count);
-
-err_alloc:
- atomic_inc(&sc->send_io.credits.count);
- wake_up(&sc->send_io.credits.wait_queue);
-
-err_wait_credit:
- atomic_inc(&sc->send_io.lcredits.count);
- wake_up(&sc->send_io.lcredits.wait_queue);
-
-err_wait_lcredit:
- return rc;
-}
-
-/*
- * Send an empty message
- * Empty message is used to extend credits to peer to for keep live
- * while there is no upper layer payload to send at the time
- */
-static void smbd_post_send_empty(struct smbdirect_socket *sc)
-{
- int ret;
-
- sc->statistics.send_empty++;
- ret = smbd_post_send_iter(sc, NULL, 0);
- if (ret < 0) {
- log_rdma_send(ERR, "smbd_post_send_iter failed ret=%d\n", ret);
- smbdirect_connection_schedule_disconnect(sc, ret);
- }
-}
-
static int smbd_post_send_full_iter(struct smbdirect_socket *sc,
struct iov_iter *iter,
u32 remaining_data_length)
@@ -952,7 +735,7 @@ static int smbd_post_send_full_iter(struct smbdirect_socket *sc,
int bytes = 0;
/*
- * smbd_post_send_iter() respects the
+ * smbdirect_connection_send_single_iter() respects the
* negotiated max_send_size, so we need to
* loop until the full iter is posted
*/
@@ -960,7 +743,11 @@ static int smbd_post_send_full_iter(struct smbdirect_socket *sc,
while (iov_iter_count(iter) > 0) {
int rc;
- rc = smbd_post_send_iter(sc, iter, remaining_data_length);
+ rc = smbdirect_connection_send_single_iter(sc,
+ NULL, /* batch */
+ iter,
+ 0, /* flags */
+ remaining_data_length);
if (rc < 0)
return rc;
remaining_data_length -= rc;
@@ -1013,18 +800,6 @@ static int smbd_negotiate(struct smbdirect_socket *sc)
return rc;
}
-static void send_immediate_empty_message(struct work_struct *work)
-{
- struct smbdirect_socket *sc =
- container_of(work, struct smbdirect_socket, idle.immediate_work);
-
- if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
- return;
-
- log_keep_alive(INFO, "send an empty message\n");
- smbd_post_send_empty(sc);
-}
-
/*
* Destroy the transport and related RDMA and memory resources
* Need to go through all the pending counters and make sure on one is using
@@ -1207,7 +982,7 @@ static struct smbd_connection *_smbd_get_connection(
list_for_each_entry(recv_io, &sc->recv_io.free.list, list)
recv_io->cqe.done = recv_done;
- INIT_WORK(&sc->idle.immediate_work, send_immediate_empty_message);
+ INIT_WORK(&sc->idle.immediate_work, smbdirect_connection_send_immediate_work);
/*
* start with the negotiate timeout and SMBDIRECT_KEEPALIVE_PENDING
* so that the timer will cause a disconnect.
@@ -1325,6 +1100,7 @@ int smbd_send(struct TCP_Server_Info *server,
struct iov_iter iter;
unsigned int remaining_data_length, klen;
int rc, i, rqst_idx;
+ int error = 0;
if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
return -EAGAIN;
@@ -1392,14 +1168,15 @@ int smbd_send(struct TCP_Server_Info *server,
* that means all the I/Os have been out and we are good to return
*/
- wait_event(sc->send_io.pending.zero_wait_queue,
- atomic_read(&sc->send_io.pending.count) == 0 ||
- sc->status != SMBDIRECT_SOCKET_CONNECTED);
+ error = rc;
+ rc = smbdirect_connection_send_wait_zero_pending(sc);
+ if (unlikely(rc && !error))
+ error = -EAGAIN;
- if (sc->status != SMBDIRECT_SOCKET_CONNECTED && rc == 0)
- rc = -EAGAIN;
+ if (unlikely(error))
+ return error;
- return rc;
+ return 0;
}
/*
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 086/127] smb: client: introduce and use smbd_mr_fill_buffer_descriptor()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (84 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 085/127] smb: client: make use of smbdirect_connection_send_{single_iter,immediate_work}() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 087/127] smb: client: introduce and use smbd_debug_proc_show() Stefan Metzmacher
` (41 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This will allow us to make struct smbdirect_mr_io private in future.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smb2pdu.c | 8 ++------
fs/smb/client/smbdirect.c | 6 ++++++
fs/smb/client/smbdirect.h | 2 ++
3 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
index b0739a2661bf..a9a04c4db6dc 100644
--- a/fs/smb/client/smb2pdu.c
+++ b/fs/smb/client/smb2pdu.c
@@ -4480,9 +4480,7 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
req->ReadChannelInfoLength =
cpu_to_le16(sizeof(struct smbdirect_buffer_descriptor_v1));
v1 = (struct smbdirect_buffer_descriptor_v1 *) &req->Buffer[0];
- v1->offset = cpu_to_le64(rdata->mr->mr->iova);
- v1->token = cpu_to_le32(rdata->mr->mr->rkey);
- v1->length = cpu_to_le32(rdata->mr->mr->length);
+ smbd_mr_fill_buffer_descriptor(rdata->mr, v1);
*total_len += sizeof(*v1) - 1;
}
@@ -5030,9 +5028,7 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
req->WriteChannelInfoLength =
cpu_to_le16(sizeof(struct smbdirect_buffer_descriptor_v1));
v1 = (struct smbdirect_buffer_descriptor_v1 *) &req->Buffer[0];
- v1->offset = cpu_to_le64(wdata->mr->mr->iova);
- v1->token = cpu_to_le32(wdata->mr->mr->rkey);
- v1->length = cpu_to_le32(wdata->mr->mr->length);
+ smbd_mr_fill_buffer_descriptor(wdata->mr, v1);
rqst.rq_iov[0].iov_len += sizeof(*v1);
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 1e17daaac227..d52ded68dee4 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -1195,6 +1195,12 @@ struct smbdirect_mr_io *smbd_register_mr(struct smbd_connection *info,
return smbdirect_connection_register_mr_io(sc, iter, writing, need_invalidate);
}
+void smbd_mr_fill_buffer_descriptor(struct smbdirect_mr_io *mr,
+ struct smbdirect_buffer_descriptor_v1 *v1)
+{
+ smbdirect_mr_io_fill_buffer_descriptor(mr, v1);
+}
+
/*
* Deregister a MR after I/O is done
* This function may wait if remote invalidation is not used
diff --git a/fs/smb/client/smbdirect.h b/fs/smb/client/smbdirect.h
index 577d37dbeb8a..09f7dd14b2c1 100644
--- a/fs/smb/client/smbdirect.h
+++ b/fs/smb/client/smbdirect.h
@@ -60,6 +60,8 @@ int smbd_send(struct TCP_Server_Info *server,
struct smbdirect_mr_io *smbd_register_mr(
struct smbd_connection *info, struct iov_iter *iter,
bool writing, bool need_invalidate);
+void smbd_mr_fill_buffer_descriptor(struct smbdirect_mr_io *mr,
+ struct smbdirect_buffer_descriptor_v1 *v1);
void smbd_deregister_mr(struct smbdirect_mr_io *mr);
#else
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 087/127] smb: client: introduce and use smbd_debug_proc_show()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (85 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 086/127] smb: client: introduce and use smbd_mr_fill_buffer_descriptor() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 088/127] smb: client: make use of smbdirect_socket_init_new() and smbdirect_connect_sync() Stefan Metzmacher
` (40 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This will allow us to make struct smbdirect_socket private
in future.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/cifs_debug.c | 67 +-------------------------------------
fs/smb/client/smbdirect.c | 15 +++++++++
fs/smb/client/smbdirect.h | 2 ++
3 files changed, 18 insertions(+), 66 deletions(-)
diff --git a/fs/smb/client/cifs_debug.c b/fs/smb/client/cifs_debug.c
index 1fb71d2d31b5..5076d4a96bda 100644
--- a/fs/smb/client/cifs_debug.c
+++ b/fs/smb/client/cifs_debug.c
@@ -24,7 +24,6 @@
#endif
#ifdef CONFIG_CIFS_SMB_DIRECT
#include "smbdirect.h"
-#include "../common/smbdirect/smbdirect_pdu.h"
#endif
#include "cifs_swn.h"
#include "cached_dir.h"
@@ -457,11 +456,6 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
c = 0;
spin_lock(&cifs_tcp_ses_lock);
list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
-#ifdef CONFIG_CIFS_SMB_DIRECT
- struct smbdirect_socket *sc;
- struct smbdirect_socket_parameters *sp;
-#endif
-
/* channel info will be printed as a part of sessions below */
if (SERVER_IS_CHAN(server))
continue;
@@ -476,66 +470,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
seq_printf(m, "\nClientGUID: %pUL", server->client_guid);
spin_unlock(&server->srv_lock);
#ifdef CONFIG_CIFS_SMB_DIRECT
- if (!server->rdma)
- goto skip_rdma;
-
- if (!server->smbd_conn) {
- seq_printf(m, "\nSMBDirect transport not available");
- goto skip_rdma;
- }
- sc = &server->smbd_conn->socket;
- sp = &sc->parameters;
-
- seq_printf(m, "\nSMBDirect protocol version: 0x%x "
- "transport status: %s (%u)",
- SMBDIRECT_V1,
- smbdirect_socket_status_string(sc->status),
- sc->status);
- seq_printf(m, "\nConn receive_credit_max: %u "
- "send_credit_target: %u max_send_size: %u",
- sp->recv_credit_max,
- sp->send_credit_target,
- sp->max_send_size);
- seq_printf(m, "\nConn max_fragmented_recv_size: %u "
- "max_fragmented_send_size: %u max_receive_size:%u",
- sp->max_fragmented_recv_size,
- sp->max_fragmented_send_size,
- sp->max_recv_size);
- seq_printf(m, "\nConn keep_alive_interval: %u "
- "max_readwrite_size: %u rdma_readwrite_threshold: %u",
- sp->keepalive_interval_msec * 1000,
- sp->max_read_write_size,
- server->rdma_readwrite_threshold);
- seq_printf(m, "\nDebug count_get_receive_buffer: %llu "
- "count_put_receive_buffer: %llu count_send_empty: %llu",
- sc->statistics.get_receive_buffer,
- sc->statistics.put_receive_buffer,
- sc->statistics.send_empty);
- seq_printf(m, "\nRead Queue "
- "count_enqueue_reassembly_queue: %llu "
- "count_dequeue_reassembly_queue: %llu "
- "reassembly_data_length: %u "
- "reassembly_queue_length: %u",
- sc->statistics.enqueue_reassembly_queue,
- sc->statistics.dequeue_reassembly_queue,
- sc->recv_io.reassembly.data_length,
- sc->recv_io.reassembly.queue_length);
- seq_printf(m, "\nCurrent Credits send_credits: %u "
- "receive_credits: %u receive_credit_target: %u",
- atomic_read(&sc->send_io.credits.count),
- atomic_read(&sc->recv_io.credits.count),
- sc->recv_io.credits.target);
- seq_printf(m, "\nPending send_pending: %u ",
- atomic_read(&sc->send_io.pending.count));
- seq_printf(m, "\nMR responder_resources: %u "
- "max_frmr_depth: %u mr_type: 0x%x",
- sp->responder_resources,
- sp->max_frmr_depth,
- sc->mr_io.type);
- seq_printf(m, "\nMR mr_ready_count: %u mr_used_count: %u",
- atomic_read(&sc->mr_io.ready.count),
- atomic_read(&sc->mr_io.used.count));
-skip_rdma:
+ smbd_debug_proc_show(server, m);
#endif
seq_printf(m, "\nNumber of credits: %d,%d,%d Dialect 0x%x",
server->credits,
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index d52ded68dee4..745879bf3a3f 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -1211,3 +1211,18 @@ void smbd_deregister_mr(struct smbdirect_mr_io *mr)
{
smbdirect_connection_deregister_mr_io(mr);
}
+
+void smbd_debug_proc_show(struct TCP_Server_Info *server, struct seq_file *m)
+{
+ if (!server->rdma)
+ return;
+
+ if (!server->smbd_conn) {
+ seq_puts(m, "\nSMBDirect transport not available");
+ return;
+ }
+
+ smbdirect_connection_legacy_debug_proc_show(&server->smbd_conn->socket,
+ server->rdma_readwrite_threshold,
+ m);
+}
diff --git a/fs/smb/client/smbdirect.h b/fs/smb/client/smbdirect.h
index 09f7dd14b2c1..7986e87bf384 100644
--- a/fs/smb/client/smbdirect.h
+++ b/fs/smb/client/smbdirect.h
@@ -64,6 +64,8 @@ void smbd_mr_fill_buffer_descriptor(struct smbdirect_mr_io *mr,
struct smbdirect_buffer_descriptor_v1 *v1);
void smbd_deregister_mr(struct smbdirect_mr_io *mr);
+void smbd_debug_proc_show(struct TCP_Server_Info *server, struct seq_file *m);
+
#else
#define cifs_rdma_enabled(server) 0
struct smbd_connection {};
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 088/127] smb: client: make use of smbdirect_socket_init_new() and smbdirect_connect_sync()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (86 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 087/127] smb: client: introduce and use smbd_debug_proc_show() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 089/127] smb: client: make use of smbdirect_socket_create_kern()/smbdirect_socket_release() Stefan Metzmacher
` (39 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
This means we finally only use common functions in the client.
We still use the embedded struct smbdirect_socket and are
able to access internals, but the will be removed in the
next commits as well.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 797 +++-----------------------------------
fs/smb/client/smbdirect.h | 1 +
2 files changed, 56 insertions(+), 742 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 745879bf3a3f..922001875d9b 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -10,19 +10,12 @@
#include <linux/module.h>
#include <linux/highmem.h>
#include <linux/folio_queue.h>
-#include "../common/smbdirect/smbdirect_pdu.h"
+#include <linux/errname.h>
#include "smbdirect.h"
#include "cifs_debug.h"
#include "cifsproto.h"
#include "smb2proto.h"
-const struct smbdirect_socket_parameters *smbd_get_parameters(struct smbd_connection *conn)
-{
- struct smbdirect_socket *sc = &conn->socket;
-
- return &sc->parameters;
-}
-
/* Port numbers for SMBD transport */
#define SMB_PORT 445
#define SMBD_PORT 5445
@@ -36,21 +29,12 @@ const struct smbdirect_socket_parameters *smbd_get_parameters(struct smbd_connec
/* The timeout to wait for a keepalive message from peer in seconds */
#define KEEPALIVE_RECV_TIMEOUT 5
-/* SMBD minimum receive size and fragmented sized defined in [MS-SMBD] */
-#define SMBD_MIN_RECEIVE_SIZE 128
-#define SMBD_MIN_FRAGMENTED_SIZE 131072
-
/*
* Default maximum number of RDMA read/write outstanding on this connection
* This value is possibly decreased during QP creation on hardware limit
*/
#define SMBD_CM_RESPONDER_RESOURCES 32
-/* Maximum number of retries on data transfer operations */
-#define SMBD_CM_RETRY 6
-/* No need to retry on Receiver Not Ready since SMBD manages credits */
-#define SMBD_CM_RNR_RETRY 0
-
/*
* User configurable initial values per SMBD transport connection
* as defined in [MS-SMBD] 3.1.1.1
@@ -179,555 +163,6 @@ do { \
#define log_rdma_mr(level, fmt, args...) \
log_rdma(level, LOG_RDMA_MR, fmt, ##args)
-/* Upcall from RDMA CM */
-static int smbd_conn_upcall(
- struct rdma_cm_id *id, struct rdma_cm_event *event)
-{
- struct smbdirect_socket *sc = id->context;
- const char *event_name = rdma_event_msg(event->event);
- u8 peer_initiator_depth;
- u8 peer_responder_resources;
-
- log_rdma_event(INFO, "event=%s status=%d\n",
- event_name, event->status);
-
- 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;
- wake_up(&sc->status_wait);
- break;
-
- case RDMA_CM_EVENT_ROUTE_RESOLVED:
- WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING);
- sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED;
- wake_up(&sc->status_wait);
- 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;
- smbdirect_connection_disconnect_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;
- smbdirect_connection_disconnect_work(&sc->disconnect_work);
- break;
-
- case RDMA_CM_EVENT_ESTABLISHED:
- log_rdma_event(INFO, "connected event=%s\n", event_name);
-
- /*
- * Here we work around an inconsistency between
- * iWarp and other devices (at least rxe and irdma using RoCEv2)
- */
- if (rdma_protocol_iwarp(id->device, id->port_num)) {
- /*
- * iWarp devices report the peer's values
- * with the perspective of the peer here.
- * Tested with siw and irdma (in iwarp mode)
- * We need to change to our perspective here,
- * so we need to switch the values.
- */
- peer_initiator_depth = event->param.conn.responder_resources;
- peer_responder_resources = event->param.conn.initiator_depth;
- } else {
- /*
- * Non iWarp devices report the peer's values
- * already changed to our perspective here.
- * Tested with rxe and irdma (in roce mode).
- */
- peer_initiator_depth = event->param.conn.initiator_depth;
- peer_responder_resources = event->param.conn.responder_resources;
- }
- smbdirect_connection_negotiate_rdma_resources(sc,
- peer_initiator_depth,
- peer_responder_resources,
- &event->param.conn);
-
- WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING);
- sc->status = SMBDIRECT_SOCKET_NEGOTIATE_NEEDED;
- wake_up(&sc->status_wait);
- break;
-
- case RDMA_CM_EVENT_CONNECT_ERROR:
- case RDMA_CM_EVENT_UNREACHABLE:
- case RDMA_CM_EVENT_REJECTED:
- 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;
- smbdirect_connection_disconnect_work(&sc->disconnect_work);
- break;
-
- case RDMA_CM_EVENT_DEVICE_REMOVAL:
- case RDMA_CM_EVENT_DISCONNECTED:
- /* 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;
- smbdirect_connection_disconnect_work(&sc->disconnect_work);
- break;
-
- default:
- log_rdma_event(ERR, "unexpected event=%s status=%d\n",
- event_name, event->status);
- break;
- }
-
- return 0;
-}
-
-static inline void *smbdirect_send_io_payload(struct smbdirect_send_io *request)
-{
- return (void *)request->packet;
-}
-
-static inline void *smbdirect_recv_io_payload(struct smbdirect_recv_io *response)
-{
- return (void *)response->packet;
-}
-
-static void dump_smbdirect_negotiate_resp(struct smbdirect_negotiate_resp *resp)
-{
- log_rdma_event(INFO, "resp message min_version %u max_version %u negotiated_version %u credits_requested %u credits_granted %u status %u max_readwrite_size %u preferred_send_size %u max_receive_size %u max_fragmented_size %u\n",
- resp->min_version, resp->max_version,
- resp->negotiated_version, resp->credits_requested,
- resp->credits_granted, resp->status,
- resp->max_readwrite_size, resp->preferred_send_size,
- resp->max_receive_size, resp->max_fragmented_size);
-}
-
-/*
- * Process a negotiation response message, according to [MS-SMBD]3.1.5.7
- * response, packet_length: the negotiation response message
- * return value: true if negotiation is a success, false if failed
- */
-static bool process_negotiation_response(
- struct smbdirect_recv_io *response, int packet_length)
-{
- struct smbdirect_socket *sc = response->socket;
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- struct smbdirect_negotiate_resp *packet = smbdirect_recv_io_payload(response);
-
- if (packet_length < sizeof(struct smbdirect_negotiate_resp)) {
- log_rdma_event(ERR,
- "error: packet_length=%d\n", packet_length);
- return false;
- }
-
- if (le16_to_cpu(packet->negotiated_version) != SMBDIRECT_V1) {
- log_rdma_event(ERR, "error: negotiated_version=%x\n",
- le16_to_cpu(packet->negotiated_version));
- return false;
- }
-
- if (packet->credits_requested == 0) {
- log_rdma_event(ERR, "error: credits_requested==0\n");
- return false;
- }
- sc->recv_io.credits.target = le16_to_cpu(packet->credits_requested);
- sc->recv_io.credits.target = min_t(u16, sc->recv_io.credits.target, sp->recv_credit_max);
-
- if (packet->credits_granted == 0) {
- log_rdma_event(ERR, "error: credits_granted==0\n");
- return false;
- }
- atomic_set(&sc->send_io.lcredits.count, sp->send_credit_target);
- atomic_set(&sc->send_io.credits.count, le16_to_cpu(packet->credits_granted));
-
- if (le32_to_cpu(packet->preferred_send_size) > sp->max_recv_size) {
- log_rdma_event(ERR, "error: preferred_send_size=%d\n",
- le32_to_cpu(packet->preferred_send_size));
- return false;
- }
- sp->max_recv_size = le32_to_cpu(packet->preferred_send_size);
-
- if (le32_to_cpu(packet->max_receive_size) < SMBD_MIN_RECEIVE_SIZE) {
- log_rdma_event(ERR, "error: max_receive_size=%d\n",
- le32_to_cpu(packet->max_receive_size));
- return false;
- }
- sp->max_send_size = min_t(u32, sp->max_send_size,
- le32_to_cpu(packet->max_receive_size));
-
- if (le32_to_cpu(packet->max_fragmented_size) <
- SMBD_MIN_FRAGMENTED_SIZE) {
- log_rdma_event(ERR, "error: max_fragmented_size=%d\n",
- le32_to_cpu(packet->max_fragmented_size));
- return false;
- }
- sp->max_fragmented_send_size =
- le32_to_cpu(packet->max_fragmented_size);
-
-
- sp->max_read_write_size = min_t(u32,
- le32_to_cpu(packet->max_readwrite_size),
- sp->max_frmr_depth * PAGE_SIZE);
- sp->max_frmr_depth = sp->max_read_write_size / PAGE_SIZE;
-
- sc->recv_io.expected = SMBDIRECT_EXPECT_DATA_TRANSFER;
- return true;
-}
-
-/* Called from softirq, when recv is done */
-static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
-{
- struct smbdirect_data_transfer *data_transfer;
- struct smbdirect_recv_io *response =
- container_of(wc->wr_cqe, struct smbdirect_recv_io, cqe);
- struct smbdirect_socket *sc = response->socket;
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- u16 old_recv_credit_target;
- u32 data_offset = 0;
- u32 data_length = 0;
- u32 remaining_data_length = 0;
- bool negotiate_done = false;
-
- log_rdma_recv(INFO,
- "response=0x%p type=%d wc status=%s wc opcode %d byte_len=%d pkey_index=%u\n",
- response, sc->recv_io.expected,
- ib_wc_status_msg(wc->status), wc->opcode,
- wc->byte_len, wc->pkey_index);
-
- if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_RECV) {
- if (wc->status != IB_WC_WR_FLUSH_ERR)
- log_rdma_recv(ERR, "wc->status=%s opcode=%d\n",
- ib_wc_status_msg(wc->status), wc->opcode);
- goto error;
- }
-
- ib_dma_sync_single_for_cpu(
- wc->qp->device,
- response->sge.addr,
- response->sge.length,
- DMA_FROM_DEVICE);
-
- /*
- * Reset timer to the keepalive interval in
- * order to trigger our next keepalive message.
- */
- sc->idle.keepalive = SMBDIRECT_KEEPALIVE_NONE;
- mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
- msecs_to_jiffies(sp->keepalive_interval_msec));
-
- switch (sc->recv_io.expected) {
- /* SMBD negotiation response */
- case SMBDIRECT_EXPECT_NEGOTIATE_REP:
- dump_smbdirect_negotiate_resp(smbdirect_recv_io_payload(response));
- sc->recv_io.reassembly.full_packet_received = true;
- negotiate_done =
- process_negotiation_response(response, wc->byte_len);
- smbdirect_connection_put_recv_io(response);
- WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_NEGOTIATE_RUNNING);
- if (!negotiate_done) {
- sc->status = SMBDIRECT_SOCKET_NEGOTIATE_FAILED;
- smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
- } else {
- sc->status = SMBDIRECT_SOCKET_CONNECTED;
- wake_up(&sc->status_wait);
- }
-
- return;
-
- /* SMBD data transfer packet */
- case SMBDIRECT_EXPECT_DATA_TRANSFER:
- data_transfer = smbdirect_recv_io_payload(response);
-
- if (wc->byte_len <
- offsetof(struct smbdirect_data_transfer, padding))
- goto error;
-
- remaining_data_length = le32_to_cpu(data_transfer->remaining_data_length);
- data_offset = le32_to_cpu(data_transfer->data_offset);
- data_length = le32_to_cpu(data_transfer->data_length);
- if (wc->byte_len < data_offset ||
- (u64)wc->byte_len < (u64)data_offset + data_length)
- goto error;
-
- if (remaining_data_length > sp->max_fragmented_recv_size ||
- data_length > sp->max_fragmented_recv_size ||
- (u64)remaining_data_length + (u64)data_length > (u64)sp->max_fragmented_recv_size)
- goto error;
-
- if (data_length) {
- if (sc->recv_io.reassembly.full_packet_received)
- response->first_segment = true;
-
- if (le32_to_cpu(data_transfer->remaining_data_length))
- sc->recv_io.reassembly.full_packet_received = false;
- else
- sc->recv_io.reassembly.full_packet_received = true;
- }
-
- atomic_dec(&sc->recv_io.posted.count);
- atomic_dec(&sc->recv_io.credits.count);
- old_recv_credit_target = sc->recv_io.credits.target;
- sc->recv_io.credits.target =
- le16_to_cpu(data_transfer->credits_requested);
- sc->recv_io.credits.target =
- min_t(u16, sc->recv_io.credits.target, sp->recv_credit_max);
- sc->recv_io.credits.target =
- max_t(u16, sc->recv_io.credits.target, 1);
- if (le16_to_cpu(data_transfer->credits_granted)) {
- atomic_add(le16_to_cpu(data_transfer->credits_granted),
- &sc->send_io.credits.count);
- /*
- * We have new send credits granted from remote peer
- * If any sender is waiting for credits, unblock it
- */
- wake_up(&sc->send_io.credits.wait_queue);
- }
-
- log_incoming(INFO, "data flags %d data_offset %d data_length %d remaining_data_length %d\n",
- le16_to_cpu(data_transfer->flags),
- le32_to_cpu(data_transfer->data_offset),
- le32_to_cpu(data_transfer->data_length),
- le32_to_cpu(data_transfer->remaining_data_length));
-
- /* Send an immediate response right away if requested */
- if (le16_to_cpu(data_transfer->flags) &
- SMBDIRECT_FLAG_RESPONSE_REQUESTED) {
- log_keep_alive(INFO, "schedule send of immediate response\n");
- queue_work(sc->workqueue, &sc->idle.immediate_work);
- }
-
- /*
- * If this is a packet with data playload place the data in
- * reassembly queue and wake up the reading thread
- */
- if (data_length) {
- if (sc->recv_io.credits.target > old_recv_credit_target)
- queue_work(sc->workqueue, &sc->recv_io.posted.refill_work);
-
- smbdirect_connection_reassembly_append_recv_io(sc, response, data_length);
- wake_up(&sc->recv_io.reassembly.wait_queue);
- } else
- smbdirect_connection_put_recv_io(response);
-
- return;
-
- case SMBDIRECT_EXPECT_NEGOTIATE_REQ:
- /* Only server... */
- break;
- }
-
- /*
- * This is an internal error!
- */
- log_rdma_recv(ERR, "unexpected response type=%d\n", sc->recv_io.expected);
- WARN_ON_ONCE(sc->recv_io.expected != SMBDIRECT_EXPECT_DATA_TRANSFER);
-error:
- smbdirect_connection_put_recv_io(response);
- smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
-}
-
-static struct rdma_cm_id *smbd_create_id(
- struct smbdirect_socket *sc,
- struct sockaddr *dstaddr, int port)
-{
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- struct rdma_cm_id *id;
- int rc;
- __be16 *sport;
-
- id = rdma_create_id(&init_net, smbd_conn_upcall, sc,
- RDMA_PS_TCP, IB_QPT_RC);
- if (IS_ERR(id)) {
- rc = PTR_ERR(id);
- log_rdma_event(ERR, "rdma_create_id() failed %i\n", rc);
- return id;
- }
-
- if (dstaddr->sa_family == AF_INET6)
- sport = &((struct sockaddr_in6 *)dstaddr)->sin6_port;
- else
- sport = &((struct sockaddr_in *)dstaddr)->sin_port;
-
- *sport = htons(port);
-
- 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,
- sp->resolve_addr_timeout_msec);
- if (rc) {
- log_rdma_event(ERR, "rdma_resolve_addr() failed %i\n", rc);
- goto out;
- }
- rc = wait_event_interruptible_timeout(
- sc->status_wait,
- sc->status != SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING,
- msecs_to_jiffies(sp->resolve_addr_timeout_msec));
- /* e.g. if interrupted returns -ERESTARTSYS */
- if (rc < 0) {
- log_rdma_event(ERR, "rdma_resolve_addr timeout rc: %i\n", rc);
- goto out;
- }
- if (sc->status == SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING) {
- rc = -ETIMEDOUT;
- log_rdma_event(ERR, "rdma_resolve_addr() completed %i\n", rc);
- goto out;
- }
- if (sc->status != SMBDIRECT_SOCKET_RESOLVE_ROUTE_NEEDED) {
- rc = -EHOSTUNREACH;
- log_rdma_event(ERR, "rdma_resolve_addr() completed %i\n", rc);
- goto out;
- }
-
- WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RESOLVE_ROUTE_NEEDED);
- sc->status = SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING;
- rc = rdma_resolve_route(id, sp->resolve_route_timeout_msec);
- if (rc) {
- log_rdma_event(ERR, "rdma_resolve_route() failed %i\n", rc);
- goto out;
- }
- rc = wait_event_interruptible_timeout(
- sc->status_wait,
- sc->status != SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING,
- msecs_to_jiffies(sp->resolve_route_timeout_msec));
- /* e.g. if interrupted returns -ERESTARTSYS */
- if (rc < 0) {
- log_rdma_event(ERR, "rdma_resolve_addr timeout rc: %i\n", rc);
- goto out;
- }
- if (sc->status == SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING) {
- rc = -ETIMEDOUT;
- log_rdma_event(ERR, "rdma_resolve_route() completed %i\n", rc);
- goto out;
- }
- if (sc->status != SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED) {
- rc = -ENETUNREACH;
- log_rdma_event(ERR, "rdma_resolve_route() completed %i\n", rc);
- goto out;
- }
-
- return id;
-
-out:
- rdma_destroy_id(id);
- return ERR_PTR(rc);
-}
-
-static int smbd_ia_open(
- struct smbdirect_socket *sc,
- struct sockaddr *dstaddr, int port)
-{
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- int rc;
-
- WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_CREATED);
- sc->status = SMBDIRECT_SOCKET_RESOLVE_ADDR_NEEDED;
-
- sc->rdma.cm_id = smbd_create_id(sc, dstaddr, port);
- if (IS_ERR(sc->rdma.cm_id)) {
- rc = PTR_ERR(sc->rdma.cm_id);
- goto out1;
- }
- sc->ib.dev = sc->rdma.cm_id->device;
-
- if (!smbdirect_frwr_is_supported(&sc->ib.dev->attrs)) {
- log_rdma_event(ERR, "Fast Registration Work Requests (FRWR) is not supported\n");
- log_rdma_event(ERR, "Device capability flags = %llx max_fast_reg_page_list_len = %u\n",
- sc->ib.dev->attrs.device_cap_flags,
- sc->ib.dev->attrs.max_fast_reg_page_list_len);
- rc = -EPROTONOSUPPORT;
- goto out2;
- }
- sp->max_frmr_depth = min_t(u32,
- sp->max_frmr_depth,
- sc->ib.dev->attrs.max_fast_reg_page_list_len);
- sc->mr_io.type = IB_MR_TYPE_MEM_REG;
- if (sc->ib.dev->attrs.kernel_cap_flags & IBK_SG_GAPS_REG)
- sc->mr_io.type = IB_MR_TYPE_SG_GAPS;
-
- return 0;
-
-out2:
- rdma_destroy_id(sc->rdma.cm_id);
- sc->rdma.cm_id = NULL;
-
-out1:
- return rc;
-}
-
-/*
- * Send a negotiation request message to the peer
- * The negotiation procedure is in [MS-SMBD] 3.1.5.2 and 3.1.5.3
- * After negotiation, the transport is connected and ready for
- * carrying upper layer SMB payload
- */
-static int smbd_post_send_negotiate_req(struct smbdirect_socket *sc)
-{
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- struct ib_send_wr send_wr;
- int rc;
- struct smbdirect_send_io *request;
- struct smbdirect_negotiate_req *packet;
-
- request = smbdirect_connection_alloc_send_io(sc);
- if (IS_ERR(request))
- return PTR_ERR(request);
-
- packet = smbdirect_send_io_payload(request);
- packet->min_version = cpu_to_le16(SMBDIRECT_V1);
- packet->max_version = cpu_to_le16(SMBDIRECT_V1);
- packet->reserved = 0;
- packet->credits_requested = cpu_to_le16(sp->send_credit_target);
- packet->preferred_send_size = cpu_to_le32(sp->max_send_size);
- packet->max_receive_size = cpu_to_le32(sp->max_recv_size);
- packet->max_fragmented_size =
- cpu_to_le32(sp->max_fragmented_recv_size);
-
- request->sge[0].addr = ib_dma_map_single(
- sc->ib.dev, (void *)packet,
- sizeof(*packet), DMA_TO_DEVICE);
- if (ib_dma_mapping_error(sc->ib.dev, request->sge[0].addr)) {
- rc = -EIO;
- goto dma_mapping_failed;
- }
-
- request->sge[0].length = sizeof(*packet);
- request->sge[0].lkey = sc->ib.pd->local_dma_lkey;
- request->num_sge = 1;
-
- ib_dma_sync_single_for_device(
- sc->ib.dev, request->sge[0].addr,
- request->sge[0].length, DMA_TO_DEVICE);
-
- request->cqe.done = smbdirect_connection_send_io_done;
-
- send_wr.next = NULL;
- send_wr.wr_cqe = &request->cqe;
- send_wr.sg_list = request->sge;
- send_wr.num_sge = request->num_sge;
- send_wr.opcode = IB_WR_SEND;
- send_wr.send_flags = IB_SEND_SIGNALED;
-
- log_rdma_send(INFO, "sge addr=0x%llx length=%u lkey=0x%x\n",
- request->sge[0].addr,
- request->sge[0].length, request->sge[0].lkey);
-
- atomic_inc(&sc->send_io.pending.count);
- rc = ib_post_send(sc->ib.qp, &send_wr, NULL);
- if (!rc)
- return 0;
-
- /* if we reach here, post send failed */
- log_rdma_send(ERR, "ib_post_send failed rc=%d\n", rc);
- atomic_dec(&sc->send_io.pending.count);
-
- smbdirect_connection_schedule_disconnect(sc, rc);
-
-dma_mapping_failed:
- smbdirect_connection_free_send_io(request);
- return rc;
-}
-
static int smbd_post_send_full_iter(struct smbdirect_socket *sc,
struct iov_iter *iter,
u32 remaining_data_length)
@@ -757,49 +192,6 @@ static int smbd_post_send_full_iter(struct smbdirect_socket *sc,
return bytes;
}
-/* Perform SMBD negotiate according to [MS-SMBD] 3.1.5.2 */
-static int smbd_negotiate(struct smbdirect_socket *sc)
-{
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- int rc;
- struct smbdirect_recv_io *response = smbdirect_connection_get_recv_io(sc);
-
- WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_NEGOTIATE_NEEDED);
- sc->status = SMBDIRECT_SOCKET_NEGOTIATE_RUNNING;
-
- sc->recv_io.expected = SMBDIRECT_EXPECT_NEGOTIATE_REP;
- rc = smbdirect_connection_post_recv_io(response);
- log_rdma_event(INFO, "smbd_post_recv rc=%d iov.addr=0x%llx iov.length=%u iov.lkey=0x%x\n",
- rc, response->sge.addr,
- response->sge.length, response->sge.lkey);
- if (rc) {
- smbdirect_connection_put_recv_io(response);
- return rc;
- }
-
- rc = smbd_post_send_negotiate_req(sc);
- if (rc)
- return rc;
-
- rc = wait_event_interruptible_timeout(
- sc->status_wait,
- sc->status != SMBDIRECT_SOCKET_NEGOTIATE_RUNNING,
- msecs_to_jiffies(sp->negotiate_timeout_msec));
- log_rdma_event(INFO, "wait_event_interruptible_timeout rc=%d\n", rc);
-
- if (sc->status == SMBDIRECT_SOCKET_CONNECTED)
- return 0;
-
- if (rc == 0)
- rc = -ETIMEDOUT;
- else if (rc == -ERESTARTSYS)
- rc = -EINTR;
- else
- rc = -ENOTCONN;
-
- return rc;
-}
-
/*
* Destroy the transport and related RDMA and memory resources
* Need to go through all the pending counters and make sure on one is using
@@ -818,7 +210,7 @@ void smbd_destroy(struct TCP_Server_Info *server)
smbdirect_connection_destroy_sync(sc);
- destroy_workqueue(sc->workqueue);
+ destroy_workqueue(info->workqueue);
kfree(info);
server->smbd_conn = NULL;
}
@@ -840,10 +232,8 @@ int smbd_reconnect(struct TCP_Server_Info *server)
* This is possible if transport is disconnected and we haven't received
* notification from RDMA, but upper layer has detected timeout
*/
- if (server->smbd_conn->socket.status == SMBDIRECT_SOCKET_CONNECTED) {
- log_rdma_event(INFO, "disconnecting transport\n");
- smbd_destroy(server);
- }
+ log_rdma_event(INFO, "disconnecting transport\n");
+ smbd_destroy(server);
create_conn:
log_rdma_event(INFO, "creating rdma session\n");
@@ -863,18 +253,14 @@ int smbd_reconnect(struct TCP_Server_Info *server)
static struct smbd_connection *_smbd_get_connection(
struct TCP_Server_Info *server, struct sockaddr *dstaddr, int port)
{
- int rc;
+ struct net *net = cifs_net_ns(server);
struct smbd_connection *info;
struct smbdirect_socket *sc;
struct smbdirect_socket_parameters init_params = {};
struct smbdirect_socket_parameters *sp;
- struct rdma_conn_param conn_param;
- struct sockaddr_in *addr_in = (struct sockaddr_in *) dstaddr;
- struct ib_port_immutable port_immutable;
- __be32 ird_ord_hdr[2];
+ __be16 *sport;
char wq_name[80];
- struct workqueue_struct *workqueue;
- struct smbdirect_recv_io *recv_io;
+ int ret;
/*
* Create the initial parameters
@@ -898,143 +284,64 @@ static struct smbd_connection *_smbd_get_connection(
info = kzalloc(sizeof(struct smbd_connection), GFP_KERNEL);
if (!info)
return NULL;
- sc = &info->socket;
- scnprintf(wq_name, ARRAY_SIZE(wq_name), "smbd_%p", sc);
- workqueue = create_workqueue(wq_name);
- if (!workqueue)
+ scnprintf(wq_name, ARRAY_SIZE(wq_name), "smbd_%p", info);
+ info->workqueue = create_workqueue(wq_name);
+ if (!info->workqueue)
goto create_wq_failed;
- smbdirect_socket_prepare_create(sc, sp, workqueue);
+ sc = &info->socket;
+ ret = smbdirect_socket_init_new(net, sc);
+ if (ret)
+ goto socket_init_failed;
smbdirect_socket_set_logging(sc, NULL, smbd_logging_needed, smbd_logging_vaprintf);
- sc->ib.poll_ctx = IB_POLL_SOFTIRQ;
- /*
- * from here we operate on the copy.
- */
- sp = &sc->parameters;
-
- rc = smbd_ia_open(sc, dstaddr, port);
- if (rc) {
- log_rdma_event(INFO, "smbd_ia_open rc=%d\n", rc);
- goto create_id_failed;
- }
-
- sp->responder_resources =
- min_t(u8, sp->responder_resources,
- sc->ib.dev->attrs.max_qp_rd_atom);
- log_rdma_mr(INFO, "responder_resources=%d\n",
- sp->responder_resources);
-
- rc = smbdirect_connection_create_qp(sc);
- if (rc) {
- log_rdma_event(ERR, "smbdirect_connection_create_qp failed %i\n", rc);
- goto create_qp_failed;
- }
-
- memset(&conn_param, 0, sizeof(conn_param));
- conn_param.initiator_depth = sp->initiator_depth;
- conn_param.responder_resources = sp->responder_resources;
-
- /* Need to send IRD/ORD in private data for iWARP */
- sc->ib.dev->ops.get_port_immutable(
- sc->ib.dev, sc->rdma.cm_id->port_num, &port_immutable);
- if (port_immutable.core_cap_flags & RDMA_CORE_PORT_IWARP) {
- ird_ord_hdr[0] = cpu_to_be32(conn_param.responder_resources);
- ird_ord_hdr[1] = cpu_to_be32(conn_param.initiator_depth);
- conn_param.private_data = ird_ord_hdr;
- conn_param.private_data_len = sizeof(ird_ord_hdr);
- } else {
- conn_param.private_data = NULL;
- conn_param.private_data_len = 0;
- }
-
- conn_param.retry_count = SMBD_CM_RETRY;
- conn_param.rnr_retry_count = SMBD_CM_RNR_RETRY;
- conn_param.flow_control = 0;
-
- log_rdma_event(INFO, "connecting to IP %pI4 port %d\n",
- &addr_in->sin_addr, port);
-
- 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);
- goto rdma_connect_failed;
- }
-
- wait_event_interruptible_timeout(
- sc->status_wait,
- sc->status != SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING,
- msecs_to_jiffies(sp->rdma_connect_timeout_msec));
-
- if (sc->status != SMBDIRECT_SOCKET_NEGOTIATE_NEEDED) {
- log_rdma_event(ERR, "rdma_connect failed port=%d\n", port);
- goto rdma_connect_failed;
- }
-
- log_rdma_event(INFO, "rdma_connect connected\n");
-
- rc = smbdirect_connection_create_mem_pools(sc);
- if (rc) {
- log_rdma_event(ERR, "cache allocation failed\n");
- goto allocate_cache_failed;
- }
+ ret = smbdirect_socket_set_initial_parameters(sc, sp);
+ if (ret)
+ goto set_params_failed;
+ ret = smbdirect_socket_set_kernel_settings(sc, IB_POLL_SOFTIRQ, GFP_KERNEL);
+ if (ret)
+ goto set_settings_failed;
+ ret = smbdirect_socket_set_custom_workqueue(sc, info->workqueue);
+ if (ret)
+ goto set_workqueue_failed;
- list_for_each_entry(recv_io, &sc->recv_io.free.list, list)
- recv_io->cqe.done = recv_done;
-
- INIT_WORK(&sc->idle.immediate_work, smbdirect_connection_send_immediate_work);
- /*
- * start with the negotiate timeout and SMBDIRECT_KEEPALIVE_PENDING
- * so that the timer will cause a disconnect.
- */
- sc->idle.keepalive = SMBDIRECT_KEEPALIVE_PENDING;
- mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
- msecs_to_jiffies(sp->negotiate_timeout_msec));
-
- INIT_WORK(&sc->recv_io.posted.refill_work, smbdirect_connection_recv_io_refill_work);
+ if (dstaddr->sa_family == AF_INET6)
+ sport = &((struct sockaddr_in6 *)dstaddr)->sin6_port;
+ else
+ sport = &((struct sockaddr_in *)dstaddr)->sin_port;
- rc = smbd_negotiate(sc);
- if (rc) {
- log_rdma_event(ERR, "smbd_negotiate rc=%d\n", rc);
- goto negotiation_failed;
- }
+ *sport = htons(port);
- rc = smbdirect_connection_create_mr_list(sc);
- if (rc) {
- log_rdma_mr(ERR, "memory registration allocation failed\n");
- goto allocate_mr_failed;
+ ret = smbdirect_connect_sync(sc, dstaddr);
+ if (ret) {
+ log_rdma_event(ERR, "smbdirect_connect_sync(%pISpsfc) failed with %d %s\n",
+ dstaddr, ret, errname(ret));
+ goto connect_failed;
}
return info;
-allocate_mr_failed:
+connect_failed:
+set_workqueue_failed:
+set_settings_failed:
+set_params_failed:
/* At this point, need to a full transport shutdown */
server->smbd_conn = info;
smbd_destroy(server);
return NULL;
-negotiation_failed:
- disable_delayed_work_sync(&sc->idle.timer_work);
- smbdirect_connection_destroy_mem_pools(sc);
- sc->status = SMBDIRECT_SOCKET_NEGOTIATE_FAILED;
- rdma_disconnect(sc->rdma.cm_id);
- wait_event(sc->status_wait,
- sc->status == SMBDIRECT_SOCKET_DISCONNECTED);
-
-allocate_cache_failed:
-rdma_connect_failed:
- smbdirect_connection_destroy_qp(sc);
-
-create_qp_failed:
- rdma_destroy_id(sc->rdma.cm_id);
-
-create_id_failed:
- destroy_workqueue(sc->workqueue);
+socket_init_failed:
+ destroy_workqueue(info->workqueue);
create_wq_failed:
kfree(info);
return NULL;
}
+const struct smbdirect_socket_parameters *smbd_get_parameters(struct smbd_connection *conn)
+{
+ struct smbdirect_socket *sc = &conn->socket;
+
+ return smbdirect_socket_get_current_parameters(sc);
+}
+
struct smbd_connection *smbd_get_connection(
struct TCP_Server_Info *server, struct sockaddr *dstaddr)
{
@@ -1053,7 +360,7 @@ struct smbd_connection *smbd_get_connection(
if (!ret)
return NULL;
- sp = &ret->socket.parameters;
+ sp = smbd_get_parameters(ret);
server->rdma_readwrite_threshold =
rdma_readwrite_threshold > sp->max_fragmented_send_size ?
@@ -1081,6 +388,9 @@ int smbd_recv(struct smbd_connection *info, struct msghdr *msg)
{
struct smbdirect_socket *sc = &info->socket;
+ if (!smbdirect_connection_is_connected(sc))
+ return -ENOTCONN;
+
return smbdirect_connection_recvmsg(sc, msg, 0);
}
@@ -1095,14 +405,14 @@ int smbd_send(struct TCP_Server_Info *server,
{
struct smbd_connection *info = server->smbd_conn;
struct smbdirect_socket *sc = &info->socket;
- struct smbdirect_socket_parameters *sp = &sc->parameters;
+ const struct smbdirect_socket_parameters *sp = smbd_get_parameters(info);
struct smb_rqst *rqst;
struct iov_iter iter;
unsigned int remaining_data_length, klen;
int rc, i, rqst_idx;
int error = 0;
- if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
+ if (!smbdirect_connection_is_connected(sc))
return -EAGAIN;
/*
@@ -1192,6 +502,9 @@ struct smbdirect_mr_io *smbd_register_mr(struct smbd_connection *info,
{
struct smbdirect_socket *sc = &info->socket;
+ if (!smbdirect_connection_is_connected(sc))
+ return NULL;
+
return smbdirect_connection_register_mr_io(sc, iter, writing, need_invalidate);
}
diff --git a/fs/smb/client/smbdirect.h b/fs/smb/client/smbdirect.h
index 7986e87bf384..3f623a37aedc 100644
--- a/fs/smb/client/smbdirect.h
+++ b/fs/smb/client/smbdirect.h
@@ -38,6 +38,7 @@ extern int smbd_receive_credit_max;
*/
struct smbd_connection {
struct smbdirect_socket socket;
+ struct workqueue_struct *workqueue;
};
/* Create a SMBDirect session */
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 089/127] smb: client: make use of smbdirect_socket_create_kern()/smbdirect_socket_release()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (87 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 088/127] smb: client: make use of smbdirect_socket_init_new() and smbdirect_connect_sync() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 090/127] smb: client: only use public smbdirect functions Stefan Metzmacher
` (38 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
With this we no longer embed struct smbdirect_socket, which will allow
us to make it private in the following commits.
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smbdirect.c | 30 ++++++++++++++----------------
fs/smb/client/smbdirect.h | 2 +-
2 files changed, 15 insertions(+), 17 deletions(-)
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 922001875d9b..1efbc15879f4 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -200,15 +200,13 @@ static int smbd_post_send_full_iter(struct smbdirect_socket *sc,
void smbd_destroy(struct TCP_Server_Info *server)
{
struct smbd_connection *info = server->smbd_conn;
- struct smbdirect_socket *sc;
if (!info) {
log_rdma_event(INFO, "rdma session already destroyed\n");
return;
}
- sc = &info->socket;
- smbdirect_connection_destroy_sync(sc);
+ smbdirect_socket_release(info->socket);
destroy_workqueue(info->workqueue);
kfree(info);
@@ -288,8 +286,7 @@ static struct smbd_connection *_smbd_get_connection(
info->workqueue = create_workqueue(wq_name);
if (!info->workqueue)
goto create_wq_failed;
- sc = &info->socket;
- ret = smbdirect_socket_init_new(net, sc);
+ ret = smbdirect_socket_create_kern(net, &sc);
if (ret)
goto socket_init_failed;
smbdirect_socket_set_logging(sc, NULL, smbd_logging_needed, smbd_logging_vaprintf);
@@ -317,17 +314,14 @@ static struct smbd_connection *_smbd_get_connection(
goto connect_failed;
}
+ info->socket = sc;
return info;
connect_failed:
set_workqueue_failed:
set_settings_failed:
set_params_failed:
- /* At this point, need to a full transport shutdown */
- server->smbd_conn = info;
- smbd_destroy(server);
- return NULL;
-
+ smbdirect_socket_release(sc);
socket_init_failed:
destroy_workqueue(info->workqueue);
create_wq_failed:
@@ -337,9 +331,13 @@ static struct smbd_connection *_smbd_get_connection(
const struct smbdirect_socket_parameters *smbd_get_parameters(struct smbd_connection *conn)
{
- struct smbdirect_socket *sc = &conn->socket;
+ if (unlikely(!conn->socket)) {
+ static const struct smbdirect_socket_parameters zero_params;
+
+ return &zero_params;
+ }
- return smbdirect_socket_get_current_parameters(sc);
+ return smbdirect_socket_get_current_parameters(conn->socket);
}
struct smbd_connection *smbd_get_connection(
@@ -386,7 +384,7 @@ struct smbd_connection *smbd_get_connection(
*/
int smbd_recv(struct smbd_connection *info, struct msghdr *msg)
{
- struct smbdirect_socket *sc = &info->socket;
+ struct smbdirect_socket *sc = info->socket;
if (!smbdirect_connection_is_connected(sc))
return -ENOTCONN;
@@ -404,7 +402,7 @@ int smbd_send(struct TCP_Server_Info *server,
int num_rqst, struct smb_rqst *rqst_array)
{
struct smbd_connection *info = server->smbd_conn;
- struct smbdirect_socket *sc = &info->socket;
+ struct smbdirect_socket *sc = info->socket;
const struct smbdirect_socket_parameters *sp = smbd_get_parameters(info);
struct smb_rqst *rqst;
struct iov_iter iter;
@@ -500,7 +498,7 @@ struct smbdirect_mr_io *smbd_register_mr(struct smbd_connection *info,
struct iov_iter *iter,
bool writing, bool need_invalidate)
{
- struct smbdirect_socket *sc = &info->socket;
+ struct smbdirect_socket *sc = info->socket;
if (!smbdirect_connection_is_connected(sc))
return NULL;
@@ -535,7 +533,7 @@ void smbd_debug_proc_show(struct TCP_Server_Info *server, struct seq_file *m)
return;
}
- smbdirect_connection_legacy_debug_proc_show(&server->smbd_conn->socket,
+ smbdirect_connection_legacy_debug_proc_show(server->smbd_conn->socket,
server->rdma_readwrite_threshold,
m);
}
diff --git a/fs/smb/client/smbdirect.h b/fs/smb/client/smbdirect.h
index 3f623a37aedc..35172076f2ee 100644
--- a/fs/smb/client/smbdirect.h
+++ b/fs/smb/client/smbdirect.h
@@ -37,7 +37,7 @@ extern int smbd_receive_credit_max;
* 5. mempools for allocating packets
*/
struct smbd_connection {
- struct smbdirect_socket socket;
+ struct smbdirect_socket *socket;
struct workqueue_struct *workqueue;
};
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 090/127] smb: client: only use public smbdirect functions
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (88 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 089/127] smb: client: make use of smbdirect_socket_create_kern()/smbdirect_socket_release() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 091/127] smb: client: make use of smbdirect.ko Stefan Metzmacher
` (37 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon
Also remove a lot of unused includes...
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: 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>
---
fs/smb/client/smb2pdu.c | 1 -
fs/smb/client/smbdirect.c | 20 +++++++++-----------
fs/smb/client/smbdirect.h | 13 -------------
3 files changed, 9 insertions(+), 25 deletions(-)
diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
index a9a04c4db6dc..40c918e7ee7d 100644
--- a/fs/smb/client/smb2pdu.c
+++ b/fs/smb/client/smb2pdu.c
@@ -36,7 +36,6 @@
#include "smb2glob.h"
#include "cifspdu.h"
#include "cifs_spnego.h"
-#include "../common/smbdirect/smbdirect.h"
#include "smbdirect.h"
#include "trace.h"
#ifdef CONFIG_CIFS_DFS_UPCALL
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 1efbc15879f4..91ed47ff8f2b 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -7,14 +7,12 @@
#define SMBDIRECT_USE_INLINE_C_FILES 1
-#include <linux/module.h>
-#include <linux/highmem.h>
-#include <linux/folio_queue.h>
#include <linux/errname.h>
#include "smbdirect.h"
#include "cifs_debug.h"
#include "cifsproto.h"
#include "smb2proto.h"
+#include "../common/smbdirect/smbdirect_public.h"
/* Port numbers for SMBD transport */
#define SMB_PORT 445
@@ -95,14 +93,6 @@ module_param(smbd_logging_level, uint, 0644);
MODULE_PARM_DESC(smbd_logging_level,
"Logging level for SMBD transport, 0 (default): error, 1: info");
-/*
- * This is a temporary solution until all code
- * is moved to smbdirect_all_c_files.c and we
- * have an smbdirect.ko that exports the required
- * functions.
- */
-#include "../common/smbdirect/smbdirect_all_c_files.c"
-
static bool smbd_logging_needed(struct smbdirect_socket *sc,
void *private_ptr,
unsigned int lvl,
@@ -537,3 +527,11 @@ void smbd_debug_proc_show(struct TCP_Server_Info *server, struct seq_file *m)
server->rdma_readwrite_threshold,
m);
}
+
+/*
+ * This is a temporary solution until all code
+ * is moved to smbdirect_all_c_files.c and we
+ * have an smbdirect.ko that exports the required
+ * functions.
+ */
+#include "../common/smbdirect/smbdirect_all_c_files.c"
diff --git a/fs/smb/client/smbdirect.h b/fs/smb/client/smbdirect.h
index 35172076f2ee..bd03ae72e9c8 100644
--- a/fs/smb/client/smbdirect.h
+++ b/fs/smb/client/smbdirect.h
@@ -11,12 +11,8 @@
#define cifs_rdma_enabled(server) ((server)->rdma)
#include "cifsglob.h"
-#include <rdma/ib_verbs.h>
-#include <rdma/rdma_cm.h>
-#include <linux/mempool.h>
#include "../common/smbdirect/smbdirect.h"
-#include "../common/smbdirect/smbdirect_socket.h"
extern int rdma_readwrite_threshold;
extern int smbd_max_frmr_depth;
@@ -27,15 +23,6 @@ extern int smbd_max_send_size;
extern int smbd_send_credit_target;
extern int smbd_receive_credit_max;
-/*
- * The context for the SMBDirect transport
- * Everything related to the transport is here. It has several logical parts
- * 1. RDMA related structures
- * 2. SMBDirect connection parameters
- * 3. Memory registrations
- * 4. Receive and reassembly queues for data receive path
- * 5. mempools for allocating packets
- */
struct smbd_connection {
struct smbdirect_socket *socket;
struct workqueue_struct *workqueue;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 091/127] smb: client: make use of smbdirect.ko
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (89 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 090/127] smb: client: only use public smbdirect functions Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 092/127] smb: server: make use of smbdirect_socket_prepare_create() Stefan Metzmacher
` (36 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Steve French, Tom Talpey, Long Li, Namjae Jeon,
David Howells
This means we no longer inline the common smbdirect
.c files and use the exported functions from the
module instead.
Note the connection specific logging is still
redirect to cifs.ko functions via
smbdirect_socket_set_logging().
We still don't use real socket layer,
but we're very close...
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: Namjae Jeon <linkinjeon@kernel.org>
Cc: David Howells <dhowells@redhat.com>
Cc: linux-cifs@vger.kernel.org
Cc: samba-technical@lists.samba.org
Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
fs/smb/client/Kconfig | 3 ++-
fs/smb/client/smbdirect.c | 10 ----------
2 files changed, 2 insertions(+), 11 deletions(-)
diff --git a/fs/smb/client/Kconfig b/fs/smb/client/Kconfig
index 17bd368574e9..72f47669da0c 100644
--- a/fs/smb/client/Kconfig
+++ b/fs/smb/client/Kconfig
@@ -181,7 +181,8 @@ if CIFS
config CIFS_SMB_DIRECT
bool "SMB Direct support"
- depends on CIFS=m && INFINIBAND && INFINIBAND_ADDR_TRANS || CIFS=y && INFINIBAND=y && INFINIBAND_ADDR_TRANS=y
+ depends on CIFS && INFINIBAND && INFINIBAND_ADDR_TRANS
+ select SMB_COMMON_SMBDIRECT
help
Enables SMB Direct support for SMB 3.0, 3.02 and 3.1.1.
SMB Direct allows transferring SMB packets over RDMA. If unsure,
diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
index 91ed47ff8f2b..0c3a4b6aa03f 100644
--- a/fs/smb/client/smbdirect.c
+++ b/fs/smb/client/smbdirect.c
@@ -5,8 +5,6 @@
* Author(s): Long Li <longli@microsoft.com>
*/
-#define SMBDIRECT_USE_INLINE_C_FILES 1
-
#include <linux/errname.h>
#include "smbdirect.h"
#include "cifs_debug.h"
@@ -527,11 +525,3 @@ void smbd_debug_proc_show(struct TCP_Server_Info *server, struct seq_file *m)
server->rdma_readwrite_threshold,
m);
}
-
-/*
- * This is a temporary solution until all code
- * is moved to smbdirect_all_c_files.c and we
- * have an smbdirect.ko that exports the required
- * functions.
- */
-#include "../common/smbdirect/smbdirect_all_c_files.c"
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 092/127] smb: server: make use of smbdirect_socket_prepare_create()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (90 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 091/127] smb: client: make use of smbdirect.ko Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 093/127] smb: server: make use of smbdirect_socket_set_logging() Stefan Metzmacher
` (35 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Namjae Jeon, Steve French, Tom Talpey, Steve French
This prepares the use of functions from smbdirect_connection.c.
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>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/smb/server/transport_rdma.c | 28 +++++++++++++++++-----------
1 file changed, 17 insertions(+), 11 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 9bf023b797ad..bcc584884f29 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -397,20 +397,14 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
{
struct smb_direct_transport *t;
struct smbdirect_socket *sc;
+ struct smbdirect_socket_parameters init_params = {};
struct smbdirect_socket_parameters *sp;
struct ksmbd_conn *conn;
- t = kzalloc(sizeof(*t), KSMBD_DEFAULT_GFP);
- if (!t)
- return NULL;
- sc = &t->socket;
- smbdirect_socket_init(sc);
- sp = &sc->parameters;
-
- sc->workqueue = smb_direct_wq;
-
- INIT_WORK(&sc->disconnect_work, smb_direct_disconnect_rdma_work);
-
+ /*
+ * 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;
@@ -423,6 +417,18 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
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;
+ sc = &t->socket;
+ smbdirect_socket_prepare_create(sc, sp, smb_direct_wq);
+ /*
+ * from here we operate on the copy.
+ */
+ sp = &sc->parameters;
+
+ INIT_WORK(&sc->disconnect_work, smb_direct_disconnect_rdma_work);
+
sc->rdma.cm_id = cm_id;
cm_id->context = sc;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 093/127] smb: server: make use of smbdirect_socket_set_logging()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (91 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 092/127] smb: server: make use of smbdirect_socket_prepare_create() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 094/127] smb: server: make use of smbdirect_connection_wake_up_all() Stefan Metzmacher
` (34 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical; +Cc: metze, Namjae Jeon, Steve French, Tom Talpey
This will allow the logging to keep working as before,
when we move to common functions in the next commits.
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>
---
fs/smb/server/transport_rdma.c | 62 ++++++++++++++++++++++++++++++++++
1 file changed, 62 insertions(+)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index bcc584884f29..fa6371ed0b76 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -109,6 +109,65 @@ struct smb_direct_transport {
struct smbdirect_socket socket;
};
+static bool smb_direct_logging_needed(struct smbdirect_socket *sc,
+ void *private_ptr,
+ unsigned int lvl,
+ unsigned int cls)
+{
+ if (lvl <= SMBDIRECT_LOG_ERR)
+ return true;
+
+ if (lvl > SMBDIRECT_LOG_INFO)
+ return false;
+
+ switch (cls) {
+ /*
+ * These were more or less also logged before
+ * the move to common code.
+ *
+ * SMBDIRECT_LOG_RDMA_MR was not used, but
+ * that's client only code and we should
+ * notice if it's used on the server...
+ */
+ case SMBDIRECT_LOG_RDMA_EVENT:
+ case SMBDIRECT_LOG_RDMA_SEND:
+ case SMBDIRECT_LOG_RDMA_RECV:
+ case SMBDIRECT_LOG_WRITE:
+ case SMBDIRECT_LOG_READ:
+ case SMBDIRECT_LOG_NEGOTIATE:
+ case SMBDIRECT_LOG_OUTGOING:
+ case SMBDIRECT_LOG_RDMA_RW:
+ case SMBDIRECT_LOG_RDMA_MR:
+ return true;
+ /*
+ * These were not logged before the move
+ * to common code.
+ */
+ case SMBDIRECT_LOG_KEEP_ALIVE:
+ case SMBDIRECT_LOG_INCOMING:
+ return false;
+ }
+
+ /*
+ * Log all unknown messages
+ */
+ return true;
+}
+
+static void smb_direct_logging_vaprintf(struct smbdirect_socket *sc,
+ const char *func,
+ unsigned int line,
+ void *private_ptr,
+ unsigned int lvl,
+ unsigned int cls,
+ struct va_format *vaf)
+{
+ if (lvl <= SMBDIRECT_LOG_ERR)
+ pr_err("%pV", vaf);
+ else
+ ksmbd_debug(RDMA, "%pV", vaf);
+}
+
#define KSMBD_TRANS(t) (&(t)->transport)
#define SMBD_TRANS(t) (container_of(t, \
struct smb_direct_transport, transport))
@@ -422,6 +481,9 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
return NULL;
sc = &t->socket;
smbdirect_socket_prepare_create(sc, sp, smb_direct_wq);
+ smbdirect_socket_set_logging(sc, NULL,
+ smb_direct_logging_needed,
+ smb_direct_logging_vaprintf);
/*
* from here we operate on the copy.
*/
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 094/127] smb: server: make use of smbdirect_connection_wake_up_all()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (92 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 093/127] smb: server: make use of smbdirect_socket_set_logging() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 095/127] smb: server: make use of smbdirect_connection_disconnect_work() Stefan Metzmacher
` (33 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Namjae Jeon, Steve French, Tom Talpey, Steve French
This is a superset of smb_direct_disconnect_wake_up_all() and
calling wake_up_all(&sc->mr_io.ready.wait_queue); and
wake_up_all(&sc->mr_io.cleanup.wait_queue); in addition
should not matter as it's not used on the server anyway.
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>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/smb/server/transport_rdma.c | 20 +++-----------------
1 file changed, 3 insertions(+), 17 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index fa6371ed0b76..b78753801fe5 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -281,20 +281,6 @@ static struct smbdirect_recv_io *get_first_reassembly(struct smbdirect_socket *s
return NULL;
}
-static void smb_direct_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.lcredits.wait_queue);
- wake_up_all(&sc->send_io.credits.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->rw_io.credits.wait_queue);
-}
-
static void smb_direct_disconnect_rdma_work(struct work_struct *work)
{
struct smbdirect_socket *sc =
@@ -350,7 +336,7 @@ static void smb_direct_disconnect_rdma_work(struct work_struct *work)
* Wake up all waiters in all wait queues
* in order to notice the broken connection.
*/
- smb_direct_disconnect_wake_up_all(sc);
+ smbdirect_connection_wake_up_all(sc);
}
static void
@@ -412,7 +398,7 @@ smb_direct_disconnect_rdma_connection(struct smbdirect_socket *sc)
* Wake up all waiters in all wait queues
* in order to notice the broken connection.
*/
- smb_direct_disconnect_wake_up_all(sc);
+ smbdirect_connection_wake_up_all(sc);
queue_work(sc->workqueue, &sc->disconnect_work);
}
@@ -538,7 +524,7 @@ static void free_transport(struct smb_direct_transport *t)
* Most likely this was already called via
* smb_direct_disconnect_rdma_work(), but call it again...
*/
- smb_direct_disconnect_wake_up_all(sc);
+ smbdirect_connection_wake_up_all(sc);
disable_work_sync(&sc->recv_io.posted.refill_work);
disable_delayed_work_sync(&sc->idle.timer_work);
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 095/127] smb: server: make use of smbdirect_connection_disconnect_work()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (93 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 094/127] smb: server: make use of smbdirect_connection_wake_up_all() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 096/127] smb: server: make use of smbdirect_connection_schedule_disconnect() Stefan Metzmacher
` (32 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Namjae Jeon, Steve French, Tom Talpey, Steve French
Note smbdirect_socket_prepare_create() already calls INIT_WORK()
with smbdirect_connection_disconnect_work.
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>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/smb/server/transport_rdma.c | 70 +++-------------------------------
1 file changed, 5 insertions(+), 65 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index b78753801fe5..a649194ab6c8 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -281,64 +281,6 @@ static struct smbdirect_recv_io *get_first_reassembly(struct smbdirect_socket *s
return NULL;
}
-static void smb_direct_disconnect_rdma_work(struct work_struct *work)
-{
- struct smbdirect_socket *sc =
- container_of(work, struct smbdirect_socket, disconnect_work);
-
- /*
- * make sure this and other work is not queued again
- * but here we don't block and avoid
- * disable[_delayed]_work_sync()
- */
- disable_work(&sc->disconnect_work);
- disable_work(&sc->recv_io.posted.refill_work);
- disable_delayed_work(&sc->idle.timer_work);
- disable_work(&sc->idle.immediate_work);
-
- if (sc->first_error == 0)
- sc->first_error = -ECONNABORTED;
-
- 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;
- }
-
- /*
- * Wake up all waiters in all wait queues
- * in order to notice the broken connection.
- */
- smbdirect_connection_wake_up_all(sc);
-}
-
static void
smb_direct_disconnect_rdma_connection(struct smbdirect_socket *sc)
{
@@ -475,8 +417,6 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
*/
sp = &sc->parameters;
- INIT_WORK(&sc->disconnect_work, smb_direct_disconnect_rdma_work);
-
sc->rdma.cm_id = cm_id;
cm_id->context = sc;
@@ -513,7 +453,7 @@ static void free_transport(struct smb_direct_transport *t)
disable_work_sync(&sc->disconnect_work);
if (sc->status < SMBDIRECT_SOCKET_DISCONNECTING)
- smb_direct_disconnect_rdma_work(&sc->disconnect_work);
+ smbdirect_connection_disconnect_work(&sc->disconnect_work);
if (sc->status < SMBDIRECT_SOCKET_DISCONNECTED)
wait_event(sc->status_wait, sc->status == SMBDIRECT_SOCKET_DISCONNECTED);
@@ -522,7 +462,7 @@ static void free_transport(struct smb_direct_transport *t)
* in order to notice the broken connection.
*
* Most likely this was already called via
- * smb_direct_disconnect_rdma_work(), but call it again...
+ * smbdirect_connection_disconnect_work(), but call it again...
*/
smbdirect_connection_wake_up_all(sc);
@@ -1773,7 +1713,7 @@ static void smb_direct_shutdown(struct ksmbd_transport *t)
ksmbd_debug(RDMA, "smb-direct shutdown cm_id=%p\n", sc->rdma.cm_id);
- smb_direct_disconnect_rdma_work(&sc->disconnect_work);
+ smbdirect_connection_disconnect_work(&sc->disconnect_work);
}
static int smb_direct_cm_handler(struct rdma_cm_id *cm_id,
@@ -1794,14 +1734,14 @@ static int smb_direct_cm_handler(struct rdma_cm_id *cm_id,
case RDMA_CM_EVENT_DEVICE_REMOVAL:
case RDMA_CM_EVENT_DISCONNECTED: {
sc->status = SMBDIRECT_SOCKET_DISCONNECTED;
- smb_direct_disconnect_rdma_work(&sc->disconnect_work);
+ smbdirect_connection_disconnect_work(&sc->disconnect_work);
if (sc->ib.qp)
ib_drain_qp(sc->ib.qp);
break;
}
case RDMA_CM_EVENT_CONNECT_ERROR: {
sc->status = SMBDIRECT_SOCKET_DISCONNECTED;
- smb_direct_disconnect_rdma_work(&sc->disconnect_work);
+ smbdirect_connection_disconnect_work(&sc->disconnect_work);
break;
}
default:
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 096/127] smb: server: make use of smbdirect_connection_schedule_disconnect()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (94 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 095/127] smb: server: make use of smbdirect_connection_disconnect_work() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 097/127] smb: server: make use of smbdirect_connection_{get,put}_recv_io() Stefan Metzmacher
` (31 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Namjae Jeon, Steve French, Tom Talpey, Steve French
This removes smb_direct_disconnect_rdma_connection() which is basically
the same as smbdirect_connection_schedule_disconnect().
And we pass more useful errors than -ECONNABORTED if we have them.
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>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/smb/server/transport_rdma.c | 88 +++++-----------------------------
1 file changed, 12 insertions(+), 76 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index a649194ab6c8..89db1cc921d2 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -281,70 +281,6 @@ static struct smbdirect_recv_io *get_first_reassembly(struct smbdirect_socket *s
return NULL;
}
-static void
-smb_direct_disconnect_rdma_connection(struct smbdirect_socket *sc)
-{
- /*
- * make sure other work (than disconnect_work) is
- * not queued again but here we don't block and avoid
- * disable[_delayed]_work_sync()
- */
- disable_work(&sc->recv_io.posted.refill_work);
- disable_work(&sc->idle.immediate_work);
- disable_delayed_work(&sc->idle.timer_work);
-
- if (sc->first_error == 0)
- sc->first_error = -ECONNABORTED;
-
- switch (sc->status) {
- case SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED:
- case SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED:
- case SMBDIRECT_SOCKET_RDMA_CONNECT_FAILED:
- case SMBDIRECT_SOCKET_NEGOTIATE_FAILED:
- case SMBDIRECT_SOCKET_ERROR:
- case SMBDIRECT_SOCKET_DISCONNECTING:
- case SMBDIRECT_SOCKET_DISCONNECTED:
- case SMBDIRECT_SOCKET_DESTROYED:
- /*
- * Keep the current error status
- */
- break;
-
- case SMBDIRECT_SOCKET_RESOLVE_ADDR_NEEDED:
- case SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING:
- sc->status = SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED;
- break;
-
- case SMBDIRECT_SOCKET_RESOLVE_ROUTE_NEEDED:
- case SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING:
- sc->status = SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED;
- break;
-
- case SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED:
- case SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING:
- sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_FAILED;
- break;
-
- case SMBDIRECT_SOCKET_NEGOTIATE_NEEDED:
- case SMBDIRECT_SOCKET_NEGOTIATE_RUNNING:
- sc->status = SMBDIRECT_SOCKET_NEGOTIATE_FAILED;
- break;
-
- case SMBDIRECT_SOCKET_CREATED:
- case SMBDIRECT_SOCKET_CONNECTED:
- sc->status = SMBDIRECT_SOCKET_ERROR;
- break;
- }
-
- /*
- * Wake up all waiters in all wait queues
- * in order to notice the broken connection.
- */
- smbdirect_connection_wake_up_all(sc);
-
- queue_work(sc->workqueue, &sc->disconnect_work);
-}
-
static void smb_direct_send_immediate_work(struct work_struct *work)
{
struct smbdirect_socket *sc =
@@ -363,7 +299,7 @@ static void smb_direct_idle_connection_timer(struct work_struct *work)
struct smbdirect_socket_parameters *sp = &sc->parameters;
if (sc->idle.keepalive != SMBDIRECT_KEEPALIVE_NONE) {
- smb_direct_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, -ETIMEDOUT);
return;
}
@@ -612,7 +548,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
pr_err("Recv error. status='%s (%d)' opcode=%d\n",
ib_wc_status_msg(wc->status), wc->status,
wc->opcode);
- smb_direct_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
}
return;
}
@@ -636,7 +572,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
case SMBDIRECT_EXPECT_NEGOTIATE_REQ:
if (wc->byte_len < sizeof(struct smbdirect_negotiate_req)) {
put_recvmsg(sc, recvmsg);
- smb_direct_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
return;
}
sc->recv_io.reassembly.full_packet_received = true;
@@ -654,7 +590,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
if (wc->byte_len <
offsetof(struct smbdirect_data_transfer, padding)) {
put_recvmsg(sc, recvmsg);
- smb_direct_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
return;
}
@@ -664,7 +600,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
if (wc->byte_len < data_offset ||
wc->byte_len < (u64)data_offset + data_length) {
put_recvmsg(sc, recvmsg);
- smb_direct_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
return;
}
if (remaining_data_length > sp->max_fragmented_recv_size ||
@@ -672,7 +608,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
(u64)remaining_data_length + (u64)data_length >
(u64)sp->max_fragmented_recv_size) {
put_recvmsg(sc, recvmsg);
- smb_direct_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
return;
}
@@ -727,7 +663,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
*/
WARN_ON_ONCE(sc->recv_io.expected != SMBDIRECT_EXPECT_DATA_TRANSFER);
put_recvmsg(sc, recvmsg);
- smb_direct_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
}
static int smb_direct_post_recv(struct smbdirect_socket *sc,
@@ -760,7 +696,7 @@ static int smb_direct_post_recv(struct smbdirect_socket *sc,
recvmsg->sge.addr, recvmsg->sge.length,
DMA_FROM_DEVICE);
recvmsg->sge.length = 0;
- smb_direct_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, ret);
return ret;
}
return ret;
@@ -947,7 +883,7 @@ static void send_done(struct ib_cq *cq, struct ib_wc *wc)
pr_err("Send error. status='%s (%d)', opcode=%d\n",
ib_wc_status_msg(wc->status), wc->status,
wc->opcode);
- smb_direct_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
return;
}
@@ -1003,7 +939,7 @@ static int smb_direct_post_send(struct smbdirect_socket *sc,
ret = ib_post_send(sc->ib.qp, wr, NULL);
if (ret) {
pr_err("failed to post send: %d\n", ret);
- smb_direct_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, ret);
}
return ret;
}
@@ -1530,7 +1466,7 @@ static void read_write_done(struct ib_cq *cq, struct ib_wc *wc,
pr_err("read/write error. opcode = %d, status = %s(%d)\n",
wc->opcode, ib_wc_status_msg(wc->status), wc->status);
if (wc->status != IB_WC_WR_FLUSH_ERR)
- smb_direct_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, msg->error);
}
complete(msg->completion);
@@ -1763,7 +1699,7 @@ static void smb_direct_qpair_handler(struct ib_event *event, void *context)
switch (event->event) {
case IB_EVENT_CQ_ERR:
case IB_EVENT_QP_FATAL:
- smb_direct_disconnect_rdma_connection(sc);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
break;
default:
break;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 097/127] smb: server: make use of smbdirect_connection_{get,put}_recv_io()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (95 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 096/127] smb: server: make use of smbdirect_connection_schedule_disconnect() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 098/127] smb: server: make use of smbdirect_connection_reassembly_{append,first}_recv_io() Stefan Metzmacher
` (30 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Namjae Jeon, Steve French, Tom Talpey, Steve French
These are basically copies of {get,put}_receive_buffer() in the client.
They are very similar to {get_free,put}_recvmsg() the only logical
difference is the updating of the sc->statistics.*.
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>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/smb/server/transport_rdma.c | 67 ++++++++--------------------------
1 file changed, 15 insertions(+), 52 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 89db1cc921d2..cc64be846daf 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -215,43 +215,6 @@ static inline void
return (void *)recvmsg->packet;
}
-static struct
-smbdirect_recv_io *get_free_recvmsg(struct smbdirect_socket *sc)
-{
- struct smbdirect_recv_io *recvmsg = NULL;
- unsigned long flags;
-
- spin_lock_irqsave(&sc->recv_io.free.lock, flags);
- if (!list_empty(&sc->recv_io.free.list)) {
- recvmsg = list_first_entry(&sc->recv_io.free.list,
- struct smbdirect_recv_io,
- list);
- list_del(&recvmsg->list);
- }
- spin_unlock_irqrestore(&sc->recv_io.free.lock, flags);
- return recvmsg;
-}
-
-static void put_recvmsg(struct smbdirect_socket *sc,
- struct smbdirect_recv_io *recvmsg)
-{
- unsigned long flags;
-
- if (likely(recvmsg->sge.length != 0)) {
- ib_dma_unmap_single(sc->ib.dev,
- recvmsg->sge.addr,
- recvmsg->sge.length,
- DMA_FROM_DEVICE);
- recvmsg->sge.length = 0;
- }
-
- spin_lock_irqsave(&sc->recv_io.free.lock, flags);
- list_add(&recvmsg->list, &sc->recv_io.free.list);
- spin_unlock_irqrestore(&sc->recv_io.free.lock, flags);
-
- queue_work(sc->workqueue, &sc->recv_io.posted.refill_work);
-}
-
static void enqueue_reassembly(struct smbdirect_socket *sc,
struct smbdirect_recv_io *recvmsg,
int data_length)
@@ -424,7 +387,7 @@ static void free_transport(struct smb_direct_transport *t)
if (recvmsg) {
list_del(&recvmsg->list);
spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags);
- put_recvmsg(sc, recvmsg);
+ smbdirect_connection_put_recv_io(recvmsg);
} else {
spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags);
}
@@ -543,7 +506,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
sp = &sc->parameters;
if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_RECV) {
- put_recvmsg(sc, recvmsg);
+ smbdirect_connection_put_recv_io(recvmsg);
if (wc->status != IB_WC_WR_FLUSH_ERR) {
pr_err("Recv error. status='%s (%d)' opcode=%d\n",
ib_wc_status_msg(wc->status), wc->status,
@@ -571,7 +534,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
switch (sc->recv_io.expected) {
case SMBDIRECT_EXPECT_NEGOTIATE_REQ:
if (wc->byte_len < sizeof(struct smbdirect_negotiate_req)) {
- put_recvmsg(sc, recvmsg);
+ smbdirect_connection_put_recv_io(recvmsg);
smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
return;
}
@@ -589,7 +552,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
if (wc->byte_len <
offsetof(struct smbdirect_data_transfer, padding)) {
- put_recvmsg(sc, recvmsg);
+ smbdirect_connection_put_recv_io(recvmsg);
smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
return;
}
@@ -599,7 +562,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
data_offset = le32_to_cpu(data_transfer->data_offset);
if (wc->byte_len < data_offset ||
wc->byte_len < (u64)data_offset + data_length) {
- put_recvmsg(sc, recvmsg);
+ smbdirect_connection_put_recv_io(recvmsg);
smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
return;
}
@@ -607,7 +570,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
data_length > sp->max_fragmented_recv_size ||
(u64)remaining_data_length + (u64)data_length >
(u64)sp->max_fragmented_recv_size) {
- put_recvmsg(sc, recvmsg);
+ smbdirect_connection_put_recv_io(recvmsg);
smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
return;
}
@@ -649,7 +612,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
enqueue_reassembly(sc, recvmsg, (int)data_length);
wake_up(&sc->recv_io.reassembly.wait_queue);
} else
- put_recvmsg(sc, recvmsg);
+ smbdirect_connection_put_recv_io(recvmsg);
return;
}
@@ -662,7 +625,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
* This is an internal error!
*/
WARN_ON_ONCE(sc->recv_io.expected != SMBDIRECT_EXPECT_DATA_TRANSFER);
- put_recvmsg(sc, recvmsg);
+ smbdirect_connection_put_recv_io(recvmsg);
smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
}
@@ -788,7 +751,7 @@ static int smb_direct_read(struct ksmbd_transport *t, char *buf,
spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags);
}
queue_removed++;
- put_recvmsg(sc, recvmsg);
+ smbdirect_connection_put_recv_io(recvmsg);
offset = 0;
} else {
offset += to_copy;
@@ -832,7 +795,7 @@ static void smb_direct_post_recv_credits(struct work_struct *work)
if (atomic_read(&sc->recv_io.credits.count) < sc->recv_io.credits.target) {
while (true) {
- recvmsg = get_free_recvmsg(sc);
+ recvmsg = smbdirect_connection_get_recv_io(sc);
if (!recvmsg)
break;
@@ -841,7 +804,7 @@ static void smb_direct_post_recv_credits(struct work_struct *work)
ret = smb_direct_post_recv(sc, recvmsg);
if (ret) {
pr_err("Can't post recv: %d\n", ret);
- put_recvmsg(sc, recvmsg);
+ smbdirect_connection_put_recv_io(recvmsg);
break;
}
credits++;
@@ -1830,7 +1793,7 @@ static int smb_direct_prepare_negotiation(struct smbdirect_socket *sc)
sc->recv_io.expected = SMBDIRECT_EXPECT_NEGOTIATE_REQ;
- recvmsg = get_free_recvmsg(sc);
+ recvmsg = smbdirect_connection_get_recv_io(sc);
if (!recvmsg)
return -ENOMEM;
@@ -1848,7 +1811,7 @@ static int smb_direct_prepare_negotiation(struct smbdirect_socket *sc)
return 0;
out_err:
- put_recvmsg(sc, recvmsg);
+ smbdirect_connection_put_recv_io(recvmsg);
return ret;
}
@@ -1888,7 +1851,7 @@ static void smb_direct_destroy_pools(struct smbdirect_socket *sc)
{
struct smbdirect_recv_io *recvmsg;
- while ((recvmsg = get_free_recvmsg(sc)))
+ while ((recvmsg = smbdirect_connection_get_recv_io(sc)))
mempool_free(recvmsg, sc->recv_io.mem.pool);
mempool_destroy(sc->recv_io.mem.pool);
@@ -2211,7 +2174,7 @@ static int smb_direct_prepare(struct ksmbd_transport *t)
sc->recv_io.reassembly.queue_length--;
list_del(&recvmsg->list);
spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags);
- put_recvmsg(sc, recvmsg);
+ smbdirect_connection_put_recv_io(recvmsg);
if (ret == -ECONNABORTED)
return ret;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 098/127] smb: server: make use of smbdirect_connection_reassembly_{append,first}_recv_io()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (96 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 097/127] smb: server: make use of smbdirect_connection_{get,put}_recv_io() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 099/127] smb: server: make use of smbdirect_connection_idle_timer_work() Stefan Metzmacher
` (29 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Namjae Jeon, Steve French, Tom Talpey, Steve French
These are basically copies of enqueue_reassembly() and
get_first_reassembly(). The only difference is that
sc->statistics.enqueue_reassembly_queue now updated.
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>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/smb/server/transport_rdma.c | 41 +++++-----------------------------
1 file changed, 6 insertions(+), 35 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index cc64be846daf..fdf8ac7d5d34 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -215,35 +215,6 @@ static inline void
return (void *)recvmsg->packet;
}
-static void enqueue_reassembly(struct smbdirect_socket *sc,
- struct smbdirect_recv_io *recvmsg,
- int data_length)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags);
- list_add_tail(&recvmsg->list, &sc->recv_io.reassembly.list);
- sc->recv_io.reassembly.queue_length++;
- /*
- * Make sure reassembly_data_length is updated after list and
- * reassembly_queue_length are updated. On the dequeue side
- * reassembly_data_length is checked without a lock to determine
- * if reassembly_queue_length and list is up to date
- */
- virt_wmb();
- sc->recv_io.reassembly.data_length += data_length;
- spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags);
-}
-
-static struct smbdirect_recv_io *get_first_reassembly(struct smbdirect_socket *sc)
-{
- if (!list_empty(&sc->recv_io.reassembly.list))
- return list_first_entry(&sc->recv_io.reassembly.list,
- struct smbdirect_recv_io, list);
- else
- return NULL;
-}
-
static void smb_direct_send_immediate_work(struct work_struct *work)
{
struct smbdirect_socket *sc =
@@ -383,7 +354,7 @@ static void free_transport(struct smb_direct_transport *t)
unsigned long flags;
spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags);
- recvmsg = get_first_reassembly(sc);
+ recvmsg = smbdirect_connection_reassembly_first_recv_io(sc);
if (recvmsg) {
list_del(&recvmsg->list);
spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags);
@@ -541,7 +512,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
sc->recv_io.reassembly.full_packet_received = true;
WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_NEGOTIATE_NEEDED);
sc->status = SMBDIRECT_SOCKET_NEGOTIATE_RUNNING;
- enqueue_reassembly(sc, recvmsg, 0);
+ smbdirect_connection_reassembly_append_recv_io(sc, recvmsg, 0);
wake_up(&sc->status_wait);
return;
case SMBDIRECT_EXPECT_DATA_TRANSFER: {
@@ -609,7 +580,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
if (sc->recv_io.credits.target > old_recv_credit_target)
queue_work(sc->workqueue, &sc->recv_io.posted.refill_work);
- enqueue_reassembly(sc, recvmsg, (int)data_length);
+ smbdirect_connection_reassembly_append_recv_io(sc, recvmsg, data_length);
wake_up(&sc->recv_io.reassembly.wait_queue);
} else
smbdirect_connection_put_recv_io(recvmsg);
@@ -695,7 +666,7 @@ static int smb_direct_read(struct ksmbd_transport *t, char *buf,
/*
* Need to make sure reassembly_data_length is read before
* reading reassembly_queue_length and calling
- * get_first_reassembly. This call is lock free
+ * smbdirect_connection_reassembly_first_recv_io. This call is lock free
* as we never read at the end of the queue which are being
* updated in SOFTIRQ as more data is received
*/
@@ -705,7 +676,7 @@ static int smb_direct_read(struct ksmbd_transport *t, char *buf,
to_read = size;
offset = sc->recv_io.reassembly.first_entry_offset;
while (data_read < size) {
- recvmsg = get_first_reassembly(sc);
+ recvmsg = smbdirect_connection_reassembly_first_recv_io(sc);
data_transfer = smbdirect_recv_io_payload(recvmsg);
data_length = le32_to_cpu(data_transfer->data_length);
remaining_data_length =
@@ -2148,7 +2119,7 @@ static int smb_direct_prepare(struct ksmbd_transport *t)
if (ret <= 0 || sc->status != SMBDIRECT_SOCKET_NEGOTIATE_RUNNING)
return ret < 0 ? ret : -ETIMEDOUT;
- recvmsg = get_first_reassembly(sc);
+ recvmsg = smbdirect_connection_reassembly_first_recv_io(sc);
if (!recvmsg)
return -ECONNABORTED;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 099/127] smb: server: make use of smbdirect_connection_idle_timer_work()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (97 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 098/127] smb: server: make use of smbdirect_connection_reassembly_{append,first}_recv_io() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 100/127] smb: server: make use of smbdirect_frwr_is_supported() Stefan Metzmacher
` (28 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Namjae Jeon, Steve French, Tom Talpey, Steve French
This is basically a copy of smb_direct_idle_connection_timer().
The only difference is that we had no logging before.
Note smbdirect_socket_prepare_create() already calls INIT_DELAYED_WORK().
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>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/smb/server/transport_rdma.c | 26 --------------------------
1 file changed, 26 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index fdf8ac7d5d34..886a350819bf 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -226,30 +226,6 @@ static void smb_direct_send_immediate_work(struct work_struct *work)
smb_direct_post_send_data(sc, NULL, NULL, 0, 0);
}
-static void smb_direct_idle_connection_timer(struct work_struct *work)
-{
- struct smbdirect_socket *sc =
- container_of(work, struct smbdirect_socket, idle.timer_work.work);
- struct smbdirect_socket_parameters *sp = &sc->parameters;
-
- if (sc->idle.keepalive != SMBDIRECT_KEEPALIVE_NONE) {
- smbdirect_connection_schedule_disconnect(sc, -ETIMEDOUT);
- return;
- }
-
- if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
- return;
-
- /*
- * Now use the keepalive timeout (instead of keepalive interval)
- * in order to wait for a response
- */
- sc->idle.keepalive = SMBDIRECT_KEEPALIVE_PENDING;
- mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
- msecs_to_jiffies(sp->keepalive_timeout_msec));
- queue_work(sc->workqueue, &sc->idle.immediate_work);
-}
-
static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
{
struct smb_direct_transport *t;
@@ -292,8 +268,6 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
sc->ib.dev = sc->rdma.cm_id->device;
- INIT_DELAYED_WORK(&sc->idle.timer_work, smb_direct_idle_connection_timer);
-
conn = ksmbd_conn_alloc();
if (!conn)
goto err;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 100/127] smb: server: make use of smbdirect_frwr_is_supported()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (98 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 099/127] smb: server: make use of smbdirect_connection_idle_timer_work() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 101/127] smb: server: make use of smbdirect_connection_{alloc,free}_send_io() Stefan Metzmacher
` (27 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Namjae Jeon, Steve French, Tom Talpey, Steve French
This is an exact copy of rdma_frwr_is_supported().
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>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/smb/server/transport_rdma.c | 15 +++------------
1 file changed, 3 insertions(+), 12 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 886a350819bf..7181d9f62b09 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -2179,15 +2179,6 @@ static int smb_direct_connect(struct smbdirect_socket *sc)
return 0;
}
-static bool rdma_frwr_is_supported(struct ib_device_attr *attrs)
-{
- if (!(attrs->device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS))
- return false;
- if (attrs->max_fast_reg_page_list_len == 0)
- return false;
- return true;
-}
-
static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id,
struct rdma_cm_event *event)
{
@@ -2199,7 +2190,7 @@ static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id,
u8 peer_responder_resources;
int ret;
- if (!rdma_frwr_is_supported(&new_cm_id->device->attrs)) {
+ 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);
@@ -2361,7 +2352,7 @@ static int smb_direct_ib_client_add(struct ib_device *ib_dev)
if (ib_dev->node_type != RDMA_NODE_IB_CA)
smb_direct_port = SMB_DIRECT_PORT_IWARP;
- if (!rdma_frwr_is_supported(&ib_dev->attrs))
+ if (!smbdirect_frwr_is_supported(&ib_dev->attrs))
return 0;
smb_dev = kzalloc(sizeof(*smb_dev), KSMBD_DEFAULT_GFP);
@@ -2485,7 +2476,7 @@ static bool ksmbd_find_rdma_capable_netdev(struct net_device *netdev)
ibdev = ib_device_get_by_netdev(netdev, RDMA_DRIVER_UNKNOWN);
if (ibdev) {
- rdma_capable = rdma_frwr_is_supported(&ibdev->attrs);
+ rdma_capable = smbdirect_frwr_is_supported(&ibdev->attrs);
ib_device_put(ibdev);
}
}
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 101/127] smb: server: make use of smbdirect_connection_{alloc,free}_send_io()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (99 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 100/127] smb: server: make use of smbdirect_frwr_is_supported() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 102/127] smb: server: make use of smbdirect_connection_send_io_done() Stefan Metzmacher
` (26 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Namjae Jeon, Steve French, Tom Talpey, Steve French
These are basically copies of smb_direct_{alloc,free}_sendmsg() just
a bit simpler and with the gfp_mask mask abstracted.
For now we still use KSMBD_DEFAULT_GFP, which includes
__GFP_RETRY_MAYFAIL.
The only difference is that we use ib_dma_unmap_page() for all sges,
this simplifies the logic and doesn't matter as
ib_dma_unmap_single() and ib_dma_unmap_page() both operate
on dma_addr_t and dma_unmap_single_attrs() is just an
alias for dma_unmap_page_attrs().
We already had such an inconsistency in the client
code where we use ib_dma_unmap_single(), while we mapped
using ib_dma_map_page().
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>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/smb/server/transport_rdma.c | 58 +++++++---------------------------
1 file changed, 11 insertions(+), 47 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 7181d9f62b09..50dc87660b25 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -258,6 +258,7 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
smbdirect_socket_set_logging(sc, NULL,
smb_direct_logging_needed,
smb_direct_logging_vaprintf);
+ sc->send_io.mem.gfp_mask = KSMBD_DEFAULT_GFP;
/*
* from here we operate on the copy.
*/
@@ -354,43 +355,6 @@ static void free_transport(struct smb_direct_transport *t)
ksmbd_conn_free(KSMBD_TRANS(t)->conn);
}
-static struct smbdirect_send_io
-*smb_direct_alloc_sendmsg(struct smbdirect_socket *sc)
-{
- struct smbdirect_send_io *msg;
-
- msg = mempool_alloc(sc->send_io.mem.pool, KSMBD_DEFAULT_GFP);
- if (!msg)
- return ERR_PTR(-ENOMEM);
- msg->socket = sc;
- INIT_LIST_HEAD(&msg->sibling_list);
- msg->num_sge = 0;
- return msg;
-}
-
-static void smb_direct_free_sendmsg(struct smbdirect_socket *sc,
- struct smbdirect_send_io *msg)
-{
- int i;
-
- /*
- * The list needs to be empty!
- * The caller should take care of it.
- */
- WARN_ON_ONCE(!list_empty(&msg->sibling_list));
-
- if (msg->num_sge > 0) {
- ib_dma_unmap_single(sc->ib.dev,
- msg->sge[0].addr, msg->sge[0].length,
- DMA_TO_DEVICE);
- for (i = 1; i < msg->num_sge; i++)
- ib_dma_unmap_page(sc->ib.dev,
- msg->sge[i].addr, msg->sge[i].length,
- DMA_TO_DEVICE);
- }
- mempool_free(msg, sc->send_io.mem.pool);
-}
-
static int smb_direct_check_recvmsg(struct smbdirect_recv_io *recvmsg)
{
struct smbdirect_socket *sc = recvmsg->socket;
@@ -780,11 +744,11 @@ static void send_done(struct ib_cq *cq, struct ib_wc *wc)
*/
list_for_each_entry_safe(sibling, next, &sendmsg->sibling_list, sibling_list) {
list_del_init(&sibling->sibling_list);
- smb_direct_free_sendmsg(sc, sibling);
+ smbdirect_connection_free_send_io(sibling);
lcredits += 1;
}
/* Note this frees wc->wr_cqe, but not wc */
- smb_direct_free_sendmsg(sc, sendmsg);
+ smbdirect_connection_free_send_io(sendmsg);
lcredits += 1;
if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_SEND) {
@@ -907,9 +871,9 @@ static int smb_direct_flush_send_list(struct smbdirect_socket *sc,
list_for_each_entry_safe(sibling, next, &last->sibling_list, sibling_list) {
list_del_init(&sibling->sibling_list);
- smb_direct_free_sendmsg(sc, sibling);
+ smbdirect_connection_free_send_io(sibling);
}
- smb_direct_free_sendmsg(sc, last);
+ smbdirect_connection_free_send_io(last);
}
return ret;
@@ -994,7 +958,7 @@ static int smb_direct_create_header(struct smbdirect_socket *sc,
int header_length;
int ret;
- sendmsg = smb_direct_alloc_sendmsg(sc);
+ sendmsg = smbdirect_connection_alloc_send_io(sc);
if (IS_ERR(sendmsg))
return PTR_ERR(sendmsg);
@@ -1037,7 +1001,7 @@ static int smb_direct_create_header(struct smbdirect_socket *sc,
DMA_TO_DEVICE);
ret = ib_dma_mapping_error(sc->ib.dev, sendmsg->sge[0].addr);
if (ret) {
- smb_direct_free_sendmsg(sc, sendmsg);
+ smbdirect_connection_free_send_io(sendmsg);
return ret;
}
@@ -1193,7 +1157,7 @@ static int smb_direct_post_send_data(struct smbdirect_socket *sc,
goto err;
return 0;
err:
- smb_direct_free_sendmsg(sc, msg);
+ smbdirect_connection_free_send_io(msg);
header_failed:
atomic_inc(&sc->send_io.credits.count);
credit_failed:
@@ -1622,7 +1586,7 @@ static int smb_direct_send_negotiate_response(struct smbdirect_socket *sc,
struct smbdirect_negotiate_resp *resp;
int ret;
- sendmsg = smb_direct_alloc_sendmsg(sc);
+ sendmsg = smbdirect_connection_alloc_send_io(sc);
if (IS_ERR(sendmsg))
return -ENOMEM;
@@ -1658,7 +1622,7 @@ static int smb_direct_send_negotiate_response(struct smbdirect_socket *sc,
DMA_TO_DEVICE);
ret = ib_dma_mapping_error(sc->ib.dev, sendmsg->sge[0].addr);
if (ret) {
- smb_direct_free_sendmsg(sc, sendmsg);
+ smbdirect_connection_free_send_io(sendmsg);
return ret;
}
@@ -1668,7 +1632,7 @@ static int smb_direct_send_negotiate_response(struct smbdirect_socket *sc,
ret = post_sendmsg(sc, NULL, sendmsg);
if (ret) {
- smb_direct_free_sendmsg(sc, sendmsg);
+ smbdirect_connection_free_send_io(sendmsg);
return ret;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 102/127] smb: server: make use of smbdirect_connection_send_io_done()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (100 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 101/127] smb: server: make use of smbdirect_connection_{alloc,free}_send_io() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 103/127] smb: server: make use of smbdirect_connection_{create,destroy}_mem_pools() Stefan Metzmacher
` (25 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Namjae Jeon, Steve French, Tom Talpey, Steve French
This also wakes up send_io.pending.dec_wait_queue, which
is currently always empty in the server, but that might
change in future. And we also don't spam the logs on IB_WC_WR_FLUSH_ERR.
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>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/smb/server/transport_rdma.c | 42 +---------------------------------
1 file changed, 1 insertion(+), 41 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 50dc87660b25..aff7ac3054bc 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -726,46 +726,6 @@ static void smb_direct_post_recv_credits(struct work_struct *work)
queue_work(sc->workqueue, &sc->idle.immediate_work);
}
-static void send_done(struct ib_cq *cq, struct ib_wc *wc)
-{
- struct smbdirect_send_io *sendmsg, *sibling, *next;
- struct smbdirect_socket *sc;
- int lcredits = 0;
-
- sendmsg = container_of(wc->wr_cqe, struct smbdirect_send_io, cqe);
- sc = sendmsg->socket;
-
- ksmbd_debug(RDMA, "Send completed. status='%s (%d)', opcode=%d\n",
- ib_wc_status_msg(wc->status), wc->status,
- wc->opcode);
-
- /*
- * Free possible siblings and then the main send_io
- */
- list_for_each_entry_safe(sibling, next, &sendmsg->sibling_list, sibling_list) {
- list_del_init(&sibling->sibling_list);
- smbdirect_connection_free_send_io(sibling);
- lcredits += 1;
- }
- /* Note this frees wc->wr_cqe, but not wc */
- smbdirect_connection_free_send_io(sendmsg);
- lcredits += 1;
-
- if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_SEND) {
- pr_err("Send error. status='%s (%d)', opcode=%d\n",
- ib_wc_status_msg(wc->status), wc->status,
- wc->opcode);
- smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
- return;
- }
-
- atomic_add(lcredits, &sc->send_io.lcredits.count);
- wake_up(&sc->send_io.lcredits.wait_queue);
-
- if (atomic_dec_and_test(&sc->send_io.pending.count))
- wake_up(&sc->send_io.pending.zero_wait_queue);
-}
-
static int manage_credits_prior_sending(struct smbdirect_socket *sc)
{
int new_credits;
@@ -1068,7 +1028,7 @@ static int post_sendmsg(struct smbdirect_socket *sc,
msg->sge[i].addr, msg->sge[i].length,
DMA_TO_DEVICE);
- msg->cqe.done = send_done;
+ msg->cqe.done = smbdirect_connection_send_io_done;
msg->wr.opcode = IB_WR_SEND;
msg->wr.sg_list = &msg->sge[0];
msg->wr.num_sge = msg->num_sge;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 103/127] smb: server: make use of smbdirect_connection_{create,destroy}_mem_pools()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (101 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 102/127] smb: server: make use of smbdirect_connection_send_io_done() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 104/127] smb: server: make use of smbdirect_map_sges_from_iter() Stefan Metzmacher
` (24 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Namjae Jeon, Steve French, Tom Talpey, Steve French
This were based on smb_direct_{create,destroy}_pools() in the server.
The main logical differences are the following:
We now don't use smbdirect_connection_get_recv_io() on cleanup,
instead it uses list_for_each_entry_safe()...
We don't generate warnings if smbdirect_recv_io payload
is copied into userspace buffers. This doesn't happen
in the server anyway.
And it uses list_add_tail() just to let me feel
better when looking at the code...
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>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/smb/server/transport_rdma.c | 76 ++--------------------------------
1 file changed, 3 insertions(+), 73 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index aff7ac3054bc..3c36c4c0580d 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -202,7 +202,6 @@ static inline int get_buf_page_count(void *buf, int size)
(uintptr_t)buf / PAGE_SIZE;
}
-static void smb_direct_destroy_pools(struct smbdirect_socket *sc);
static void smb_direct_post_recv_credits(struct work_struct *work);
static int smb_direct_post_send_data(struct smbdirect_socket *sc,
struct smbdirect_send_batch *send_ctx,
@@ -259,6 +258,7 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
smb_direct_logging_needed,
smb_direct_logging_vaprintf);
sc->send_io.mem.gfp_mask = KSMBD_DEFAULT_GFP;
+ sc->recv_io.mem.gfp_mask = KSMBD_DEFAULT_GFP;
/*
* from here we operate on the copy.
*/
@@ -351,7 +351,7 @@ static void free_transport(struct smb_direct_transport *t)
rdma_destroy_id(sc->rdma.cm_id);
}
- smb_direct_destroy_pools(sc);
+ smbdirect_connection_destroy_mem_pools(sc);
ksmbd_conn_free(KSMBD_TRANS(t)->conn);
}
@@ -1716,76 +1716,6 @@ static int smb_direct_init_params(struct smbdirect_socket *sc)
return 0;
}
-static void smb_direct_destroy_pools(struct smbdirect_socket *sc)
-{
- struct smbdirect_recv_io *recvmsg;
-
- while ((recvmsg = smbdirect_connection_get_recv_io(sc)))
- mempool_free(recvmsg, sc->recv_io.mem.pool);
-
- mempool_destroy(sc->recv_io.mem.pool);
- sc->recv_io.mem.pool = NULL;
-
- kmem_cache_destroy(sc->recv_io.mem.cache);
- sc->recv_io.mem.cache = NULL;
-
- mempool_destroy(sc->send_io.mem.pool);
- sc->send_io.mem.pool = NULL;
-
- kmem_cache_destroy(sc->send_io.mem.cache);
- sc->send_io.mem.cache = NULL;
-}
-
-static int smb_direct_create_pools(struct smbdirect_socket *sc)
-{
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- char name[80];
- int i;
- struct smbdirect_recv_io *recvmsg;
-
- snprintf(name, sizeof(name), "smbdirect_send_io_pool_%p", sc);
- sc->send_io.mem.cache = kmem_cache_create(name,
- sizeof(struct smbdirect_send_io) +
- sizeof(struct smbdirect_negotiate_resp),
- 0, SLAB_HWCACHE_ALIGN, NULL);
- if (!sc->send_io.mem.cache)
- return -ENOMEM;
-
- sc->send_io.mem.pool = mempool_create(sp->send_credit_target,
- mempool_alloc_slab, mempool_free_slab,
- sc->send_io.mem.cache);
- if (!sc->send_io.mem.pool)
- goto err;
-
- snprintf(name, sizeof(name), "smbdirect_recv_io_pool_%p", sc);
- sc->recv_io.mem.cache = kmem_cache_create(name,
- sizeof(struct smbdirect_recv_io) +
- sp->max_recv_size,
- 0, SLAB_HWCACHE_ALIGN, NULL);
- if (!sc->recv_io.mem.cache)
- goto err;
-
- sc->recv_io.mem.pool =
- mempool_create(sp->recv_credit_max, mempool_alloc_slab,
- mempool_free_slab, sc->recv_io.mem.cache);
- if (!sc->recv_io.mem.pool)
- goto err;
-
- for (i = 0; i < sp->recv_credit_max; i++) {
- recvmsg = mempool_alloc(sc->recv_io.mem.pool, KSMBD_DEFAULT_GFP);
- if (!recvmsg)
- goto err;
- recvmsg->socket = sc;
- recvmsg->sge.length = 0;
- list_add(&recvmsg->list, &sc->recv_io.free.list);
- }
-
- return 0;
-err:
- smb_direct_destroy_pools(sc);
- return -ENOMEM;
-}
-
static u32 smb_direct_rdma_rw_send_wrs(struct ib_device *dev, const struct ib_qp_init_attr *attr)
{
/*
@@ -2083,7 +2013,7 @@ static int smb_direct_connect(struct smbdirect_socket *sc)
return ret;
}
- ret = smb_direct_create_pools(sc);
+ ret = smbdirect_connection_create_mem_pools(sc);
if (ret) {
pr_err("Can't init RDMA pool: %d\n", ret);
return ret;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 104/127] smb: server: make use of smbdirect_map_sges_from_iter()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (102 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 103/127] smb: server: make use of smbdirect_connection_{create,destroy}_mem_pools() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 105/127] smb: server: make use of smbdirect_connection_qp_event_handler() Stefan Metzmacher
` (23 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Namjae Jeon, Steve French, Tom Talpey, Steve French
It will make it easier to move stuff into common code when
both client and server use smbdirect_map_sges_from_iter().
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>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/smb/server/transport_rdma.c | 58 +++++++++++-----------------------
1 file changed, 19 insertions(+), 39 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 3c36c4c0580d..4e2de2664e31 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -1005,18 +1005,6 @@ static int get_sg_list(void *buf, int size, struct scatterlist *sg_list, int nen
return i;
}
-static int get_mapped_sg_list(struct ib_device *device, void *buf, int size,
- struct scatterlist *sg_list, int nentries,
- enum dma_data_direction dir)
-{
- int npages;
-
- npages = get_sg_list(buf, size, sg_list, nentries);
- if (npages < 0)
- return -EINVAL;
- return ib_dma_map_sg(device, sg_list, npages, dir);
-}
-
static int post_sendmsg(struct smbdirect_socket *sc,
struct smbdirect_send_batch *send_ctx,
struct smbdirect_send_io *msg)
@@ -1060,10 +1048,9 @@ static int smb_direct_post_send_data(struct smbdirect_socket *sc,
struct kvec *iov, int niov,
int remaining_data_length)
{
- int i, j, ret;
+ int i, ret;
struct smbdirect_send_io *msg;
int data_length;
- struct scatterlist sg[SMBDIRECT_SEND_IO_MAX_SGE - 1];
ret = wait_for_send_lcredit(sc, send_ctx);
if (ret)
@@ -1082,34 +1069,27 @@ static int smb_direct_post_send_data(struct smbdirect_socket *sc,
if (ret)
goto header_failed;
- for (i = 0; i < niov; i++) {
- struct ib_sge *sge;
- int sg_cnt;
-
- sg_init_table(sg, SMBDIRECT_SEND_IO_MAX_SGE - 1);
- sg_cnt = get_mapped_sg_list(sc->ib.dev,
- iov[i].iov_base, iov[i].iov_len,
- sg, SMBDIRECT_SEND_IO_MAX_SGE - 1,
- DMA_TO_DEVICE);
- if (sg_cnt <= 0) {
- pr_err("failed to map buffer\n");
- ret = -ENOMEM;
+ if (data_length) {
+ struct smbdirect_map_sges extract = {
+ .num_sge = msg->num_sge,
+ .max_sge = ARRAY_SIZE(msg->sge),
+ .sge = msg->sge,
+ .device = sc->ib.dev,
+ .local_dma_lkey = sc->ib.pd->local_dma_lkey,
+ .direction = DMA_TO_DEVICE,
+ };
+ struct iov_iter iter;
+
+ iov_iter_kvec(&iter, ITER_SOURCE, iov, niov, data_length);
+
+ ret = smbdirect_map_sges_from_iter(&iter, data_length, &extract);
+ if (ret < 0)
goto err;
- } else if (sg_cnt + msg->num_sge > SMBDIRECT_SEND_IO_MAX_SGE) {
- pr_err("buffer not fitted into sges\n");
- ret = -E2BIG;
- ib_dma_unmap_sg(sc->ib.dev, sg, sg_cnt,
- DMA_TO_DEVICE);
+ if (WARN_ON_ONCE(ret != data_length)) {
+ ret = -EIO;
goto err;
}
-
- for (j = 0; j < sg_cnt; j++) {
- sge = &msg->sge[msg->num_sge];
- sge->addr = sg_dma_address(&sg[j]);
- sge->length = sg_dma_len(&sg[j]);
- sge->lkey = sc->ib.pd->local_dma_lkey;
- msg->num_sge++;
- }
+ msg->num_sge = extract.num_sge;
}
ret = post_sendmsg(sc, send_ctx, msg);
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 105/127] smb: server: make use of smbdirect_connection_qp_event_handler()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (103 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 104/127] smb: server: make use of smbdirect_map_sges_from_iter() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 106/127] smb: server: make use of smbdirect_connection_negotiate_rdma_resources() Stefan Metzmacher
` (22 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Namjae Jeon, Steve French, Tom Talpey, Steve French
This is a copy of smb_direct_qpair_handler()...
It will allow more code to be moved to common functions
soon.
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>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/smb/server/transport_rdma.c | 19 +------------------
1 file changed, 1 insertion(+), 18 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 4e2de2664e31..ef2de6302768 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -1501,23 +1501,6 @@ static int smb_direct_cm_handler(struct rdma_cm_id *cm_id,
return 0;
}
-static void smb_direct_qpair_handler(struct ib_event *event, void *context)
-{
- struct smbdirect_socket *sc = context;
-
- ksmbd_debug(RDMA, "Received QP event. cm_id=%p, event=%s (%d)\n",
- sc->rdma.cm_id, ib_event_msg(event->event), event->event);
-
- switch (event->event) {
- case IB_EVENT_CQ_ERR:
- case IB_EVENT_QP_FATAL:
- smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
- break;
- default:
- break;
- }
-}
-
static int smb_direct_send_negotiate_response(struct smbdirect_socket *sc,
int failed)
{
@@ -1857,7 +1840,7 @@ static int smb_direct_create_qpair(struct smbdirect_socket *sc)
* again if max_rdma_ctxs is not 0.
*/
memset(&qp_attr, 0, sizeof(qp_attr));
- qp_attr.event_handler = smb_direct_qpair_handler;
+ qp_attr.event_handler = smbdirect_connection_qp_event_handler;
qp_attr.qp_context = sc;
qp_attr.cap = qp_cap;
qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 106/127] smb: server: make use of smbdirect_connection_negotiate_rdma_resources()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (104 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 105/127] smb: server: make use of smbdirect_connection_qp_event_handler() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 107/127] smb: server: make use of smbdirect_connection_{create,destroy}_qp() Stefan Metzmacher
` (21 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Namjae Jeon, Steve French, Tom Talpey, Steve French
It's good to have this logic in a central place, it will allow us
share more code soon.
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>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/smb/server/transport_rdma.c | 62 ++++------------------------------
1 file changed, 7 insertions(+), 55 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index ef2de6302768..526ad5c19b6e 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -2020,66 +2020,18 @@ static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id,
sc = &t->socket;
sp = &sc->parameters;
- peer_initiator_depth = event->param.conn.initiator_depth;
- peer_responder_resources = event->param.conn.responder_resources;
- if (rdma_protocol_iwarp(new_cm_id->device, new_cm_id->port_num) &&
- event->param.conn.private_data_len == 8) {
- /*
- * Legacy clients with only iWarp MPA v1 support
- * need a private blob in order to negotiate
- * the IRD/ORD values.
- */
- const __be32 *ird_ord_hdr = event->param.conn.private_data;
- u32 ird32 = be32_to_cpu(ird_ord_hdr[0]);
- u32 ord32 = be32_to_cpu(ird_ord_hdr[1]);
-
- /*
- * cifs.ko sends the legacy IRD/ORD negotiation
- * event if iWarp MPA v2 was used.
- *
- * Here we check that the values match and only
- * mark the client as legacy if they don't match.
- */
- if ((u32)event->param.conn.initiator_depth != ird32 ||
- (u32)event->param.conn.responder_resources != ord32) {
- /*
- * There are broken clients (old cifs.ko)
- * using little endian and also
- * struct rdma_conn_param only uses u8
- * for initiator_depth and responder_resources,
- * so we truncate the value to U8_MAX.
- *
- * smb_direct_accept_client() will then
- * do the real negotiation in order to
- * select the minimum between client and
- * server.
- */
- ird32 = min_t(u32, ird32, U8_MAX);
- ord32 = min_t(u32, ord32, U8_MAX);
-
- sc->rdma.legacy_iwarp = true;
- peer_initiator_depth = (u8)ird32;
- peer_responder_resources = (u8)ord32;
- }
- }
-
/*
* First set what the we as server are able to support
*/
sp->initiator_depth = min_t(u8, sp->initiator_depth,
- new_cm_id->device->attrs.max_qp_rd_atom);
+ sc->ib.dev->attrs.max_qp_rd_atom);
- /*
- * negotiate the value by using the minimum
- * between client and server if the client provided
- * non 0 values.
- */
- if (peer_initiator_depth != 0)
- sp->initiator_depth = min_t(u8, sp->initiator_depth,
- peer_initiator_depth);
- if (peer_responder_resources != 0)
- sp->responder_resources = min_t(u8, sp->responder_resources,
- peer_responder_resources);
+ peer_initiator_depth = event->param.conn.initiator_depth;
+ peer_responder_resources = event->param.conn.responder_resources;
+ smbdirect_connection_negotiate_rdma_resources(sc,
+ peer_initiator_depth,
+ peer_responder_resources,
+ &event->param.conn);
ret = smb_direct_connect(sc);
if (ret)
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 107/127] smb: server: make use of smbdirect_connection_{create,destroy}_qp()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (105 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 106/127] smb: server: make use of smbdirect_connection_negotiate_rdma_resources() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 108/127] smb: server: initialize recv_io->cqe.done = recv_done just once Stefan Metzmacher
` (20 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Namjae Jeon, Steve French, Tom Talpey, Steve French
It's good a use common code for this and it will allow us
to share more code in the next steps.
Calling ib_drain_qp() twice is ok.
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>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/smb/server/transport_rdma.c | 217 +--------------------------------
1 file changed, 6 insertions(+), 211 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 526ad5c19b6e..2f55764a5f2e 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -257,6 +257,7 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
smbdirect_socket_set_logging(sc, NULL,
smb_direct_logging_needed,
smb_direct_logging_vaprintf);
+ sc->ib.poll_ctx = IB_POLL_WORKQUEUE;
sc->send_io.mem.gfp_mask = KSMBD_DEFAULT_GFP;
sc->recv_io.mem.gfp_mask = KSMBD_DEFAULT_GFP;
/*
@@ -318,11 +319,8 @@ static void free_transport(struct smb_direct_transport *t)
if (sc->rdma.cm_id)
rdma_lock_handler(sc->rdma.cm_id);
- if (sc->ib.qp) {
+ if (sc->ib.qp)
ib_drain_qp(sc->ib.qp);
- sc->ib.qp = NULL;
- rdma_destroy_qp(sc->rdma.cm_id);
- }
ksmbd_debug(RDMA, "drain the reassembly queue\n");
do {
@@ -340,12 +338,7 @@ static void free_transport(struct smb_direct_transport *t)
} while (recvmsg);
sc->recv_io.reassembly.data_length = 0;
- if (sc->ib.send_cq)
- ib_free_cq(sc->ib.send_cq);
- if (sc->ib.recv_cq)
- ib_free_cq(sc->ib.recv_cq);
- if (sc->ib.pd)
- ib_dealloc_pd(sc->ib.pd);
+ smbdirect_connection_destroy_qp(sc);
if (sc->rdma.cm_id) {
rdma_unlock_handler(sc->rdma.cm_id);
rdma_destroy_id(sc->rdma.cm_id);
@@ -1679,206 +1672,6 @@ static int smb_direct_init_params(struct smbdirect_socket *sc)
return 0;
}
-static u32 smb_direct_rdma_rw_send_wrs(struct ib_device *dev, const struct ib_qp_init_attr *attr)
-{
- /*
- * This could be split out of rdma_rw_init_qp()
- * and be a helper function next to rdma_rw_mr_factor()
- *
- * We can't check unlikely(rdma_rw_force_mr) here,
- * but that is most likely 0 anyway.
- */
- u32 factor;
-
- WARN_ON_ONCE(attr->port_num == 0);
-
- /*
- * Each context needs at least one RDMA READ or WRITE WR.
- *
- * For some hardware we might need more, eventually we should ask the
- * HCA driver for a multiplier here.
- */
- factor = 1;
-
- /*
- * If the device needs MRs to perform RDMA READ or WRITE operations,
- * we'll need two additional MRs for the registrations and the
- * invalidation.
- */
- if (rdma_protocol_iwarp(dev, attr->port_num) || dev->attrs.max_sgl_rd)
- factor += 2; /* inv + reg */
-
- return factor * attr->cap.max_rdma_ctxs;
-}
-
-static int smb_direct_create_qpair(struct smbdirect_socket *sc)
-{
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- int ret;
- struct ib_qp_cap qp_cap;
- struct ib_qp_init_attr qp_attr;
- u32 max_send_wr;
- u32 rdma_send_wr;
-
- /*
- * Note that {rdma,ib}_create_qp() will call
- * rdma_rw_init_qp() if cap->max_rdma_ctxs is not 0.
- * It will adjust cap->max_send_wr to the required
- * number of additional WRs for the RDMA RW operations.
- * It will cap cap->max_send_wr to the device limit.
- *
- * +1 for ib_drain_qp
- */
- qp_cap.max_send_wr = sp->send_credit_target + 1;
- qp_cap.max_recv_wr = sp->recv_credit_max + 1;
- qp_cap.max_send_sge = SMBDIRECT_SEND_IO_MAX_SGE;
- qp_cap.max_recv_sge = SMBDIRECT_RECV_IO_MAX_SGE;
- qp_cap.max_inline_data = 0;
- qp_cap.max_rdma_ctxs = sc->rw_io.credits.max;
-
- /*
- * Find out the number of max_send_wr
- * after rdma_rw_init_qp() adjusted it.
- *
- * We only do it on a temporary variable,
- * as rdma_create_qp() will trigger
- * rdma_rw_init_qp() again.
- */
- memset(&qp_attr, 0, sizeof(qp_attr));
- qp_attr.cap = qp_cap;
- qp_attr.port_num = sc->rdma.cm_id->port_num;
- rdma_send_wr = smb_direct_rdma_rw_send_wrs(sc->ib.dev, &qp_attr);
- max_send_wr = qp_cap.max_send_wr + rdma_send_wr;
-
- if (qp_cap.max_send_wr > sc->ib.dev->attrs.max_cqe ||
- qp_cap.max_send_wr > sc->ib.dev->attrs.max_qp_wr) {
- pr_err("Possible CQE overrun: max_send_wr %d\n",
- qp_cap.max_send_wr);
- pr_err("device %.*s reporting max_cqe %d max_qp_wr %d\n",
- IB_DEVICE_NAME_MAX,
- sc->ib.dev->name,
- sc->ib.dev->attrs.max_cqe,
- sc->ib.dev->attrs.max_qp_wr);
- pr_err("consider lowering send_credit_target = %d\n",
- sp->send_credit_target);
- return -EINVAL;
- }
-
- if (qp_cap.max_rdma_ctxs &&
- (max_send_wr >= sc->ib.dev->attrs.max_cqe ||
- max_send_wr >= sc->ib.dev->attrs.max_qp_wr)) {
- pr_err("Possible CQE overrun: rdma_send_wr %d + max_send_wr %d = %d\n",
- rdma_send_wr, qp_cap.max_send_wr, max_send_wr);
- pr_err("device %.*s reporting max_cqe %d max_qp_wr %d\n",
- IB_DEVICE_NAME_MAX,
- sc->ib.dev->name,
- sc->ib.dev->attrs.max_cqe,
- sc->ib.dev->attrs.max_qp_wr);
- pr_err("consider lowering send_credit_target = %d, max_rdma_ctxs = %d\n",
- sp->send_credit_target, qp_cap.max_rdma_ctxs);
- return -EINVAL;
- }
-
- if (qp_cap.max_recv_wr > sc->ib.dev->attrs.max_cqe ||
- qp_cap.max_recv_wr > sc->ib.dev->attrs.max_qp_wr) {
- pr_err("Possible CQE overrun: max_recv_wr %d\n",
- qp_cap.max_recv_wr);
- pr_err("device %.*s reporting max_cqe %d max_qp_wr %d\n",
- IB_DEVICE_NAME_MAX,
- sc->ib.dev->name,
- sc->ib.dev->attrs.max_cqe,
- sc->ib.dev->attrs.max_qp_wr);
- pr_err("consider lowering receive_credit_max = %d\n",
- sp->recv_credit_max);
- return -EINVAL;
- }
-
- if (qp_cap.max_send_sge > sc->ib.dev->attrs.max_send_sge ||
- qp_cap.max_recv_sge > sc->ib.dev->attrs.max_recv_sge) {
- pr_err("device %.*s max_send_sge/max_recv_sge = %d/%d too small\n",
- IB_DEVICE_NAME_MAX,
- sc->ib.dev->name,
- sc->ib.dev->attrs.max_send_sge,
- sc->ib.dev->attrs.max_recv_sge);
- return -EINVAL;
- }
-
- sc->ib.pd = ib_alloc_pd(sc->ib.dev, 0);
- if (IS_ERR(sc->ib.pd)) {
- pr_err("Can't create RDMA PD\n");
- ret = PTR_ERR(sc->ib.pd);
- sc->ib.pd = NULL;
- return ret;
- }
-
- sc->ib.send_cq = ib_alloc_cq_any(sc->ib.dev, sc,
- max_send_wr,
- IB_POLL_WORKQUEUE);
- if (IS_ERR(sc->ib.send_cq)) {
- pr_err("Can't create RDMA send CQ\n");
- ret = PTR_ERR(sc->ib.send_cq);
- sc->ib.send_cq = NULL;
- goto err;
- }
-
- sc->ib.recv_cq = ib_alloc_cq_any(sc->ib.dev, sc,
- qp_cap.max_recv_wr,
- IB_POLL_WORKQUEUE);
- if (IS_ERR(sc->ib.recv_cq)) {
- pr_err("Can't create RDMA recv CQ\n");
- ret = PTR_ERR(sc->ib.recv_cq);
- sc->ib.recv_cq = NULL;
- goto err;
- }
-
- /*
- * We reset completely here!
- * As the above use was just temporary
- * to calc max_send_wr and rdma_send_wr.
- *
- * rdma_create_qp() will trigger rdma_rw_init_qp()
- * again if max_rdma_ctxs is not 0.
- */
- memset(&qp_attr, 0, sizeof(qp_attr));
- qp_attr.event_handler = smbdirect_connection_qp_event_handler;
- qp_attr.qp_context = sc;
- qp_attr.cap = qp_cap;
- qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR;
- qp_attr.qp_type = IB_QPT_RC;
- qp_attr.send_cq = sc->ib.send_cq;
- qp_attr.recv_cq = sc->ib.recv_cq;
- qp_attr.port_num = ~0;
-
- ret = rdma_create_qp(sc->rdma.cm_id, sc->ib.pd, &qp_attr);
- if (ret) {
- pr_err("Can't create RDMA QP: %d\n", ret);
- goto err;
- }
-
- sc->ib.qp = sc->rdma.cm_id->qp;
- sc->rdma.cm_id->event_handler = smb_direct_cm_handler;
-
- return 0;
-err:
- if (sc->ib.qp) {
- sc->ib.qp = NULL;
- rdma_destroy_qp(sc->rdma.cm_id);
- }
- if (sc->ib.recv_cq) {
- ib_destroy_cq(sc->ib.recv_cq);
- sc->ib.recv_cq = NULL;
- }
- if (sc->ib.send_cq) {
- ib_destroy_cq(sc->ib.send_cq);
- sc->ib.send_cq = NULL;
- }
- if (sc->ib.pd) {
- ib_dealloc_pd(sc->ib.pd);
- sc->ib.pd = NULL;
- }
- return ret;
-}
-
static int smb_direct_prepare(struct ksmbd_transport *t)
{
struct smb_direct_transport *st = SMBD_TRANS(t);
@@ -1970,6 +1763,8 @@ static int smb_direct_connect(struct smbdirect_socket *sc)
{
int ret;
+ sc->rdma.cm_id->event_handler = smb_direct_cm_handler;
+
ret = smb_direct_init_params(sc);
if (ret) {
pr_err("Can't configure RDMA parameters\n");
@@ -1982,7 +1777,7 @@ static int smb_direct_connect(struct smbdirect_socket *sc)
return ret;
}
- ret = smb_direct_create_qpair(sc);
+ ret = smbdirect_connection_create_qp(sc);
if (ret) {
pr_err("Can't accept RDMA client: %d\n", ret);
return ret;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 108/127] smb: server: initialize recv_io->cqe.done = recv_done just once
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (106 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 107/127] smb: server: make use of smbdirect_connection_{create,destroy}_qp() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 109/127] smb: server: make use of smbdirect_connection_post_recv_io() Stefan Metzmacher
` (19 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Namjae Jeon, Steve French, Tom Talpey, Steve French
smbdirect_recv_io structures are pre-allocated so we can set the
callback function just once.
This will make it easy to move smb_direct_post_recv to common code
soon.
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>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/smb/server/transport_rdma.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 2f55764a5f2e..0919ef007602 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -547,7 +547,6 @@ static int smb_direct_post_recv(struct smbdirect_socket *sc,
return ret;
recvmsg->sge.length = sp->max_recv_size;
recvmsg->sge.lkey = sc->ib.pd->local_dma_lkey;
- recvmsg->cqe.done = recv_done;
wr.wr_cqe = &recvmsg->cqe;
wr.next = NULL;
@@ -1761,6 +1760,7 @@ static int smb_direct_prepare(struct ksmbd_transport *t)
static int smb_direct_connect(struct smbdirect_socket *sc)
{
+ struct smbdirect_recv_io *recv_io;
int ret;
sc->rdma.cm_id->event_handler = smb_direct_cm_handler;
@@ -1777,6 +1777,9 @@ static int smb_direct_connect(struct smbdirect_socket *sc)
return ret;
}
+ list_for_each_entry(recv_io, &sc->recv_io.free.list, list)
+ recv_io->cqe.done = recv_done;
+
ret = smbdirect_connection_create_qp(sc);
if (ret) {
pr_err("Can't accept RDMA client: %d\n", ret);
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 109/127] smb: server: make use of smbdirect_connection_post_recv_io()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (107 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 108/127] smb: server: initialize recv_io->cqe.done = recv_done just once Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 110/127] smb: server: make use of smbdirect_connection_recv_io_refill[_work]() Stefan Metzmacher
` (18 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: metze, Namjae Jeon, Steve French, Tom Talpey, Steve French
The only difference is that smbdirect_connection_post_recv_io()
returns early if the connection is already broken.
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>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/smb/server/transport_rdma.c | 39 ++--------------------------------
1 file changed, 2 insertions(+), 37 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 0919ef007602..4acae8e43b76 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -531,41 +531,6 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
}
-static int smb_direct_post_recv(struct smbdirect_socket *sc,
- struct smbdirect_recv_io *recvmsg)
-{
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- struct ib_recv_wr wr;
- int ret;
-
- recvmsg->sge.addr = ib_dma_map_single(sc->ib.dev,
- recvmsg->packet,
- sp->max_recv_size,
- DMA_FROM_DEVICE);
- ret = ib_dma_mapping_error(sc->ib.dev, recvmsg->sge.addr);
- if (ret)
- return ret;
- recvmsg->sge.length = sp->max_recv_size;
- recvmsg->sge.lkey = sc->ib.pd->local_dma_lkey;
-
- wr.wr_cqe = &recvmsg->cqe;
- wr.next = NULL;
- wr.sg_list = &recvmsg->sge;
- wr.num_sge = 1;
-
- ret = ib_post_recv(sc->ib.qp, &wr, NULL);
- if (ret) {
- pr_err("Can't post recv: %d\n", ret);
- ib_dma_unmap_single(sc->ib.dev,
- recvmsg->sge.addr, recvmsg->sge.length,
- DMA_FROM_DEVICE);
- recvmsg->sge.length = 0;
- smbdirect_connection_schedule_disconnect(sc, ret);
- return ret;
- }
- return ret;
-}
-
static int smb_direct_read(struct ksmbd_transport *t, char *buf,
unsigned int size, int unused)
{
@@ -702,7 +667,7 @@ static void smb_direct_post_recv_credits(struct work_struct *work)
recvmsg->first_segment = false;
- ret = smb_direct_post_recv(sc, recvmsg);
+ ret = smbdirect_connection_post_recv_io(recvmsg);
if (ret) {
pr_err("Can't post recv: %d\n", ret);
smbdirect_connection_put_recv_io(recvmsg);
@@ -1621,7 +1586,7 @@ static int smb_direct_prepare_negotiation(struct smbdirect_socket *sc)
if (!recvmsg)
return -ENOMEM;
- ret = smb_direct_post_recv(sc, recvmsg);
+ ret = smbdirect_connection_post_recv_io(recvmsg);
if (ret) {
pr_err("Can't post recv: %d\n", ret);
goto out_err;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 110/127] smb: server: make use of smbdirect_connection_recv_io_refill[_work]()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (108 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 109/127] smb: server: make use of smbdirect_connection_post_recv_io() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 111/127] smb: server: make use of smbdirect_get_buf_page_count() Stefan Metzmacher
` (17 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical; +Cc: metze, Namjae Jeon, Steve French, Tom Talpey
This is basically a copy of smb_direct_post_recv_credits(), but
there are several improvements compared to the existing function:
1. We calculate the number of missing posted buffers by getting the
difference between recv_io.credits.target and recv_io.posted.count.
Instead of the difference between recv_io.credits.target
and recv_io.credits.count, because recv_io.credits.count is
only updated once a message is send to the peer.
It was not really a problem before, because we have
a fixed number smbdirect_recv_io buffers, so the
loop terminated when smbdirect_connection_get_recv_io()
returns NULL.
But using recv_io.posted.count makes it easier to
understand.
2. In order to tell the peer about the newly posted buffer
and grant the credits, we only trigger the send immediate
when we're not granting only the last possible credit.
This is mostly a difference relative to the servers
smb_direct_post_recv_credits() implementation,
which should avoid useless ping pong messages.
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>
---
fs/smb/server/transport_rdma.c | 53 +++++++---------------------------
1 file changed, 10 insertions(+), 43 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 4acae8e43b76..9cc8cffcc6e9 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -202,7 +202,6 @@ static inline int get_buf_page_count(void *buf, int size)
(uintptr_t)buf / PAGE_SIZE;
}
-static void smb_direct_post_recv_credits(struct work_struct *work);
static int smb_direct_post_send_data(struct smbdirect_socket *sc,
struct smbdirect_send_batch *send_ctx,
struct kvec *iov, int niov,
@@ -651,38 +650,6 @@ static int smb_direct_read(struct ksmbd_transport *t, char *buf,
goto again;
}
-static void smb_direct_post_recv_credits(struct work_struct *work)
-{
- struct smbdirect_socket *sc =
- container_of(work, struct smbdirect_socket, recv_io.posted.refill_work);
- struct smbdirect_recv_io *recvmsg;
- int credits = 0;
- int ret;
-
- if (atomic_read(&sc->recv_io.credits.count) < sc->recv_io.credits.target) {
- while (true) {
- recvmsg = smbdirect_connection_get_recv_io(sc);
- if (!recvmsg)
- break;
-
- recvmsg->first_segment = false;
-
- ret = smbdirect_connection_post_recv_io(recvmsg);
- if (ret) {
- pr_err("Can't post recv: %d\n", ret);
- smbdirect_connection_put_recv_io(recvmsg);
- break;
- }
- credits++;
-
- atomic_inc(&sc->recv_io.posted.count);
- }
- }
-
- if (credits)
- queue_work(sc->workqueue, &sc->idle.immediate_work);
-}
-
static int manage_credits_prior_sending(struct smbdirect_socket *sc)
{
int new_credits;
@@ -1703,24 +1670,24 @@ static int smb_direct_prepare(struct ksmbd_transport *t)
/*
* We negotiated with success, so we need to refill the recv queue.
- * We do that with sc->idle.immediate_work still being disabled
- * via smbdirect_socket_init(), so that queue_work(sc->workqueue,
- * &sc->idle.immediate_work) in smb_direct_post_recv_credits()
- * is a no-op.
*
* The message that grants the credits to the client is
* the negotiate response.
*/
- INIT_WORK(&sc->recv_io.posted.refill_work, smb_direct_post_recv_credits);
- smb_direct_post_recv_credits(&sc->recv_io.posted.refill_work);
- if (unlikely(sc->first_error))
- return sc->first_error;
- INIT_WORK(&sc->idle.immediate_work, smb_direct_send_immediate_work);
+ ret = smbdirect_connection_recv_io_refill(sc);
+ if (ret < 0)
+ return ret;
+ ret = 0;
respond:
ret = smb_direct_send_negotiate_response(sc, ret);
+ if (ret)
+ return ret;
- return ret;
+ INIT_WORK(&sc->recv_io.posted.refill_work, smbdirect_connection_recv_io_refill_work);
+ INIT_WORK(&sc->idle.immediate_work, smb_direct_send_immediate_work);
+
+ return 0;
}
static int smb_direct_connect(struct smbdirect_socket *sc)
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 111/127] smb: server: make use of smbdirect_get_buf_page_count()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (109 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 110/127] smb: server: make use of smbdirect_connection_recv_io_refill[_work]() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 112/127] smb: server: make use of smbdirect_connection_wait_for_credits() Stefan Metzmacher
` (16 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical; +Cc: metze, Namjae Jeon, Steve French, Tom Talpey
This will allow us to move code into common code
between client and server soon.
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>
---
fs/smb/server/transport_rdma.c | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 9cc8cffcc6e9..d8829cb57270 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -196,12 +196,6 @@ unsigned int get_smbd_max_read_write_size(struct ksmbd_transport *kt)
return sp->max_read_write_size;
}
-static inline int get_buf_page_count(void *buf, int size)
-{
- return DIV_ROUND_UP((uintptr_t)buf + size, PAGE_SIZE) -
- (uintptr_t)buf / PAGE_SIZE;
-}
-
static int smb_direct_post_send_data(struct smbdirect_socket *sc,
struct smbdirect_send_batch *send_ctx,
struct kvec *iov, int niov,
@@ -828,7 +822,7 @@ static int wait_for_rw_credits(struct smbdirect_socket *sc, int credits)
static int calc_rw_credits(struct smbdirect_socket *sc,
char *buf, unsigned int len)
{
- return DIV_ROUND_UP(get_buf_page_count(buf, len),
+ return DIV_ROUND_UP(smbdirect_get_buf_page_count(buf, len),
sc->rw_io.credits.num_pages);
}
@@ -904,7 +898,7 @@ static int get_sg_list(void *buf, int size, struct scatterlist *sg_list, int nen
int offset, len;
int i = 0;
- if (size <= 0 || nentries < get_buf_page_count(buf, size))
+ if (size <= 0 || nentries < smbdirect_get_buf_page_count(buf, size))
return -EINVAL;
offset = offset_in_page(buf);
@@ -1095,7 +1089,7 @@ static int smb_direct_writev(struct ksmbd_transport *t,
v->iov_len = min_t(size_t,
iov[iov_idx].iov_len - iov_ofs,
possible_bytes);
- page_count = get_buf_page_count(v->iov_base, v->iov_len);
+ page_count = smbdirect_get_buf_page_count(v->iov_base, v->iov_len);
if (page_count > possible_vecs) {
/*
* If the number of pages in the buffer
@@ -1124,7 +1118,7 @@ static int smb_direct_writev(struct ksmbd_transport *t,
size_t elen = min_t(size_t, v->iov_len - fplen, epages*PAGE_SIZE);
v->iov_len = fplen + elen;
- page_count = get_buf_page_count(v->iov_base, v->iov_len);
+ page_count = smbdirect_get_buf_page_count(v->iov_base, v->iov_len);
if (WARN_ON_ONCE(page_count > possible_vecs)) {
/*
* Something went wrong in the above
@@ -1289,7 +1283,7 @@ static int smb_direct_rdma_xmit(struct smb_direct_transport *t,
msg->sgt.sgl = &msg->sg_list[0];
ret = sg_alloc_table_chained(&msg->sgt,
- get_buf_page_count(desc_buf, desc_buf_len),
+ smbdirect_get_buf_page_count(desc_buf, desc_buf_len),
msg->sg_list, SG_CHUNK_SIZE);
if (ret) {
ret = -ENOMEM;
@@ -1303,7 +1297,7 @@ static int smb_direct_rdma_xmit(struct smb_direct_transport *t,
ret = rdma_rw_ctx_init(&msg->rdma_ctx, sc->ib.qp, sc->ib.qp->port,
msg->sgt.sgl,
- get_buf_page_count(desc_buf, desc_buf_len),
+ smbdirect_get_buf_page_count(desc_buf, desc_buf_len),
0,
le64_to_cpu(desc[i].offset),
le32_to_cpu(desc[i].token),
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 112/127] smb: server: make use of smbdirect_connection_wait_for_credits()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (110 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 111/127] smb: server: make use of smbdirect_get_buf_page_count() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 113/127] smb: server: make use of functions from smbdirect_rw.c Stefan Metzmacher
` (15 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical; +Cc: metze, Namjae Jeon, Steve French, Tom Talpey
This will allow us to share more common code between client and
server soon.
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>
---
fs/smb/server/transport_rdma.c | 42 ++++++++++------------------------
1 file changed, 12 insertions(+), 30 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index d8829cb57270..3902ba403c0f 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -757,27 +757,6 @@ static int smb_direct_flush_send_list(struct smbdirect_socket *sc,
return ret;
}
-static int wait_for_credits(struct smbdirect_socket *sc,
- wait_queue_head_t *waitq, atomic_t *total_credits,
- int needed)
-{
- int ret;
-
- do {
- if (atomic_sub_return(needed, total_credits) >= 0)
- return 0;
-
- atomic_add(needed, total_credits);
- ret = wait_event_interruptible(*waitq,
- atomic_read(total_credits) >= needed ||
- sc->status != SMBDIRECT_SOCKET_CONNECTED);
-
- if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
- return -ENOTCONN;
- else if (ret < 0)
- return ret;
- } while (true);
-}
static int wait_for_send_lcredit(struct smbdirect_socket *sc,
struct smbdirect_send_batch *send_ctx)
@@ -790,10 +769,10 @@ static int wait_for_send_lcredit(struct smbdirect_socket *sc,
return ret;
}
- return wait_for_credits(sc,
- &sc->send_io.lcredits.wait_queue,
- &sc->send_io.lcredits.count,
- 1);
+ return smbdirect_connection_wait_for_credits(sc,
+ &sc->send_io.lcredits.wait_queue,
+ &sc->send_io.lcredits.count,
+ 1);
}
static int wait_for_send_credits(struct smbdirect_socket *sc,
@@ -808,15 +787,18 @@ static int wait_for_send_credits(struct smbdirect_socket *sc,
return ret;
}
- return wait_for_credits(sc, &sc->send_io.credits.wait_queue, &sc->send_io.credits.count, 1);
+ return smbdirect_connection_wait_for_credits(sc,
+ &sc->send_io.credits.wait_queue,
+ &sc->send_io.credits.count,
+ 1);
}
static int wait_for_rw_credits(struct smbdirect_socket *sc, int credits)
{
- return wait_for_credits(sc,
- &sc->rw_io.credits.wait_queue,
- &sc->rw_io.credits.count,
- credits);
+ return smbdirect_connection_wait_for_credits(sc,
+ &sc->rw_io.credits.wait_queue,
+ &sc->rw_io.credits.count,
+ credits);
}
static int calc_rw_credits(struct smbdirect_socket *sc,
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 113/127] smb: server: make use of functions from smbdirect_rw.c
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (111 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 112/127] smb: server: make use of smbdirect_connection_wait_for_credits() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 114/127] smb: server: make use of smbdirect_connection_destroy_sync() Stefan Metzmacher
` (14 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical; +Cc: metze, Namjae Jeon, Steve French, Tom Talpey
The copied code only got new names, some indentation/formatting changes,
some variable names are changed too.
They also only use struct smbdirect_socket instead of
struct smb_direct_transport.
But the logic is still the same.
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>
---
fs/smb/server/transport_rdma.c | 234 ++-------------------------------
1 file changed, 11 insertions(+), 223 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 3902ba403c0f..2845f58301fb 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -253,6 +253,7 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
sc->ib.poll_ctx = IB_POLL_WORKQUEUE;
sc->send_io.mem.gfp_mask = KSMBD_DEFAULT_GFP;
sc->recv_io.mem.gfp_mask = KSMBD_DEFAULT_GFP;
+ sc->rw_io.mem.gfp_mask = KSMBD_DEFAULT_GFP;
/*
* from here we operate on the copy.
*/
@@ -793,21 +794,6 @@ static int wait_for_send_credits(struct smbdirect_socket *sc,
1);
}
-static int wait_for_rw_credits(struct smbdirect_socket *sc, int credits)
-{
- return smbdirect_connection_wait_for_credits(sc,
- &sc->rw_io.credits.wait_queue,
- &sc->rw_io.credits.count,
- credits);
-}
-
-static int calc_rw_credits(struct smbdirect_socket *sc,
- char *buf, unsigned int len)
-{
- return DIV_ROUND_UP(smbdirect_get_buf_page_count(buf, len),
- sc->rw_io.credits.num_pages);
-}
-
static int smb_direct_create_header(struct smbdirect_socket *sc,
int size, int remaining_data_length,
struct smbdirect_send_io **sendmsg_out)
@@ -873,38 +859,6 @@ static int smb_direct_create_header(struct smbdirect_socket *sc,
return 0;
}
-static int get_sg_list(void *buf, int size, struct scatterlist *sg_list, int nentries)
-{
- bool high = is_vmalloc_addr(buf);
- struct page *page;
- int offset, len;
- int i = 0;
-
- if (size <= 0 || nentries < smbdirect_get_buf_page_count(buf, size))
- return -EINVAL;
-
- offset = offset_in_page(buf);
- buf -= offset;
- while (size > 0) {
- len = min_t(int, PAGE_SIZE - offset, size);
- if (high)
- page = vmalloc_to_page(buf);
- else
- page = kmap_to_page(buf);
-
- if (!sg_list)
- return -EINVAL;
- sg_set_page(sg_list, page, len, offset);
- sg_list = sg_next(sg_list);
-
- buf += PAGE_SIZE;
- size -= len;
- offset = 0;
- i++;
- }
- return i;
-}
-
static int post_sendmsg(struct smbdirect_socket *sc,
struct smbdirect_send_batch *send_ctx,
struct smbdirect_send_io *msg)
@@ -1154,185 +1108,16 @@ static int smb_direct_writev(struct ksmbd_transport *t,
return ret;
}
-static void smb_direct_free_rdma_rw_msg(struct smb_direct_transport *t,
- struct smbdirect_rw_io *msg,
- enum dma_data_direction dir)
-{
- struct smbdirect_socket *sc = &t->socket;
-
- rdma_rw_ctx_destroy(&msg->rdma_ctx, sc->ib.qp, sc->ib.qp->port,
- msg->sgt.sgl, msg->sgt.nents, dir);
- sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE);
- kfree(msg);
-}
-
-static void read_write_done(struct ib_cq *cq, struct ib_wc *wc,
- enum dma_data_direction dir)
-{
- struct smbdirect_rw_io *msg =
- container_of(wc->wr_cqe, struct smbdirect_rw_io, cqe);
- struct smbdirect_socket *sc = msg->socket;
-
- if (wc->status != IB_WC_SUCCESS) {
- msg->error = -EIO;
- pr_err("read/write error. opcode = %d, status = %s(%d)\n",
- wc->opcode, ib_wc_status_msg(wc->status), wc->status);
- if (wc->status != IB_WC_WR_FLUSH_ERR)
- smbdirect_connection_schedule_disconnect(sc, msg->error);
- }
-
- complete(msg->completion);
-}
-
-static void read_done(struct ib_cq *cq, struct ib_wc *wc)
-{
- read_write_done(cq, wc, DMA_FROM_DEVICE);
-}
-
-static void write_done(struct ib_cq *cq, struct ib_wc *wc)
-{
- read_write_done(cq, wc, DMA_TO_DEVICE);
-}
-
-static int smb_direct_rdma_xmit(struct smb_direct_transport *t,
- void *buf, int buf_len,
- struct smbdirect_buffer_descriptor_v1 *desc,
- unsigned int desc_len,
- bool is_read)
-{
- struct smbdirect_socket *sc = &t->socket;
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- struct smbdirect_rw_io *msg, *next_msg;
- int i, ret;
- DECLARE_COMPLETION_ONSTACK(completion);
- struct ib_send_wr *first_wr;
- LIST_HEAD(msg_list);
- char *desc_buf;
- int credits_needed;
- unsigned int desc_buf_len, desc_num = 0;
-
- if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
- return -ENOTCONN;
-
- if (buf_len > sp->max_read_write_size)
- return -EINVAL;
-
- /* calculate needed credits */
- credits_needed = 0;
- desc_buf = buf;
- for (i = 0; i < desc_len / sizeof(*desc); i++) {
- if (!buf_len)
- break;
-
- desc_buf_len = le32_to_cpu(desc[i].length);
- if (!desc_buf_len)
- return -EINVAL;
-
- if (desc_buf_len > buf_len) {
- desc_buf_len = buf_len;
- desc[i].length = cpu_to_le32(desc_buf_len);
- buf_len = 0;
- }
-
- credits_needed += calc_rw_credits(sc, desc_buf, desc_buf_len);
- desc_buf += desc_buf_len;
- buf_len -= desc_buf_len;
- desc_num++;
- }
-
- ksmbd_debug(RDMA, "RDMA %s, len %#x, needed credits %#x\n",
- str_read_write(is_read), buf_len, credits_needed);
-
- ret = wait_for_rw_credits(sc, credits_needed);
- if (ret < 0)
- return ret;
-
- /* build rdma_rw_ctx for each descriptor */
- desc_buf = buf;
- for (i = 0; i < desc_num; i++) {
- msg = kzalloc(struct_size(msg, sg_list, SG_CHUNK_SIZE),
- KSMBD_DEFAULT_GFP);
- if (!msg) {
- ret = -ENOMEM;
- goto out;
- }
-
- desc_buf_len = le32_to_cpu(desc[i].length);
-
- msg->socket = sc;
- msg->cqe.done = is_read ? read_done : write_done;
- msg->completion = &completion;
-
- msg->sgt.sgl = &msg->sg_list[0];
- ret = sg_alloc_table_chained(&msg->sgt,
- smbdirect_get_buf_page_count(desc_buf, desc_buf_len),
- msg->sg_list, SG_CHUNK_SIZE);
- if (ret) {
- ret = -ENOMEM;
- goto free_msg;
- }
-
- ret = get_sg_list(desc_buf, desc_buf_len,
- msg->sgt.sgl, msg->sgt.orig_nents);
- if (ret < 0)
- goto free_table;
-
- ret = rdma_rw_ctx_init(&msg->rdma_ctx, sc->ib.qp, sc->ib.qp->port,
- msg->sgt.sgl,
- smbdirect_get_buf_page_count(desc_buf, desc_buf_len),
- 0,
- le64_to_cpu(desc[i].offset),
- le32_to_cpu(desc[i].token),
- is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
- if (ret < 0) {
- pr_err("failed to init rdma_rw_ctx: %d\n", ret);
- goto free_table;
- }
-
- list_add_tail(&msg->list, &msg_list);
- desc_buf += desc_buf_len;
- }
-
- /* concatenate work requests of rdma_rw_ctxs */
- first_wr = NULL;
- list_for_each_entry_reverse(msg, &msg_list, list) {
- first_wr = rdma_rw_ctx_wrs(&msg->rdma_ctx, sc->ib.qp, sc->ib.qp->port,
- &msg->cqe, first_wr);
- }
-
- ret = ib_post_send(sc->ib.qp, first_wr, NULL);
- if (ret) {
- pr_err("failed to post send wr for RDMA R/W: %d\n", ret);
- goto out;
- }
-
- msg = list_last_entry(&msg_list, struct smbdirect_rw_io, list);
- wait_for_completion(&completion);
- ret = msg->error;
-out:
- list_for_each_entry_safe(msg, next_msg, &msg_list, list) {
- list_del(&msg->list);
- smb_direct_free_rdma_rw_msg(t, msg,
- is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
- }
- atomic_add(credits_needed, &sc->rw_io.credits.count);
- wake_up(&sc->rw_io.credits.wait_queue);
- return ret;
-
-free_table:
- sg_free_table_chained(&msg->sgt, SG_CHUNK_SIZE);
-free_msg:
- kfree(msg);
- goto out;
-}
-
static int smb_direct_rdma_write(struct ksmbd_transport *t,
void *buf, unsigned int buflen,
struct smbdirect_buffer_descriptor_v1 *desc,
unsigned int desc_len)
{
- return smb_direct_rdma_xmit(SMBD_TRANS(t), buf, buflen,
- desc, desc_len, false);
+ struct smb_direct_transport *st = SMBD_TRANS(t);
+ struct smbdirect_socket *sc = &st->socket;
+
+ return smbdirect_connection_rdma_xmit(sc, buf, buflen,
+ desc, desc_len, false);
}
static int smb_direct_rdma_read(struct ksmbd_transport *t,
@@ -1340,8 +1125,11 @@ static int smb_direct_rdma_read(struct ksmbd_transport *t,
struct smbdirect_buffer_descriptor_v1 *desc,
unsigned int desc_len)
{
- return smb_direct_rdma_xmit(SMBD_TRANS(t), buf, buflen,
- desc, desc_len, true);
+ struct smb_direct_transport *st = SMBD_TRANS(t);
+ struct smbdirect_socket *sc = &st->socket;
+
+ return smbdirect_connection_rdma_xmit(sc, buf, buflen,
+ desc, desc_len, true);
}
static void smb_direct_disconnect(struct ksmbd_transport *t)
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 114/127] smb: server: make use of smbdirect_connection_destroy_sync()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (112 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 113/127] smb: server: make use of functions from smbdirect_rw.c Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 115/127] smb: server: make use of smbdirect_connection_recvmsg() Stefan Metzmacher
` (13 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical; +Cc: metze, Namjae Jeon, Steve French, Tom Talpey
This is basically the same logic as before, but we now
use common code, which will also be used by the server soon.
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>
---
fs/smb/server/transport_rdma.c | 49 +---------------------------------
1 file changed, 1 insertion(+), 48 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 2845f58301fb..98ecc9f7f482 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -289,56 +289,9 @@ static void smb_direct_free_transport(struct ksmbd_transport *kt)
static void free_transport(struct smb_direct_transport *t)
{
struct smbdirect_socket *sc = &t->socket;
- struct smbdirect_recv_io *recvmsg;
-
- disable_work_sync(&sc->disconnect_work);
- if (sc->status < SMBDIRECT_SOCKET_DISCONNECTING)
- smbdirect_connection_disconnect_work(&sc->disconnect_work);
- if (sc->status < SMBDIRECT_SOCKET_DISCONNECTED)
- wait_event(sc->status_wait, 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
- * smbdirect_connection_disconnect_work(), but call it again...
- */
- smbdirect_connection_wake_up_all(sc);
-
- disable_work_sync(&sc->recv_io.posted.refill_work);
- disable_delayed_work_sync(&sc->idle.timer_work);
- disable_work_sync(&sc->idle.immediate_work);
-
- if (sc->rdma.cm_id)
- rdma_lock_handler(sc->rdma.cm_id);
- if (sc->ib.qp)
- ib_drain_qp(sc->ib.qp);
-
- ksmbd_debug(RDMA, "drain the reassembly queue\n");
- do {
- unsigned long flags;
-
- spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags);
- recvmsg = smbdirect_connection_reassembly_first_recv_io(sc);
- if (recvmsg) {
- list_del(&recvmsg->list);
- spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags);
- smbdirect_connection_put_recv_io(recvmsg);
- } else {
- spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags);
- }
- } while (recvmsg);
- sc->recv_io.reassembly.data_length = 0;
-
- smbdirect_connection_destroy_qp(sc);
- if (sc->rdma.cm_id) {
- rdma_unlock_handler(sc->rdma.cm_id);
- rdma_destroy_id(sc->rdma.cm_id);
- }
+ smbdirect_connection_destroy_sync(sc);
- smbdirect_connection_destroy_mem_pools(sc);
ksmbd_conn_free(KSMBD_TRANS(t)->conn);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 115/127] smb: server: make use of smbdirect_connection_recvmsg()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (113 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 114/127] smb: server: make use of smbdirect_connection_destroy_sync() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 116/127] smb: server: make use of smbdirect_connection_grant_recv_credits() Stefan Metzmacher
` (12 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical; +Cc: metze, Namjae Jeon, Steve French, Tom Talpey
This is basically the same logic, it just operates on iov_iter_kvec()
instead of a raw buffer pointer. This allows us to use common
code between client and server.
We keep returning -EINTR instead of -ERESTARTSYS if
wait_event_interruptible() fails. I don't if this is
required, but changing it is a task for another patch.
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>
---
fs/smb/server/transport_rdma.c | 128 +++------------------------------
1 file changed, 11 insertions(+), 117 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 98ecc9f7f482..d64896a2a1d1 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -201,12 +201,6 @@ static int smb_direct_post_send_data(struct smbdirect_socket *sc,
struct kvec *iov, int niov,
int remaining_data_length);
-static inline void
-*smbdirect_recv_io_payload(struct smbdirect_recv_io *recvmsg)
-{
- return (void *)recvmsg->packet;
-}
-
static void smb_direct_send_immediate_work(struct work_struct *work)
{
struct smbdirect_socket *sc =
@@ -481,121 +475,21 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
static int smb_direct_read(struct ksmbd_transport *t, char *buf,
unsigned int size, int unused)
{
- struct smbdirect_recv_io *recvmsg;
- struct smbdirect_data_transfer *data_transfer;
- int to_copy, to_read, data_read, offset;
- u32 data_length, remaining_data_length, data_offset;
- int rc;
struct smb_direct_transport *st = SMBD_TRANS(t);
struct smbdirect_socket *sc = &st->socket;
+ struct msghdr msg = { .msg_flags = 0, };
+ struct kvec iov = {
+ .iov_base = buf,
+ .iov_len = size,
+ };
+ int ret;
-again:
- if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
- pr_err("disconnected\n");
- return -ENOTCONN;
- }
-
- /*
- * No need to hold the reassembly queue lock all the time as we are
- * the only one reading from the front of the queue. The transport
- * may add more entries to the back of the queue at the same time
- */
- if (sc->recv_io.reassembly.data_length >= size) {
- int queue_length;
- int queue_removed = 0;
- unsigned long flags;
-
- /*
- * Need to make sure reassembly_data_length is read before
- * reading reassembly_queue_length and calling
- * smbdirect_connection_reassembly_first_recv_io. This call is lock free
- * as we never read at the end of the queue which are being
- * updated in SOFTIRQ as more data is received
- */
- virt_rmb();
- queue_length = sc->recv_io.reassembly.queue_length;
- data_read = 0;
- to_read = size;
- offset = sc->recv_io.reassembly.first_entry_offset;
- while (data_read < size) {
- recvmsg = smbdirect_connection_reassembly_first_recv_io(sc);
- data_transfer = smbdirect_recv_io_payload(recvmsg);
- data_length = le32_to_cpu(data_transfer->data_length);
- remaining_data_length =
- le32_to_cpu(data_transfer->remaining_data_length);
- data_offset = le32_to_cpu(data_transfer->data_offset);
-
- /*
- * The upper layer expects RFC1002 length at the
- * beginning of the payload. Return it to indicate
- * the total length of the packet. This minimize the
- * change to upper layer packet processing logic. This
- * will be eventually remove when an intermediate
- * transport layer is added
- */
- if (recvmsg->first_segment && size == 4) {
- unsigned int rfc1002_len =
- data_length + remaining_data_length;
- *((__be32 *)buf) = cpu_to_be32(rfc1002_len);
- data_read = 4;
- recvmsg->first_segment = false;
- ksmbd_debug(RDMA,
- "returning rfc1002 length %d\n",
- rfc1002_len);
- goto read_rfc1002_done;
- }
-
- to_copy = min_t(int, data_length - offset, to_read);
- memcpy(buf + data_read, (char *)data_transfer + data_offset + offset,
- to_copy);
-
- /* move on to the next buffer? */
- if (to_copy == data_length - offset) {
- queue_length--;
- /*
- * No need to lock if we are not at the
- * end of the queue
- */
- if (queue_length) {
- list_del(&recvmsg->list);
- } else {
- spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags);
- list_del(&recvmsg->list);
- spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags);
- }
- queue_removed++;
- smbdirect_connection_put_recv_io(recvmsg);
- offset = 0;
- } else {
- offset += to_copy;
- }
-
- to_read -= to_copy;
- data_read += to_copy;
- }
-
- spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags);
- sc->recv_io.reassembly.data_length -= data_read;
- sc->recv_io.reassembly.queue_length -= queue_removed;
- spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags);
-
- sc->recv_io.reassembly.first_entry_offset = offset;
- ksmbd_debug(RDMA,
- "returning to thread data_read=%d reassembly_data_length=%d first_entry_offset=%d\n",
- data_read, sc->recv_io.reassembly.data_length,
- sc->recv_io.reassembly.first_entry_offset);
-read_rfc1002_done:
- return data_read;
- }
-
- ksmbd_debug(RDMA, "wait_event on more data\n");
- rc = wait_event_interruptible(sc->recv_io.reassembly.wait_queue,
- sc->recv_io.reassembly.data_length >= size ||
- sc->status != SMBDIRECT_SOCKET_CONNECTED);
- if (rc)
- return -EINTR;
+ iov_iter_kvec(&msg.msg_iter, ITER_DEST, &iov, 1, size);
- goto again;
+ ret = smbdirect_connection_recvmsg(sc, &msg, 0);
+ if (ret == -ERESTARTSYS)
+ ret = -EINTR;
+ return ret;
}
static int manage_credits_prior_sending(struct smbdirect_socket *sc)
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 116/127] smb: server: make use of smbdirect_connection_grant_recv_credits()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (114 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 115/127] smb: server: make use of smbdirect_connection_recvmsg() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 117/127] smb: server: make use of smbdirect_connection_request_keep_alive() Stefan Metzmacher
` (11 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical; +Cc: metze, Namjae Jeon, Steve French, Tom Talpey
This is already used by the client too and will
help to share more common code.
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>
---
fs/smb/server/transport_rdma.c | 25 ++++---------------------
1 file changed, 4 insertions(+), 21 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index d64896a2a1d1..55757c66cd44 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -492,25 +492,6 @@ static int smb_direct_read(struct ksmbd_transport *t, char *buf,
return ret;
}
-static int manage_credits_prior_sending(struct smbdirect_socket *sc)
-{
- int new_credits;
-
- if (atomic_read(&sc->recv_io.credits.count) >= sc->recv_io.credits.target)
- return 0;
-
- new_credits = atomic_read(&sc->recv_io.posted.count);
- if (new_credits == 0)
- return 0;
-
- new_credits -= atomic_read(&sc->recv_io.credits.count);
- if (new_credits <= 0)
- return 0;
-
- atomic_add(new_credits, &sc->recv_io.credits.count);
- return new_credits;
-}
-
static int manage_keep_alive_before_sending(struct smbdirect_socket *sc)
{
struct smbdirect_socket_parameters *sp = &sc->parameters;
@@ -648,6 +629,7 @@ static int smb_direct_create_header(struct smbdirect_socket *sc,
struct smbdirect_socket_parameters *sp = &sc->parameters;
struct smbdirect_send_io *sendmsg;
struct smbdirect_data_transfer *packet;
+ u16 new_credits = 0;
int header_length;
int ret;
@@ -658,7 +640,8 @@ static int smb_direct_create_header(struct smbdirect_socket *sc,
/* Fill in the packet header */
packet = (struct smbdirect_data_transfer *)sendmsg->packet;
packet->credits_requested = cpu_to_le16(sp->send_credit_target);
- packet->credits_granted = cpu_to_le16(manage_credits_prior_sending(sc));
+ new_credits = smbdirect_connection_grant_recv_credits(sc);
+ packet->credits_granted = cpu_to_le16(new_credits);
packet->flags = 0;
if (manage_keep_alive_before_sending(sc))
@@ -1064,7 +1047,7 @@ static int smb_direct_send_negotiate_response(struct smbdirect_socket *sc,
resp->reserved = 0;
resp->credits_requested =
cpu_to_le16(sp->send_credit_target);
- resp->credits_granted = cpu_to_le16(manage_credits_prior_sending(sc));
+ resp->credits_granted = cpu_to_le16(smbdirect_connection_grant_recv_credits(sc));
resp->max_readwrite_size = cpu_to_le32(sp->max_read_write_size);
resp->preferred_send_size = cpu_to_le32(sp->max_send_size);
resp->max_receive_size = cpu_to_le32(sp->max_recv_size);
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 117/127] smb: server: make use of smbdirect_connection_request_keep_alive()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (115 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 116/127] smb: server: make use of smbdirect_connection_grant_recv_credits() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 118/127] smb: server: move iov_iter_kvec() out of smb_direct_post_send_data() Stefan Metzmacher
` (10 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical; +Cc: metze, Namjae Jeon, Steve French, Tom Talpey
This will help to share more common code soon.
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>
---
fs/smb/server/transport_rdma.c | 19 +------------------
1 file changed, 1 insertion(+), 18 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 55757c66cd44..72cd64149785 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -492,23 +492,6 @@ static int smb_direct_read(struct ksmbd_transport *t, char *buf,
return ret;
}
-static int manage_keep_alive_before_sending(struct smbdirect_socket *sc)
-{
- struct smbdirect_socket_parameters *sp = &sc->parameters;
-
- if (sc->idle.keepalive == SMBDIRECT_KEEPALIVE_PENDING) {
- sc->idle.keepalive = SMBDIRECT_KEEPALIVE_SENT;
- /*
- * Now use the keepalive timeout (instead of keepalive interval)
- * in order to wait for a response
- */
- mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
- msecs_to_jiffies(sp->keepalive_timeout_msec));
- return 1;
- }
- return 0;
-}
-
static int smb_direct_post_send(struct smbdirect_socket *sc,
struct ib_send_wr *wr)
{
@@ -644,7 +627,7 @@ static int smb_direct_create_header(struct smbdirect_socket *sc,
packet->credits_granted = cpu_to_le16(new_credits);
packet->flags = 0;
- if (manage_keep_alive_before_sending(sc))
+ if (smbdirect_connection_request_keep_alive(sc))
packet->flags |= cpu_to_le16(SMBDIRECT_FLAG_RESPONSE_REQUESTED);
packet->reserved = 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 118/127] smb: server: move iov_iter_kvec() out of smb_direct_post_send_data()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (116 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 117/127] smb: server: make use of smbdirect_connection_request_keep_alive() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 119/127] smb: server: inline smb_direct_create_header() into smb_direct_post_send_data() Stefan Metzmacher
` (9 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical; +Cc: metze, Namjae Jeon, Steve French, Tom Talpey
This will allow us to make the code more generic in order
to move it to common with the client.
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>
---
fs/smb/server/transport_rdma.c | 38 ++++++++++++++++++----------------
1 file changed, 20 insertions(+), 18 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 72cd64149785..03aedfa92c88 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -198,8 +198,8 @@ unsigned int get_smbd_max_read_write_size(struct ksmbd_transport *kt)
static int smb_direct_post_send_data(struct smbdirect_socket *sc,
struct smbdirect_send_batch *send_ctx,
- struct kvec *iov, int niov,
- int remaining_data_length);
+ struct iov_iter *iter,
+ size_t *remaining_data_length);
static void smb_direct_send_immediate_work(struct work_struct *work)
{
@@ -209,7 +209,7 @@ static void smb_direct_send_immediate_work(struct work_struct *work)
if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
return;
- smb_direct_post_send_data(sc, NULL, NULL, 0, 0);
+ smb_direct_post_send_data(sc, NULL, NULL, NULL);
}
static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
@@ -712,12 +712,13 @@ static int post_sendmsg(struct smbdirect_socket *sc,
static int smb_direct_post_send_data(struct smbdirect_socket *sc,
struct smbdirect_send_batch *send_ctx,
- struct kvec *iov, int niov,
- int remaining_data_length)
+ struct iov_iter *iter,
+ size_t *_remaining_data_length)
{
- int i, ret;
struct smbdirect_send_io *msg;
- int data_length;
+ u32 remaining_data_length = 0;
+ u32 data_length = 0;
+ int ret;
ret = wait_for_send_lcredit(sc, send_ctx);
if (ret)
@@ -727,16 +728,20 @@ static int smb_direct_post_send_data(struct smbdirect_socket *sc,
if (ret)
goto credit_failed;
- data_length = 0;
- for (i = 0; i < niov; i++)
- data_length += iov[i].iov_len;
+ if (iter)
+ data_length = iov_iter_count(iter);
+
+ if (_remaining_data_length) {
+ *_remaining_data_length -= data_length;
+ remaining_data_length = *_remaining_data_length;
+ }
ret = smb_direct_create_header(sc, data_length, remaining_data_length,
&msg);
if (ret)
goto header_failed;
- if (data_length) {
+ if (iter) {
struct smbdirect_map_sges extract = {
.num_sge = msg->num_sge,
.max_sge = ARRAY_SIZE(msg->sge),
@@ -745,11 +750,8 @@ static int smb_direct_post_send_data(struct smbdirect_socket *sc,
.local_dma_lkey = sc->ib.pd->local_dma_lkey,
.direction = DMA_TO_DEVICE,
};
- struct iov_iter iter;
-
- iov_iter_kvec(&iter, ITER_SOURCE, iov, niov, data_length);
- ret = smbdirect_map_sges_from_iter(&iter, data_length, &extract);
+ ret = smbdirect_map_sges_from_iter(iter, data_length, &extract);
if (ret < 0)
goto err;
if (WARN_ON_ONCE(ret != data_length)) {
@@ -809,6 +811,7 @@ static int smb_direct_writev(struct ksmbd_transport *t,
size_t possible_vecs;
size_t bytes = 0;
size_t nvecs = 0;
+ struct iov_iter iter;
/*
* For the last message remaining_data_length should be
@@ -889,11 +892,10 @@ static int smb_direct_writev(struct ksmbd_transport *t,
}
}
- remaining_data_length -= bytes;
+ iov_iter_kvec(&iter, ITER_SOURCE, vecs, nvecs, bytes);
ret = smb_direct_post_send_data(sc, &send_ctx,
- vecs, nvecs,
- remaining_data_length);
+ &iter, &remaining_data_length);
if (unlikely(ret)) {
error = ret;
goto done;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 119/127] smb: server: inline smb_direct_create_header() into smb_direct_post_send_data()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (117 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 118/127] smb: server: move iov_iter_kvec() out of smb_direct_post_send_data() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 120/127] smb: server: let smbdirect_map_sges_from_iter() truncate the message boundary Stefan Metzmacher
` (8 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical; +Cc: metze, Namjae Jeon, Steve French, Tom Talpey
The point is that ib_dma_map_single() is done first, but
the 'Fill in the packet header' will be done after
smbdirect_map_sges_from_iter().
This will simplify further changes in order to
share common code with the client.
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>
---
fs/smb/server/transport_rdma.c | 128 +++++++++++++++------------------
1 file changed, 57 insertions(+), 71 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 03aedfa92c88..463520e1c07c 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -605,73 +605,6 @@ static int wait_for_send_credits(struct smbdirect_socket *sc,
1);
}
-static int smb_direct_create_header(struct smbdirect_socket *sc,
- int size, int remaining_data_length,
- struct smbdirect_send_io **sendmsg_out)
-{
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- struct smbdirect_send_io *sendmsg;
- struct smbdirect_data_transfer *packet;
- u16 new_credits = 0;
- int header_length;
- int ret;
-
- sendmsg = smbdirect_connection_alloc_send_io(sc);
- if (IS_ERR(sendmsg))
- return PTR_ERR(sendmsg);
-
- /* Fill in the packet header */
- packet = (struct smbdirect_data_transfer *)sendmsg->packet;
- packet->credits_requested = cpu_to_le16(sp->send_credit_target);
- new_credits = smbdirect_connection_grant_recv_credits(sc);
- packet->credits_granted = cpu_to_le16(new_credits);
-
- packet->flags = 0;
- if (smbdirect_connection_request_keep_alive(sc))
- packet->flags |= cpu_to_le16(SMBDIRECT_FLAG_RESPONSE_REQUESTED);
-
- packet->reserved = 0;
- if (!size)
- packet->data_offset = 0;
- else
- packet->data_offset = cpu_to_le32(24);
- packet->data_length = cpu_to_le32(size);
- packet->remaining_data_length = cpu_to_le32(remaining_data_length);
- packet->padding = 0;
-
- ksmbd_debug(RDMA,
- "credits_requested=%d credits_granted=%d data_offset=%d data_length=%d remaining_data_length=%d\n",
- le16_to_cpu(packet->credits_requested),
- le16_to_cpu(packet->credits_granted),
- le32_to_cpu(packet->data_offset),
- le32_to_cpu(packet->data_length),
- le32_to_cpu(packet->remaining_data_length));
-
- /* Map the packet to DMA */
- header_length = sizeof(struct smbdirect_data_transfer);
- /* If this is a packet without payload, don't send padding */
- if (!size)
- header_length =
- offsetof(struct smbdirect_data_transfer, padding);
-
- sendmsg->sge[0].addr = ib_dma_map_single(sc->ib.dev,
- (void *)packet,
- header_length,
- DMA_TO_DEVICE);
- ret = ib_dma_mapping_error(sc->ib.dev, sendmsg->sge[0].addr);
- if (ret) {
- smbdirect_connection_free_send_io(sendmsg);
- return ret;
- }
-
- sendmsg->num_sge = 1;
- sendmsg->sge[0].length = header_length;
- sendmsg->sge[0].lkey = sc->ib.pd->local_dma_lkey;
-
- *sendmsg_out = sendmsg;
- return 0;
-}
-
static int post_sendmsg(struct smbdirect_socket *sc,
struct smbdirect_send_batch *send_ctx,
struct smbdirect_send_io *msg)
@@ -715,11 +648,22 @@ static int smb_direct_post_send_data(struct smbdirect_socket *sc,
struct iov_iter *iter,
size_t *_remaining_data_length)
{
+ const struct smbdirect_socket_parameters *sp = &sc->parameters;
struct smbdirect_send_io *msg;
+ struct smbdirect_data_transfer *packet;
+ size_t header_length;
+ u16 new_credits = 0;
u32 remaining_data_length = 0;
u32 data_length = 0;
int ret;
+ if (iter) {
+ header_length = sizeof(struct smbdirect_data_transfer);
+ } else {
+ /* If this is a packet without payload, don't send padding */
+ header_length = offsetof(struct smbdirect_data_transfer, padding);
+ }
+
ret = wait_for_send_lcredit(sc, send_ctx);
if (ret)
goto lcredit_failed;
@@ -736,10 +680,24 @@ static int smb_direct_post_send_data(struct smbdirect_socket *sc,
remaining_data_length = *_remaining_data_length;
}
- ret = smb_direct_create_header(sc, data_length, remaining_data_length,
- &msg);
+ msg = smbdirect_connection_alloc_send_io(sc);
+ if (IS_ERR(msg)) {
+ ret = PTR_ERR(msg);
+ goto alloc_failed;
+ }
+
+ /* Map the packet to DMA */
+ msg->sge[0].addr = ib_dma_map_single(sc->ib.dev,
+ msg->packet,
+ header_length,
+ DMA_TO_DEVICE);
+ ret = ib_dma_mapping_error(sc->ib.dev, msg->sge[0].addr);
if (ret)
- goto header_failed;
+ goto err;
+
+ msg->sge[0].length = header_length;
+ msg->sge[0].lkey = sc->ib.pd->local_dma_lkey;
+ msg->num_sge = 1;
if (iter) {
struct smbdirect_map_sges extract = {
@@ -761,13 +719,41 @@ static int smb_direct_post_send_data(struct smbdirect_socket *sc,
msg->num_sge = extract.num_sge;
}
+ /* Fill in the packet header */
+ packet = (struct smbdirect_data_transfer *)msg->packet;
+ packet->credits_requested = cpu_to_le16(sp->send_credit_target);
+ new_credits = smbdirect_connection_grant_recv_credits(sc);
+ packet->credits_granted = cpu_to_le16(new_credits);
+
+ packet->flags = 0;
+ if (smbdirect_connection_request_keep_alive(sc))
+ packet->flags |= cpu_to_le16(SMBDIRECT_FLAG_RESPONSE_REQUESTED);
+
+ packet->reserved = 0;
+ if (!data_length)
+ packet->data_offset = 0;
+ else
+ packet->data_offset = cpu_to_le32(24);
+ packet->data_length = cpu_to_le32(data_length);
+ packet->remaining_data_length = cpu_to_le32(remaining_data_length);
+ packet->padding = 0;
+
+ ksmbd_debug(RDMA,
+ "credits_req=%u credits_granted=%u flags=0x%x ofs=%u len=%u remaining=%u\n",
+ le16_to_cpu(packet->credits_requested),
+ le16_to_cpu(packet->credits_granted),
+ le16_to_cpu(packet->flags),
+ le32_to_cpu(packet->data_offset),
+ le32_to_cpu(packet->data_length),
+ le32_to_cpu(packet->remaining_data_length));
+
ret = post_sendmsg(sc, send_ctx, msg);
if (ret)
goto err;
return 0;
err:
smbdirect_connection_free_send_io(msg);
-header_failed:
+alloc_failed:
atomic_inc(&sc->send_io.credits.count);
credit_failed:
atomic_inc(&sc->send_io.lcredits.count);
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 120/127] smb: server: let smbdirect_map_sges_from_iter() truncate the message boundary
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (118 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 119/127] smb: server: inline smb_direct_create_header() into smb_direct_post_send_data() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 121/127] smb: server: split out smb_direct_send_iter() out of smb_direct_writev() Stefan Metzmacher
` (7 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical; +Cc: metze, Namjae Jeon, Steve French, Tom Talpey
smbdirect_map_sges_from_iter() already handles the case that only
a limited number of sges are available. Its return value
is data_length and the remaining bytes in the iter are
remaining_data_length.
This is now much easier and will allow us to share
more code with the client soon.
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>
---
fs/smb/server/transport_rdma.c | 151 +++++++--------------------------
1 file changed, 31 insertions(+), 120 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 463520e1c07c..d888b5396cd6 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -199,7 +199,7 @@ unsigned int get_smbd_max_read_write_size(struct ksmbd_transport *kt)
static int smb_direct_post_send_data(struct smbdirect_socket *sc,
struct smbdirect_send_batch *send_ctx,
struct iov_iter *iter,
- size_t *remaining_data_length);
+ u32 remaining_data_length);
static void smb_direct_send_immediate_work(struct work_struct *work)
{
@@ -209,7 +209,7 @@ static void smb_direct_send_immediate_work(struct work_struct *work)
if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
return;
- smb_direct_post_send_data(sc, NULL, NULL, NULL);
+ smb_direct_post_send_data(sc, NULL, NULL, 0);
}
static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
@@ -646,22 +646,26 @@ static int post_sendmsg(struct smbdirect_socket *sc,
static int smb_direct_post_send_data(struct smbdirect_socket *sc,
struct smbdirect_send_batch *send_ctx,
struct iov_iter *iter,
- size_t *_remaining_data_length)
+ u32 remaining_data_length)
{
const struct smbdirect_socket_parameters *sp = &sc->parameters;
struct smbdirect_send_io *msg;
struct smbdirect_data_transfer *packet;
size_t header_length;
u16 new_credits = 0;
- u32 remaining_data_length = 0;
u32 data_length = 0;
int ret;
if (iter) {
header_length = sizeof(struct smbdirect_data_transfer);
+ if (WARN_ON_ONCE(remaining_data_length == 0 ||
+ iov_iter_count(iter) > remaining_data_length))
+ return -EINVAL;
} else {
/* If this is a packet without payload, don't send padding */
header_length = offsetof(struct smbdirect_data_transfer, padding);
+ if (WARN_ON_ONCE(remaining_data_length))
+ return -EINVAL;
}
ret = wait_for_send_lcredit(sc, send_ctx);
@@ -672,14 +676,6 @@ static int smb_direct_post_send_data(struct smbdirect_socket *sc,
if (ret)
goto credit_failed;
- if (iter)
- data_length = iov_iter_count(iter);
-
- if (_remaining_data_length) {
- *_remaining_data_length -= data_length;
- remaining_data_length = *_remaining_data_length;
- }
-
msg = smbdirect_connection_alloc_send_io(sc);
if (IS_ERR(msg)) {
ret = PTR_ERR(msg);
@@ -708,14 +704,14 @@ static int smb_direct_post_send_data(struct smbdirect_socket *sc,
.local_dma_lkey = sc->ib.pd->local_dma_lkey,
.direction = DMA_TO_DEVICE,
};
+ size_t payload_len = umin(iov_iter_count(iter),
+ sp->max_send_size - sizeof(*packet));
- ret = smbdirect_map_sges_from_iter(iter, data_length, &extract);
+ ret = smbdirect_map_sges_from_iter(iter, payload_len, &extract);
if (ret < 0)
goto err;
- if (WARN_ON_ONCE(ret != data_length)) {
- ret = -EIO;
- goto err;
- }
+ data_length = ret;
+ remaining_data_length -= data_length;
msg->num_sge = extract.num_sge;
}
@@ -768,13 +764,9 @@ static int smb_direct_writev(struct ksmbd_transport *t,
struct smb_direct_transport *st = SMBD_TRANS(t);
struct smbdirect_socket *sc = &st->socket;
struct smbdirect_socket_parameters *sp = &sc->parameters;
- size_t remaining_data_length;
- size_t iov_idx;
- size_t iov_ofs;
- size_t max_iov_size = sp->max_send_size -
- sizeof(struct smbdirect_data_transfer);
int ret;
struct smbdirect_send_batch send_ctx;
+ struct iov_iter iter;
int error = 0;
if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
@@ -783,112 +775,31 @@ static int smb_direct_writev(struct ksmbd_transport *t,
//FIXME: skip RFC1002 header..
if (WARN_ON_ONCE(niovs <= 1 || iov[0].iov_len != 4))
return -EINVAL;
- buflen -= 4;
- iov_idx = 1;
- iov_ofs = 0;
-
- remaining_data_length = buflen;
- ksmbd_debug(RDMA, "Sending smb (RDMA): smb_len=%u\n", buflen);
-
- smb_direct_send_ctx_init(&send_ctx, need_invalidate, remote_key);
- while (remaining_data_length) {
- struct kvec vecs[SMBDIRECT_SEND_IO_MAX_SGE - 1]; /* minus smbdirect hdr */
- size_t possible_bytes = max_iov_size;
- size_t possible_vecs;
- size_t bytes = 0;
- size_t nvecs = 0;
- struct iov_iter iter;
-
- /*
- * For the last message remaining_data_length should be
- * have been 0 already!
- */
- if (WARN_ON_ONCE(iov_idx >= niovs)) {
- error = -EINVAL;
- goto done;
- }
+ iov_iter_kvec(&iter, ITER_SOURCE, iov, niovs, buflen);
+ iov_iter_advance(&iter, 4);
- /*
- * We have 2 factors which limit the arguments we pass
- * to smb_direct_post_send_data():
- *
- * 1. The number of supported sges for the send,
- * while one is reserved for the smbdirect header.
- * And we currently need one SGE per page.
- * 2. The number of negotiated payload bytes per send.
- */
- possible_vecs = min_t(size_t, ARRAY_SIZE(vecs), niovs - iov_idx);
-
- while (iov_idx < niovs && possible_vecs && possible_bytes) {
- struct kvec *v = &vecs[nvecs];
- int page_count;
-
- v->iov_base = ((u8 *)iov[iov_idx].iov_base) + iov_ofs;
- v->iov_len = min_t(size_t,
- iov[iov_idx].iov_len - iov_ofs,
- possible_bytes);
- page_count = smbdirect_get_buf_page_count(v->iov_base, v->iov_len);
- if (page_count > possible_vecs) {
- /*
- * If the number of pages in the buffer
- * is to much (because we currently require
- * one SGE per page), we need to limit the
- * length.
- *
- * We know possible_vecs is at least 1,
- * so we always keep the first page.
- *
- * We need to calculate the number extra
- * pages (epages) we can also keep.
- *
- * We calculate the number of bytes in the
- * first page (fplen), this should never be
- * larger than v->iov_len because page_count is
- * at least 2, but adding a limitation feels
- * better.
- *
- * Then we calculate the number of bytes (elen)
- * we can keep for the extra pages.
- */
- size_t epages = possible_vecs - 1;
- size_t fpofs = offset_in_page(v->iov_base);
- size_t fplen = min_t(size_t, PAGE_SIZE - fpofs, v->iov_len);
- size_t elen = min_t(size_t, v->iov_len - fplen, epages*PAGE_SIZE);
-
- v->iov_len = fplen + elen;
- page_count = smbdirect_get_buf_page_count(v->iov_base, v->iov_len);
- if (WARN_ON_ONCE(page_count > possible_vecs)) {
- /*
- * Something went wrong in the above
- * logic...
- */
- error = -EINVAL;
- goto done;
- }
- }
- possible_vecs -= page_count;
- nvecs += 1;
- possible_bytes -= v->iov_len;
- bytes += v->iov_len;
-
- iov_ofs += v->iov_len;
- if (iov_ofs >= iov[iov_idx].iov_len) {
- iov_idx += 1;
- iov_ofs = 0;
- }
- }
+ /*
+ * The size must fit into the negotiated
+ * fragmented send size.
+ */
+ if (iov_iter_count(&iter) > sp->max_fragmented_send_size)
+ return -EMSGSIZE;
- iov_iter_kvec(&iter, ITER_SOURCE, vecs, nvecs, bytes);
+ ksmbd_debug(RDMA, "Sending smb (RDMA): smb_len=%zu\n",
+ iov_iter_count(&iter));
- ret = smb_direct_post_send_data(sc, &send_ctx,
- &iter, &remaining_data_length);
+ smb_direct_send_ctx_init(&send_ctx, need_invalidate, remote_key);
+ while (iov_iter_count(&iter)) {
+ ret = smb_direct_post_send_data(sc,
+ &send_ctx,
+ &iter,
+ iov_iter_count(&iter));
if (unlikely(ret)) {
error = ret;
- goto done;
+ break;
}
}
-done:
ret = smb_direct_flush_send_list(sc, &send_ctx, true);
if (unlikely(!ret && error))
ret = error;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 121/127] smb: server: split out smb_direct_send_iter() out of smb_direct_writev()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (119 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 120/127] smb: server: let smbdirect_map_sges_from_iter() truncate the message boundary Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 122/127] smb: server: let smb_direct_post_send_data() return data_length Stefan Metzmacher
` (6 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical; +Cc: metze, Namjae Jeon, Steve French, Tom Talpey
This will help to move to common code in future.
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>
---
fs/smb/server/transport_rdma.c | 47 +++++++++++++++++++++++-----------
1 file changed, 32 insertions(+), 15 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index d888b5396cd6..8a5183426bbb 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -757,43 +757,47 @@ static int smb_direct_post_send_data(struct smbdirect_socket *sc,
return ret;
}
-static int smb_direct_writev(struct ksmbd_transport *t,
- struct kvec *iov, int niovs, int buflen,
- bool need_invalidate, unsigned int remote_key)
+static int smb_direct_send_iter(struct smbdirect_socket *sc,
+ struct iov_iter *iter,
+ bool need_invalidate,
+ unsigned int remote_key)
{
- struct smb_direct_transport *st = SMBD_TRANS(t);
- struct smbdirect_socket *sc = &st->socket;
struct smbdirect_socket_parameters *sp = &sc->parameters;
int ret;
struct smbdirect_send_batch send_ctx;
- struct iov_iter iter;
int error = 0;
+ __be32 hdr;
if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
return -ENOTCONN;
- //FIXME: skip RFC1002 header..
- if (WARN_ON_ONCE(niovs <= 1 || iov[0].iov_len != 4))
+ /*
+ * For now we expect the iter to have the full
+ * message, including a 4 byte length header.
+ */
+ if (iov_iter_count(iter) <= 4)
+ return -EINVAL;
+ if (!copy_from_iter_full(&hdr, sizeof(hdr), iter))
+ return -EFAULT;
+ if (iov_iter_count(iter) != be32_to_cpu(hdr))
return -EINVAL;
- iov_iter_kvec(&iter, ITER_SOURCE, iov, niovs, buflen);
- iov_iter_advance(&iter, 4);
/*
* The size must fit into the negotiated
* fragmented send size.
*/
- if (iov_iter_count(&iter) > sp->max_fragmented_send_size)
+ if (iov_iter_count(iter) > sp->max_fragmented_send_size)
return -EMSGSIZE;
ksmbd_debug(RDMA, "Sending smb (RDMA): smb_len=%zu\n",
- iov_iter_count(&iter));
+ iov_iter_count(iter));
smb_direct_send_ctx_init(&send_ctx, need_invalidate, remote_key);
- while (iov_iter_count(&iter)) {
+ while (iov_iter_count(iter)) {
ret = smb_direct_post_send_data(sc,
&send_ctx,
- &iter,
- iov_iter_count(&iter));
+ iter,
+ iov_iter_count(iter));
if (unlikely(ret)) {
error = ret;
break;
@@ -820,6 +824,19 @@ static int smb_direct_writev(struct ksmbd_transport *t,
return ret;
}
+static int smb_direct_writev(struct ksmbd_transport *t,
+ struct kvec *iov, int niovs, int buflen,
+ bool need_invalidate, unsigned int remote_key)
+{
+ struct smb_direct_transport *st = SMBD_TRANS(t);
+ struct smbdirect_socket *sc = &st->socket;
+ struct iov_iter iter;
+
+ iov_iter_kvec(&iter, ITER_SOURCE, iov, niovs, buflen);
+
+ return smb_direct_send_iter(sc, &iter, need_invalidate, remote_key);
+}
+
static int smb_direct_rdma_write(struct ksmbd_transport *t,
void *buf, unsigned int buflen,
struct smbdirect_buffer_descriptor_v1 *desc,
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 122/127] smb: server: let smb_direct_post_send_data() return data_length
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (120 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 121/127] smb: server: split out smb_direct_send_iter() out of smb_direct_writev() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 123/127] smb: server: make use of smbdirect_connection_send_iter() and related functions Stefan Metzmacher
` (5 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical; +Cc: metze, Namjae Jeon, Steve French, Tom Talpey
This make it easier moving to common code shared with the client.
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>
---
fs/smb/server/transport_rdma.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 8a5183426bbb..070c386dd2ea 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -746,7 +746,7 @@ static int smb_direct_post_send_data(struct smbdirect_socket *sc,
ret = post_sendmsg(sc, send_ctx, msg);
if (ret)
goto err;
- return 0;
+ return data_length;
err:
smbdirect_connection_free_send_io(msg);
alloc_failed:
@@ -798,7 +798,7 @@ static int smb_direct_send_iter(struct smbdirect_socket *sc,
&send_ctx,
iter,
iov_iter_count(iter));
- if (unlikely(ret)) {
+ if (unlikely(ret < 0)) {
error = ret;
break;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 123/127] smb: server: make use of smbdirect_connection_send_iter() and related functions
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (121 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 122/127] smb: server: let smb_direct_post_send_data() return data_length Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 124/127] smb: server: make use of smbdirect_{socket_init_accepting,connection_wait_for_connected}() Stefan Metzmacher
` (4 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical; +Cc: metze, Namjae Jeon, Steve French, Tom Talpey
This makes use of common code for sending messages, this will
allow to make more use of common code in the next commits.
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>
---
fs/smb/server/transport_rdma.c | 355 +--------------------------------
1 file changed, 4 insertions(+), 351 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 070c386dd2ea..e3a410d773f6 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -196,22 +196,6 @@ unsigned int get_smbd_max_read_write_size(struct ksmbd_transport *kt)
return sp->max_read_write_size;
}
-static int smb_direct_post_send_data(struct smbdirect_socket *sc,
- struct smbdirect_send_batch *send_ctx,
- struct iov_iter *iter,
- u32 remaining_data_length);
-
-static void smb_direct_send_immediate_work(struct work_struct *work)
-{
- struct smbdirect_socket *sc =
- container_of(work, struct smbdirect_socket, idle.immediate_work);
-
- if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
- return;
-
- smb_direct_post_send_data(sc, NULL, NULL, 0);
-}
-
static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
{
struct smb_direct_transport *t;
@@ -492,338 +476,6 @@ static int smb_direct_read(struct ksmbd_transport *t, char *buf,
return ret;
}
-static int smb_direct_post_send(struct smbdirect_socket *sc,
- struct ib_send_wr *wr)
-{
- int ret;
-
- atomic_inc(&sc->send_io.pending.count);
- ret = ib_post_send(sc->ib.qp, wr, NULL);
- if (ret) {
- pr_err("failed to post send: %d\n", ret);
- smbdirect_connection_schedule_disconnect(sc, ret);
- }
- return ret;
-}
-
-static void smb_direct_send_ctx_init(struct smbdirect_send_batch *send_ctx,
- bool need_invalidate_rkey,
- unsigned int remote_key)
-{
- INIT_LIST_HEAD(&send_ctx->msg_list);
- send_ctx->wr_cnt = 0;
- send_ctx->need_invalidate_rkey = need_invalidate_rkey;
- send_ctx->remote_key = remote_key;
-}
-
-static int smb_direct_flush_send_list(struct smbdirect_socket *sc,
- struct smbdirect_send_batch *send_ctx,
- bool is_last)
-{
- struct smbdirect_send_io *first, *last;
- int ret;
-
- if (list_empty(&send_ctx->msg_list))
- return 0;
-
- first = list_first_entry(&send_ctx->msg_list,
- struct smbdirect_send_io,
- sibling_list);
- last = list_last_entry(&send_ctx->msg_list,
- struct smbdirect_send_io,
- sibling_list);
-
- if (send_ctx->need_invalidate_rkey) {
- first->wr.opcode = IB_WR_SEND_WITH_INV;
- first->wr.ex.invalidate_rkey = send_ctx->remote_key;
- send_ctx->need_invalidate_rkey = false;
- send_ctx->remote_key = 0;
- }
-
- last->wr.send_flags = IB_SEND_SIGNALED;
- last->wr.wr_cqe = &last->cqe;
-
- /*
- * Remove last from send_ctx->msg_list
- * and splice the rest of send_ctx->msg_list
- * to last->sibling_list.
- *
- * send_ctx->msg_list is a valid empty list
- * at the end.
- */
- list_del_init(&last->sibling_list);
- list_splice_tail_init(&send_ctx->msg_list, &last->sibling_list);
- send_ctx->wr_cnt = 0;
-
- ret = smb_direct_post_send(sc, &first->wr);
- if (ret) {
- struct smbdirect_send_io *sibling, *next;
-
- list_for_each_entry_safe(sibling, next, &last->sibling_list, sibling_list) {
- list_del_init(&sibling->sibling_list);
- smbdirect_connection_free_send_io(sibling);
- }
- smbdirect_connection_free_send_io(last);
- }
-
- return ret;
-}
-
-
-static int wait_for_send_lcredit(struct smbdirect_socket *sc,
- struct smbdirect_send_batch *send_ctx)
-{
- if (send_ctx && (atomic_read(&sc->send_io.lcredits.count) <= 1)) {
- int ret;
-
- ret = smb_direct_flush_send_list(sc, send_ctx, false);
- if (ret)
- return ret;
- }
-
- return smbdirect_connection_wait_for_credits(sc,
- &sc->send_io.lcredits.wait_queue,
- &sc->send_io.lcredits.count,
- 1);
-}
-
-static int wait_for_send_credits(struct smbdirect_socket *sc,
- struct smbdirect_send_batch *send_ctx)
-{
- int ret;
-
- if (send_ctx &&
- (send_ctx->wr_cnt >= 16 || atomic_read(&sc->send_io.credits.count) <= 1)) {
- ret = smb_direct_flush_send_list(sc, send_ctx, false);
- if (ret)
- return ret;
- }
-
- return smbdirect_connection_wait_for_credits(sc,
- &sc->send_io.credits.wait_queue,
- &sc->send_io.credits.count,
- 1);
-}
-
-static int post_sendmsg(struct smbdirect_socket *sc,
- struct smbdirect_send_batch *send_ctx,
- struct smbdirect_send_io *msg)
-{
- int i;
-
- for (i = 0; i < msg->num_sge; i++)
- ib_dma_sync_single_for_device(sc->ib.dev,
- msg->sge[i].addr, msg->sge[i].length,
- DMA_TO_DEVICE);
-
- msg->cqe.done = smbdirect_connection_send_io_done;
- msg->wr.opcode = IB_WR_SEND;
- msg->wr.sg_list = &msg->sge[0];
- msg->wr.num_sge = msg->num_sge;
- msg->wr.next = NULL;
-
- if (send_ctx) {
- msg->wr.wr_cqe = NULL;
- msg->wr.send_flags = 0;
- if (!list_empty(&send_ctx->msg_list)) {
- struct smbdirect_send_io *last;
-
- last = list_last_entry(&send_ctx->msg_list,
- struct smbdirect_send_io,
- sibling_list);
- last->wr.next = &msg->wr;
- }
- list_add_tail(&msg->sibling_list, &send_ctx->msg_list);
- send_ctx->wr_cnt++;
- return 0;
- }
-
- msg->wr.wr_cqe = &msg->cqe;
- msg->wr.send_flags = IB_SEND_SIGNALED;
- return smb_direct_post_send(sc, &msg->wr);
-}
-
-static int smb_direct_post_send_data(struct smbdirect_socket *sc,
- struct smbdirect_send_batch *send_ctx,
- struct iov_iter *iter,
- u32 remaining_data_length)
-{
- const struct smbdirect_socket_parameters *sp = &sc->parameters;
- struct smbdirect_send_io *msg;
- struct smbdirect_data_transfer *packet;
- size_t header_length;
- u16 new_credits = 0;
- u32 data_length = 0;
- int ret;
-
- if (iter) {
- header_length = sizeof(struct smbdirect_data_transfer);
- if (WARN_ON_ONCE(remaining_data_length == 0 ||
- iov_iter_count(iter) > remaining_data_length))
- return -EINVAL;
- } else {
- /* If this is a packet without payload, don't send padding */
- header_length = offsetof(struct smbdirect_data_transfer, padding);
- if (WARN_ON_ONCE(remaining_data_length))
- return -EINVAL;
- }
-
- ret = wait_for_send_lcredit(sc, send_ctx);
- if (ret)
- goto lcredit_failed;
-
- ret = wait_for_send_credits(sc, send_ctx);
- if (ret)
- goto credit_failed;
-
- msg = smbdirect_connection_alloc_send_io(sc);
- if (IS_ERR(msg)) {
- ret = PTR_ERR(msg);
- goto alloc_failed;
- }
-
- /* Map the packet to DMA */
- msg->sge[0].addr = ib_dma_map_single(sc->ib.dev,
- msg->packet,
- header_length,
- DMA_TO_DEVICE);
- ret = ib_dma_mapping_error(sc->ib.dev, msg->sge[0].addr);
- if (ret)
- goto err;
-
- msg->sge[0].length = header_length;
- msg->sge[0].lkey = sc->ib.pd->local_dma_lkey;
- msg->num_sge = 1;
-
- if (iter) {
- struct smbdirect_map_sges extract = {
- .num_sge = msg->num_sge,
- .max_sge = ARRAY_SIZE(msg->sge),
- .sge = msg->sge,
- .device = sc->ib.dev,
- .local_dma_lkey = sc->ib.pd->local_dma_lkey,
- .direction = DMA_TO_DEVICE,
- };
- size_t payload_len = umin(iov_iter_count(iter),
- sp->max_send_size - sizeof(*packet));
-
- ret = smbdirect_map_sges_from_iter(iter, payload_len, &extract);
- if (ret < 0)
- goto err;
- data_length = ret;
- remaining_data_length -= data_length;
- msg->num_sge = extract.num_sge;
- }
-
- /* Fill in the packet header */
- packet = (struct smbdirect_data_transfer *)msg->packet;
- packet->credits_requested = cpu_to_le16(sp->send_credit_target);
- new_credits = smbdirect_connection_grant_recv_credits(sc);
- packet->credits_granted = cpu_to_le16(new_credits);
-
- packet->flags = 0;
- if (smbdirect_connection_request_keep_alive(sc))
- packet->flags |= cpu_to_le16(SMBDIRECT_FLAG_RESPONSE_REQUESTED);
-
- packet->reserved = 0;
- if (!data_length)
- packet->data_offset = 0;
- else
- packet->data_offset = cpu_to_le32(24);
- packet->data_length = cpu_to_le32(data_length);
- packet->remaining_data_length = cpu_to_le32(remaining_data_length);
- packet->padding = 0;
-
- ksmbd_debug(RDMA,
- "credits_req=%u credits_granted=%u flags=0x%x ofs=%u len=%u remaining=%u\n",
- le16_to_cpu(packet->credits_requested),
- le16_to_cpu(packet->credits_granted),
- le16_to_cpu(packet->flags),
- le32_to_cpu(packet->data_offset),
- le32_to_cpu(packet->data_length),
- le32_to_cpu(packet->remaining_data_length));
-
- ret = post_sendmsg(sc, send_ctx, msg);
- if (ret)
- goto err;
- return data_length;
-err:
- smbdirect_connection_free_send_io(msg);
-alloc_failed:
- atomic_inc(&sc->send_io.credits.count);
-credit_failed:
- atomic_inc(&sc->send_io.lcredits.count);
-lcredit_failed:
- return ret;
-}
-
-static int smb_direct_send_iter(struct smbdirect_socket *sc,
- struct iov_iter *iter,
- bool need_invalidate,
- unsigned int remote_key)
-{
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- int ret;
- struct smbdirect_send_batch send_ctx;
- int error = 0;
- __be32 hdr;
-
- if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
- return -ENOTCONN;
-
- /*
- * For now we expect the iter to have the full
- * message, including a 4 byte length header.
- */
- if (iov_iter_count(iter) <= 4)
- return -EINVAL;
- if (!copy_from_iter_full(&hdr, sizeof(hdr), iter))
- return -EFAULT;
- if (iov_iter_count(iter) != be32_to_cpu(hdr))
- return -EINVAL;
-
- /*
- * The size must fit into the negotiated
- * fragmented send size.
- */
- if (iov_iter_count(iter) > sp->max_fragmented_send_size)
- return -EMSGSIZE;
-
- ksmbd_debug(RDMA, "Sending smb (RDMA): smb_len=%zu\n",
- iov_iter_count(iter));
-
- smb_direct_send_ctx_init(&send_ctx, need_invalidate, remote_key);
- while (iov_iter_count(iter)) {
- ret = smb_direct_post_send_data(sc,
- &send_ctx,
- iter,
- iov_iter_count(iter));
- if (unlikely(ret < 0)) {
- error = ret;
- break;
- }
- }
-
- ret = smb_direct_flush_send_list(sc, &send_ctx, true);
- if (unlikely(!ret && error))
- ret = error;
-
- /*
- * As an optimization, we don't wait for individual I/O to finish
- * before sending the next one.
- * Send them all and wait for pending send count to get to 0
- * that means all the I/Os have been out and we are good to return
- */
-
- wait_event(sc->send_io.pending.zero_wait_queue,
- atomic_read(&sc->send_io.pending.count) == 0 ||
- sc->status != SMBDIRECT_SOCKET_CONNECTED);
- if (sc->status != SMBDIRECT_SOCKET_CONNECTED && ret == 0)
- ret = -ENOTCONN;
-
- return ret;
-}
-
static int smb_direct_writev(struct ksmbd_transport *t,
struct kvec *iov, int niovs, int buflen,
bool need_invalidate, unsigned int remote_key)
@@ -834,7 +486,8 @@ static int smb_direct_writev(struct ksmbd_transport *t,
iov_iter_kvec(&iter, ITER_SOURCE, iov, niovs, buflen);
- return smb_direct_send_iter(sc, &iter, need_invalidate, remote_key);
+ return smbdirect_connection_send_iter(sc, &iter, 0,
+ need_invalidate, remote_key);
}
static int smb_direct_rdma_write(struct ksmbd_transport *t,
@@ -970,7 +623,7 @@ static int smb_direct_send_negotiate_response(struct smbdirect_socket *sc,
sendmsg->sge[0].length = sizeof(*resp);
sendmsg->sge[0].lkey = sc->ib.pd->local_dma_lkey;
- ret = post_sendmsg(sc, NULL, sendmsg);
+ ret = smbdirect_connection_post_send_io(sc, NULL, sendmsg);
if (ret) {
smbdirect_connection_free_send_io(sendmsg);
return ret;
@@ -1178,7 +831,7 @@ static int smb_direct_prepare(struct ksmbd_transport *t)
return ret;
INIT_WORK(&sc->recv_io.posted.refill_work, smbdirect_connection_recv_io_refill_work);
- INIT_WORK(&sc->idle.immediate_work, smb_direct_send_immediate_work);
+ INIT_WORK(&sc->idle.immediate_work, smbdirect_connection_send_immediate_work);
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 124/127] smb: server: make use of smbdirect_{socket_init_accepting,connection_wait_for_connected}()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (122 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 123/127] smb: server: make use of smbdirect_connection_send_iter() and related functions Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 125/127] smb: server: make use of smbdirect_socket_create_accepting()/smbdirect_socket_release() Stefan Metzmacher
` (3 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical; +Cc: metze, Namjae Jeon, Steve French, Tom Talpey
This means we finally only use common functions in the server.
We still use the embedded struct smbdirect_socket and are
able to access internals, but the will be removed in the
next commits as well.
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>
---
fs/smb/server/transport_rdma.c | 575 ++-------------------------------
1 file changed, 30 insertions(+), 545 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index e3a410d773f6..d6162b8be58b 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -17,6 +17,7 @@
#include <linux/highmem.h>
#include <linux/scatterlist.h>
#include <linux/string_choices.h>
+#include <linux/errname.h>
#include <rdma/ib_verbs.h>
#include <rdma/rdma_cm.h>
#include <rdma/rw.h>
@@ -184,14 +185,14 @@ unsigned int get_smbd_max_read_write_size(struct ksmbd_transport *kt)
{
struct smb_direct_transport *t;
struct smbdirect_socket *sc;
- struct smbdirect_socket_parameters *sp;
+ const struct smbdirect_socket_parameters *sp;
if (kt->ops != &ksmbd_smb_direct_transport_ops)
return 0;
t = SMBD_TRANS(kt);
sc = &t->socket;
- sp = &sc->parameters;
+ sp = smbdirect_socket_get_current_parameters(sc);
return sp->max_read_write_size;
}
@@ -203,6 +204,7 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
struct smbdirect_socket_parameters init_params = {};
struct smbdirect_socket_parameters *sp;
struct ksmbd_conn *conn;
+ int ret;
/*
* Create the initial parameters
@@ -224,27 +226,25 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
if (!t)
return NULL;
sc = &t->socket;
- smbdirect_socket_prepare_create(sc, sp, smb_direct_wq);
+ ret = smbdirect_socket_init_accepting(cm_id, sc);
+ if (ret)
+ goto socket_init_failed;
smbdirect_socket_set_logging(sc, NULL,
smb_direct_logging_needed,
smb_direct_logging_vaprintf);
- sc->ib.poll_ctx = IB_POLL_WORKQUEUE;
- sc->send_io.mem.gfp_mask = KSMBD_DEFAULT_GFP;
- sc->recv_io.mem.gfp_mask = KSMBD_DEFAULT_GFP;
- sc->rw_io.mem.gfp_mask = KSMBD_DEFAULT_GFP;
- /*
- * from here we operate on the copy.
- */
- sp = &sc->parameters;
-
- sc->rdma.cm_id = cm_id;
- cm_id->context = sc;
-
- sc->ib.dev = sc->rdma.cm_id->device;
+ 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;
+ ret = smbdirect_socket_set_custom_workqueue(sc, smb_direct_wq);
+ if (ret)
+ goto set_workqueue_failed;
conn = ksmbd_conn_alloc();
if (!conn)
- goto err;
+ goto conn_alloc_failed;
down_write(&conn_list_lock);
hash_add(conn_list, &conn->hlist, 0);
@@ -254,7 +254,12 @@ 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;
return t;
-err:
+
+conn_alloc_failed:
+set_workqueue_failed:
+set_settings_failed:
+set_params_failed:
+socket_init_failed:
kfree(t);
return NULL;
}
@@ -273,189 +278,6 @@ static void free_transport(struct smb_direct_transport *t)
ksmbd_conn_free(KSMBD_TRANS(t)->conn);
}
-static int smb_direct_check_recvmsg(struct smbdirect_recv_io *recvmsg)
-{
- struct smbdirect_socket *sc = recvmsg->socket;
-
- switch (sc->recv_io.expected) {
- case SMBDIRECT_EXPECT_DATA_TRANSFER: {
- struct smbdirect_data_transfer *req =
- (struct smbdirect_data_transfer *)recvmsg->packet;
- struct smb2_hdr *hdr = (struct smb2_hdr *)(recvmsg->packet
- + le32_to_cpu(req->data_offset));
- ksmbd_debug(RDMA,
- "CreditGranted: %u, CreditRequested: %u, DataLength: %u, RemainingDataLength: %u, SMB: %x, Command: %u\n",
- le16_to_cpu(req->credits_granted),
- le16_to_cpu(req->credits_requested),
- req->data_length, req->remaining_data_length,
- hdr->ProtocolId, hdr->Command);
- return 0;
- }
- case SMBDIRECT_EXPECT_NEGOTIATE_REQ: {
- struct smbdirect_negotiate_req *req =
- (struct smbdirect_negotiate_req *)recvmsg->packet;
- ksmbd_debug(RDMA,
- "MinVersion: %u, MaxVersion: %u, CreditRequested: %u, MaxSendSize: %u, MaxRecvSize: %u, MaxFragmentedSize: %u\n",
- le16_to_cpu(req->min_version),
- le16_to_cpu(req->max_version),
- le16_to_cpu(req->credits_requested),
- le32_to_cpu(req->preferred_send_size),
- le32_to_cpu(req->max_receive_size),
- le32_to_cpu(req->max_fragmented_size));
- if (le16_to_cpu(req->min_version) > 0x0100 ||
- le16_to_cpu(req->max_version) < 0x0100)
- return -EOPNOTSUPP;
- if (le16_to_cpu(req->credits_requested) <= 0 ||
- le32_to_cpu(req->max_receive_size) <= 128 ||
- le32_to_cpu(req->max_fragmented_size) <=
- 128 * 1024)
- return -ECONNABORTED;
-
- return 0;
- }
- case SMBDIRECT_EXPECT_NEGOTIATE_REP:
- /* client only */
- break;
- }
-
- /* This is an internal error */
- return -EINVAL;
-}
-
-static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
-{
- struct smbdirect_recv_io *recvmsg;
- struct smbdirect_socket *sc;
- struct smbdirect_socket_parameters *sp;
-
- recvmsg = container_of(wc->wr_cqe, struct smbdirect_recv_io, cqe);
- sc = recvmsg->socket;
- sp = &sc->parameters;
-
- if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_RECV) {
- smbdirect_connection_put_recv_io(recvmsg);
- if (wc->status != IB_WC_WR_FLUSH_ERR) {
- pr_err("Recv error. status='%s (%d)' opcode=%d\n",
- ib_wc_status_msg(wc->status), wc->status,
- wc->opcode);
- smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
- }
- return;
- }
-
- ksmbd_debug(RDMA, "Recv completed. status='%s (%d)', opcode=%d\n",
- ib_wc_status_msg(wc->status), wc->status,
- wc->opcode);
-
- ib_dma_sync_single_for_cpu(wc->qp->device, recvmsg->sge.addr,
- recvmsg->sge.length, DMA_FROM_DEVICE);
-
- /*
- * Reset timer to the keepalive interval in
- * order to trigger our next keepalive message.
- */
- sc->idle.keepalive = SMBDIRECT_KEEPALIVE_NONE;
- mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
- msecs_to_jiffies(sp->keepalive_interval_msec));
-
- switch (sc->recv_io.expected) {
- case SMBDIRECT_EXPECT_NEGOTIATE_REQ:
- if (wc->byte_len < sizeof(struct smbdirect_negotiate_req)) {
- smbdirect_connection_put_recv_io(recvmsg);
- smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
- return;
- }
- sc->recv_io.reassembly.full_packet_received = true;
- WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_NEGOTIATE_NEEDED);
- sc->status = SMBDIRECT_SOCKET_NEGOTIATE_RUNNING;
- smbdirect_connection_reassembly_append_recv_io(sc, recvmsg, 0);
- wake_up(&sc->status_wait);
- return;
- case SMBDIRECT_EXPECT_DATA_TRANSFER: {
- struct smbdirect_data_transfer *data_transfer =
- (struct smbdirect_data_transfer *)recvmsg->packet;
- u32 remaining_data_length, data_offset, data_length;
- u16 old_recv_credit_target;
-
- if (wc->byte_len <
- offsetof(struct smbdirect_data_transfer, padding)) {
- smbdirect_connection_put_recv_io(recvmsg);
- smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
- return;
- }
-
- remaining_data_length = le32_to_cpu(data_transfer->remaining_data_length);
- data_length = le32_to_cpu(data_transfer->data_length);
- data_offset = le32_to_cpu(data_transfer->data_offset);
- if (wc->byte_len < data_offset ||
- wc->byte_len < (u64)data_offset + data_length) {
- smbdirect_connection_put_recv_io(recvmsg);
- smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
- return;
- }
- if (remaining_data_length > sp->max_fragmented_recv_size ||
- data_length > sp->max_fragmented_recv_size ||
- (u64)remaining_data_length + (u64)data_length >
- (u64)sp->max_fragmented_recv_size) {
- smbdirect_connection_put_recv_io(recvmsg);
- smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
- return;
- }
-
- if (data_length) {
- if (sc->recv_io.reassembly.full_packet_received)
- recvmsg->first_segment = true;
-
- if (le32_to_cpu(data_transfer->remaining_data_length))
- sc->recv_io.reassembly.full_packet_received = false;
- else
- sc->recv_io.reassembly.full_packet_received = true;
- }
-
- atomic_dec(&sc->recv_io.posted.count);
- atomic_dec(&sc->recv_io.credits.count);
-
- old_recv_credit_target = sc->recv_io.credits.target;
- sc->recv_io.credits.target =
- le16_to_cpu(data_transfer->credits_requested);
- sc->recv_io.credits.target =
- min_t(u16, sc->recv_io.credits.target, sp->recv_credit_max);
- sc->recv_io.credits.target =
- max_t(u16, sc->recv_io.credits.target, 1);
- atomic_add(le16_to_cpu(data_transfer->credits_granted),
- &sc->send_io.credits.count);
-
- if (le16_to_cpu(data_transfer->flags) &
- SMBDIRECT_FLAG_RESPONSE_REQUESTED)
- queue_work(sc->workqueue, &sc->idle.immediate_work);
-
- if (atomic_read(&sc->send_io.credits.count) > 0)
- wake_up(&sc->send_io.credits.wait_queue);
-
- if (data_length) {
- if (sc->recv_io.credits.target > old_recv_credit_target)
- queue_work(sc->workqueue, &sc->recv_io.posted.refill_work);
-
- smbdirect_connection_reassembly_append_recv_io(sc, recvmsg, data_length);
- wake_up(&sc->recv_io.reassembly.wait_queue);
- } else
- smbdirect_connection_put_recv_io(recvmsg);
-
- return;
- }
- case SMBDIRECT_EXPECT_NEGOTIATE_REP:
- /* client only */
- break;
- }
-
- /*
- * This is an internal error!
- */
- WARN_ON_ONCE(sc->recv_io.expected != SMBDIRECT_EXPECT_DATA_TRANSFER);
- smbdirect_connection_put_recv_io(recvmsg);
- smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
-}
-
static int smb_direct_read(struct ksmbd_transport *t, char *buf,
unsigned int size, int unused)
{
@@ -531,344 +353,24 @@ static void smb_direct_shutdown(struct ksmbd_transport *t)
ksmbd_debug(RDMA, "smb-direct shutdown cm_id=%p\n", sc->rdma.cm_id);
- smbdirect_connection_disconnect_work(&sc->disconnect_work);
-}
-
-static int smb_direct_cm_handler(struct rdma_cm_id *cm_id,
- struct rdma_cm_event *event)
-{
- struct smbdirect_socket *sc = cm_id->context;
-
- ksmbd_debug(RDMA, "RDMA CM event. cm_id=%p event=%s (%d)\n",
- cm_id, rdma_event_msg(event->event), event->event);
-
- switch (event->event) {
- case RDMA_CM_EVENT_ESTABLISHED: {
- WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING);
- sc->status = SMBDIRECT_SOCKET_NEGOTIATE_NEEDED;
- wake_up(&sc->status_wait);
- break;
- }
- case RDMA_CM_EVENT_DEVICE_REMOVAL:
- case RDMA_CM_EVENT_DISCONNECTED: {
- sc->status = SMBDIRECT_SOCKET_DISCONNECTED;
- smbdirect_connection_disconnect_work(&sc->disconnect_work);
- if (sc->ib.qp)
- ib_drain_qp(sc->ib.qp);
- break;
- }
- case RDMA_CM_EVENT_CONNECT_ERROR: {
- sc->status = SMBDIRECT_SOCKET_DISCONNECTED;
- smbdirect_connection_disconnect_work(&sc->disconnect_work);
- break;
- }
- default:
- pr_err("Unexpected RDMA CM event. cm_id=%p, event=%s (%d)\n",
- cm_id, rdma_event_msg(event->event),
- event->event);
- break;
- }
- return 0;
-}
-
-static int smb_direct_send_negotiate_response(struct smbdirect_socket *sc,
- int failed)
-{
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- struct smbdirect_send_io *sendmsg;
- struct smbdirect_negotiate_resp *resp;
- int ret;
-
- sendmsg = smbdirect_connection_alloc_send_io(sc);
- if (IS_ERR(sendmsg))
- return -ENOMEM;
-
- resp = (struct smbdirect_negotiate_resp *)sendmsg->packet;
- if (failed) {
- memset(resp, 0, sizeof(*resp));
- 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;
- resp->max_version = SMB_DIRECT_VERSION_LE;
- resp->negotiated_version = SMB_DIRECT_VERSION_LE;
- resp->reserved = 0;
- resp->credits_requested =
- cpu_to_le16(sp->send_credit_target);
- resp->credits_granted = cpu_to_le16(smbdirect_connection_grant_recv_credits(sc));
- resp->max_readwrite_size = cpu_to_le32(sp->max_read_write_size);
- resp->preferred_send_size = cpu_to_le32(sp->max_send_size);
- resp->max_receive_size = cpu_to_le32(sp->max_recv_size);
- resp->max_fragmented_size =
- 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,
- (void *)resp, sizeof(*resp),
- DMA_TO_DEVICE);
- ret = ib_dma_mapping_error(sc->ib.dev, sendmsg->sge[0].addr);
- if (ret) {
- smbdirect_connection_free_send_io(sendmsg);
- return ret;
- }
-
- sendmsg->num_sge = 1;
- sendmsg->sge[0].length = sizeof(*resp);
- sendmsg->sge[0].lkey = sc->ib.pd->local_dma_lkey;
-
- ret = smbdirect_connection_post_send_io(sc, NULL, sendmsg);
- if (ret) {
- smbdirect_connection_free_send_io(sendmsg);
- return ret;
- }
-
- wait_event(sc->send_io.pending.zero_wait_queue,
- atomic_read(&sc->send_io.pending.count) == 0 ||
- sc->status != SMBDIRECT_SOCKET_CONNECTED);
- if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
- return -ENOTCONN;
-
- return 0;
-}
-
-static int smb_direct_accept_client(struct smbdirect_socket *sc)
-{
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- struct rdma_conn_param conn_param;
- __be32 ird_ord_hdr[2];
- int ret;
-
- /*
- * smb_direct_handle_connect_request()
- * already negotiated sp->initiator_depth
- * and sp->responder_resources
- */
- memset(&conn_param, 0, sizeof(conn_param));
- conn_param.initiator_depth = sp->initiator_depth;
- conn_param.responder_resources = sp->responder_resources;
-
- if (sc->rdma.legacy_iwarp) {
- ird_ord_hdr[0] = cpu_to_be32(conn_param.responder_resources);
- ird_ord_hdr[1] = cpu_to_be32(conn_param.initiator_depth);
- conn_param.private_data = ird_ord_hdr;
- conn_param.private_data_len = sizeof(ird_ord_hdr);
- } else {
- conn_param.private_data = NULL;
- conn_param.private_data_len = 0;
- }
- conn_param.retry_count = SMB_DIRECT_CM_RETRY;
- conn_param.rnr_retry_count = SMB_DIRECT_CM_RNR_RETRY;
- conn_param.flow_control = 0;
-
- /*
- * start with the negotiate timeout and SMBDIRECT_KEEPALIVE_PENDING
- * so that the timer will cause a disconnect.
- */
- sc->idle.keepalive = SMBDIRECT_KEEPALIVE_PENDING;
- mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
- msecs_to_jiffies(sp->negotiate_timeout_msec));
-
- 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);
- return ret;
- }
- return 0;
-}
-
-static int smb_direct_prepare_negotiation(struct smbdirect_socket *sc)
-{
- struct smbdirect_recv_io *recvmsg;
- int ret;
-
- WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_CREATED);
- sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED;
-
- sc->recv_io.expected = SMBDIRECT_EXPECT_NEGOTIATE_REQ;
-
- recvmsg = smbdirect_connection_get_recv_io(sc);
- if (!recvmsg)
- return -ENOMEM;
-
- ret = smbdirect_connection_post_recv_io(recvmsg);
- if (ret) {
- pr_err("Can't post recv: %d\n", ret);
- goto out_err;
- }
-
- ret = smb_direct_accept_client(sc);
- if (ret) {
- pr_err("Can't accept client\n");
- goto out_err;
- }
-
- return 0;
-out_err:
- smbdirect_connection_put_recv_io(recvmsg);
- return ret;
-}
-
-static int smb_direct_init_params(struct smbdirect_socket *sc)
-{
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- int max_send_sges;
- unsigned int maxpages;
-
- /* need 3 more sge. because a SMB_DIRECT header, SMB2 header,
- * SMB2 response could be mapped.
- */
- max_send_sges = DIV_ROUND_UP(sp->max_send_size, PAGE_SIZE) + 3;
- if (max_send_sges > SMBDIRECT_SEND_IO_MAX_SGE) {
- pr_err("max_send_size %d is too large\n", sp->max_send_size);
- return -EINVAL;
- }
-
- atomic_set(&sc->send_io.lcredits.count, sp->send_credit_target);
-
- maxpages = DIV_ROUND_UP(sp->max_read_write_size, PAGE_SIZE);
- sc->rw_io.credits.max = rdma_rw_mr_factor(sc->ib.dev,
- sc->rdma.cm_id->port_num,
- maxpages);
- sc->rw_io.credits.num_pages = DIV_ROUND_UP(maxpages, sc->rw_io.credits.max);
- /* add one extra in order to handle unaligned pages */
- sc->rw_io.credits.max += 1;
-
- sc->recv_io.credits.target = 1;
-
- atomic_set(&sc->rw_io.credits.count, sc->rw_io.credits.max);
-
- return 0;
+ 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;
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- struct smbdirect_recv_io *recvmsg;
- struct smbdirect_negotiate_req *req;
- unsigned long flags;
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,
- sc->status != SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED &&
- sc->status != SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING &&
- sc->status != SMBDIRECT_SOCKET_NEGOTIATE_NEEDED,
- msecs_to_jiffies(sp->negotiate_timeout_msec));
- if (ret <= 0 || sc->status != SMBDIRECT_SOCKET_NEGOTIATE_RUNNING)
- return ret < 0 ? ret : -ETIMEDOUT;
-
- recvmsg = smbdirect_connection_reassembly_first_recv_io(sc);
- if (!recvmsg)
- return -ECONNABORTED;
-
- ret = smb_direct_check_recvmsg(recvmsg);
- if (ret)
- goto put;
-
- req = (struct smbdirect_negotiate_req *)recvmsg->packet;
- sp->max_recv_size = min_t(int, sp->max_recv_size,
- le32_to_cpu(req->preferred_send_size));
- sp->max_send_size = min_t(int, sp->max_send_size,
- le32_to_cpu(req->max_receive_size));
- sp->max_fragmented_send_size =
- le32_to_cpu(req->max_fragmented_size);
- sp->max_fragmented_recv_size =
- (sp->recv_credit_max * sp->max_recv_size) / 2;
- sc->recv_io.credits.target = le16_to_cpu(req->credits_requested);
- sc->recv_io.credits.target = min_t(u16, sc->recv_io.credits.target, sp->recv_credit_max);
- sc->recv_io.credits.target = max_t(u16, sc->recv_io.credits.target, 1);
-
-put:
- spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags);
- sc->recv_io.reassembly.queue_length--;
- list_del(&recvmsg->list);
- spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags);
- smbdirect_connection_put_recv_io(recvmsg);
-
- if (ret == -ECONNABORTED)
- return ret;
-
- if (ret)
- goto respond;
-
- /*
- * We negotiated with success, so we need to refill the recv queue.
- *
- * The message that grants the credits to the client is
- * the negotiate response.
- */
- ret = smbdirect_connection_recv_io_refill(sc);
- if (ret < 0)
- return ret;
- ret = 0;
-
-respond:
- ret = smb_direct_send_negotiate_response(sc, ret);
- if (ret)
- return ret;
-
- INIT_WORK(&sc->recv_io.posted.refill_work, smbdirect_connection_recv_io_refill_work);
- INIT_WORK(&sc->idle.immediate_work, smbdirect_connection_send_immediate_work);
-
- return 0;
-}
-
-static int smb_direct_connect(struct smbdirect_socket *sc)
-{
- struct smbdirect_recv_io *recv_io;
- int ret;
-
- sc->rdma.cm_id->event_handler = smb_direct_cm_handler;
-
- ret = smb_direct_init_params(sc);
+ ksmbd_debug(RDMA, "SMB_DIRECT Waiting for connection\n");
+ ret = smbdirect_connection_wait_for_connected(sc);
if (ret) {
- pr_err("Can't configure RDMA parameters\n");
+ ksmbd_debug(RDMA, "SMB_DIRECT connection failed %d => %s\n",
+ ret, errname(ret));
return ret;
}
- ret = smbdirect_connection_create_mem_pools(sc);
- if (ret) {
- pr_err("Can't init RDMA pool: %d\n", ret);
- return ret;
- }
-
- list_for_each_entry(recv_io, &sc->recv_io.free.list, list)
- recv_io->cqe.done = recv_done;
-
- ret = smbdirect_connection_create_qp(sc);
- if (ret) {
- pr_err("Can't accept RDMA client: %d\n", ret);
- return ret;
- }
-
- ret = smb_direct_prepare_negotiation(sc);
- if (ret) {
- pr_err("Can't negotiate: %d\n", ret);
- return ret;
- }
+ ksmbd_debug(RDMA, "SMB_DIRECT connection ready\n");
return 0;
}
@@ -877,10 +379,7 @@ static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id,
{
struct smb_direct_transport *t;
struct smbdirect_socket *sc;
- struct smbdirect_socket_parameters *sp;
struct task_struct *handler;
- u8 peer_initiator_depth;
- u8 peer_responder_resources;
int ret;
if (!smbdirect_frwr_is_supported(&new_cm_id->device->attrs)) {
@@ -894,22 +393,8 @@ static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id,
if (!t)
return -ENOMEM;
sc = &t->socket;
- sp = &sc->parameters;
-
- /*
- * First set what the we as server are able to support
- */
- sp->initiator_depth = min_t(u8, sp->initiator_depth,
- sc->ib.dev->attrs.max_qp_rd_atom);
-
- peer_initiator_depth = event->param.conn.initiator_depth;
- peer_responder_resources = event->param.conn.responder_resources;
- smbdirect_connection_negotiate_rdma_resources(sc,
- peer_initiator_depth,
- peer_responder_resources,
- &event->param.conn);
- ret = smb_direct_connect(sc);
+ ret = smbdirect_accept_connect_request(sc, &event->param.conn);
if (ret)
goto out_err;
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 125/127] smb: server: make use of smbdirect_socket_create_accepting()/smbdirect_socket_release()
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (123 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 124/127] smb: server: make use of smbdirect_{socket_init_accepting,connection_wait_for_connected}() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 126/127] smb: server: only use public smbdirect functions Stefan Metzmacher
` (2 subsequent siblings)
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical; +Cc: metze, Namjae Jeon, Steve French, Tom Talpey
With this we no longer embed struct smbdirect_socket, which will allow
us to make it private in the following commits.
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>
---
fs/smb/server/transport_rdma.c | 53 +++++++++++++++-------------------
1 file changed, 23 insertions(+), 30 deletions(-)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index d6162b8be58b..85aed6963c86 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -42,8 +42,6 @@
#define SMB_DIRECT_PORT_IWARP 5445
#define SMB_DIRECT_PORT_INFINIBAND 445
-#define SMB_DIRECT_VERSION_LE cpu_to_le16(SMBDIRECT_V1)
-
/* SMB_DIRECT negotiation timeout (for the server) in seconds */
#define SMB_DIRECT_NEGOTIATE_TIMEOUT 5
@@ -59,11 +57,6 @@
*/
#define SMB_DIRECT_CM_INITIATOR_DEPTH 8
-/* Maximum number of retries on data transfer operations */
-#define SMB_DIRECT_CM_RETRY 6
-/* No need to retry on Receiver Not Ready since SMB_DIRECT manages credits */
-#define SMB_DIRECT_CM_RNR_RETRY 0
-
/*
* User configurable initial values per SMB_DIRECT transport connection
* as defined in [MS-SMBD] 3.1.1.1
@@ -107,7 +100,7 @@ static struct workqueue_struct *smb_direct_wq;
struct smb_direct_transport {
struct ksmbd_transport transport;
- struct smbdirect_socket socket;
+ struct smbdirect_socket *socket;
};
static bool smb_direct_logging_needed(struct smbdirect_socket *sc,
@@ -184,15 +177,13 @@ void init_smbd_max_io_size(unsigned int sz)
unsigned int get_smbd_max_read_write_size(struct ksmbd_transport *kt)
{
struct smb_direct_transport *t;
- struct smbdirect_socket *sc;
const struct smbdirect_socket_parameters *sp;
if (kt->ops != &ksmbd_smb_direct_transport_ops)
return 0;
t = SMBD_TRANS(kt);
- sc = &t->socket;
- sp = smbdirect_socket_get_current_parameters(sc);
+ sp = smbdirect_socket_get_current_parameters(t->socket);
return sp->max_read_write_size;
}
@@ -225,10 +216,9 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
t = kzalloc(sizeof(*t), KSMBD_DEFAULT_GFP);
if (!t)
return NULL;
- sc = &t->socket;
- ret = smbdirect_socket_init_accepting(cm_id, sc);
+ ret = smbdirect_socket_create_accepting(cm_id, &sc);
if (ret)
- goto socket_init_failed;
+ goto socket_create_failed;
smbdirect_socket_set_logging(sc, NULL,
smb_direct_logging_needed,
smb_direct_logging_vaprintf);
@@ -253,28 +243,31 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
conn->transport = KSMBD_TRANS(t);
KSMBD_TRANS(t)->conn = conn;
KSMBD_TRANS(t)->ops = &ksmbd_smb_direct_transport_ops;
+
+ t->socket = sc;
return t;
conn_alloc_failed:
set_workqueue_failed:
set_settings_failed:
set_params_failed:
-socket_init_failed:
+ smbdirect_socket_release(sc);
+socket_create_failed:
kfree(t);
return NULL;
}
static void smb_direct_free_transport(struct ksmbd_transport *kt)
{
- kfree(SMBD_TRANS(kt));
+ struct smb_direct_transport *t = SMBD_TRANS(kt);
+
+ smbdirect_socket_release(t->socket);
+ kfree(t);
}
static void free_transport(struct smb_direct_transport *t)
{
- struct smbdirect_socket *sc = &t->socket;
-
- smbdirect_connection_destroy_sync(sc);
-
+ smbdirect_socket_shutdown(t->socket);
ksmbd_conn_free(KSMBD_TRANS(t)->conn);
}
@@ -282,7 +275,7 @@ static int smb_direct_read(struct ksmbd_transport *t, char *buf,
unsigned int size, int unused)
{
struct smb_direct_transport *st = SMBD_TRANS(t);
- struct smbdirect_socket *sc = &st->socket;
+ struct smbdirect_socket *sc = st->socket;
struct msghdr msg = { .msg_flags = 0, };
struct kvec iov = {
.iov_base = buf,
@@ -303,7 +296,7 @@ static int smb_direct_writev(struct ksmbd_transport *t,
bool need_invalidate, unsigned int remote_key)
{
struct smb_direct_transport *st = SMBD_TRANS(t);
- struct smbdirect_socket *sc = &st->socket;
+ struct smbdirect_socket *sc = st->socket;
struct iov_iter iter;
iov_iter_kvec(&iter, ITER_SOURCE, iov, niovs, buflen);
@@ -318,7 +311,7 @@ static int smb_direct_rdma_write(struct ksmbd_transport *t,
unsigned int desc_len)
{
struct smb_direct_transport *st = SMBD_TRANS(t);
- struct smbdirect_socket *sc = &st->socket;
+ struct smbdirect_socket *sc = st->socket;
return smbdirect_connection_rdma_xmit(sc, buf, buflen,
desc, desc_len, false);
@@ -330,7 +323,7 @@ static int smb_direct_rdma_read(struct ksmbd_transport *t,
unsigned int desc_len)
{
struct smb_direct_transport *st = SMBD_TRANS(t);
- struct smbdirect_socket *sc = &st->socket;
+ struct smbdirect_socket *sc = st->socket;
return smbdirect_connection_rdma_xmit(sc, buf, buflen,
desc, desc_len, true);
@@ -339,9 +332,9 @@ static int smb_direct_rdma_read(struct ksmbd_transport *t,
static void smb_direct_disconnect(struct ksmbd_transport *t)
{
struct smb_direct_transport *st = SMBD_TRANS(t);
- struct smbdirect_socket *sc = &st->socket;
+ struct smbdirect_socket *sc = st->socket;
- ksmbd_debug(RDMA, "Disconnecting cm_id=%p\n", sc->rdma.cm_id);
+ ksmbd_debug(RDMA, "Disconnecting sc=%p\n", sc);
free_transport(st);
}
@@ -349,9 +342,9 @@ static void smb_direct_disconnect(struct ksmbd_transport *t)
static void smb_direct_shutdown(struct ksmbd_transport *t)
{
struct smb_direct_transport *st = SMBD_TRANS(t);
- struct smbdirect_socket *sc = &st->socket;
+ struct smbdirect_socket *sc = st->socket;
- ksmbd_debug(RDMA, "smb-direct shutdown cm_id=%p\n", sc->rdma.cm_id);
+ ksmbd_debug(RDMA, "smb-direct shutdown sc=%p\n", sc);
smbdirect_socket_shutdown(sc);
}
@@ -359,7 +352,7 @@ static void smb_direct_shutdown(struct ksmbd_transport *t)
static int smb_direct_prepare(struct ksmbd_transport *t)
{
struct smb_direct_transport *st = SMBD_TRANS(t);
- struct smbdirect_socket *sc = &st->socket;
+ struct smbdirect_socket *sc = st->socket;
int ret;
ksmbd_debug(RDMA, "SMB_DIRECT Waiting for connection\n");
@@ -392,7 +385,7 @@ static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id,
t = alloc_transport(new_cm_id);
if (!t)
return -ENOMEM;
- sc = &t->socket;
+ sc = t->socket;
ret = smbdirect_accept_connect_request(sc, &event->param.conn);
if (ret)
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 126/127] smb: server: only use public smbdirect functions
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (124 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 125/127] smb: server: make use of smbdirect_socket_create_accepting()/smbdirect_socket_release() Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 127/127] smb: server: make use of smbdirect.ko Stefan Metzmacher
2025-11-04 10:49 ` [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical; +Cc: metze, Namjae Jeon, Steve French, Tom Talpey
Also remove a lot of unused includes...
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>
---
fs/smb/server/smb2pdu.c | 1 -
fs/smb/server/transport_rdma.c | 25 +++++++++----------------
fs/smb/server/transport_rdma.h | 2 ++
3 files changed, 11 insertions(+), 17 deletions(-)
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index f901ae18e68a..d20c8e5cd18e 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -23,7 +23,6 @@
#include "asn1.h"
#include "connection.h"
#include "transport_ipc.h"
-#include "../common/smbdirect/smbdirect.h"
#include "transport_rdma.h"
#include "vfs.h"
#include "vfs_cache.h"
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 85aed6963c86..e7d54283ae47 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -13,31 +13,16 @@
#include <linux/kthread.h>
#include <linux/list.h>
-#include <linux/mempool.h>
-#include <linux/highmem.h>
-#include <linux/scatterlist.h>
#include <linux/string_choices.h>
#include <linux/errname.h>
-#include <rdma/ib_verbs.h>
-#include <rdma/rdma_cm.h>
-#include <rdma/rw.h>
#include "glob.h"
#include "connection.h"
#include "smb_common.h"
#include "../common/smb2status.h"
-#include "../common/smbdirect/smbdirect.h"
-#include "../common/smbdirect/smbdirect_pdu.h"
-#include "../common/smbdirect/smbdirect_socket.h"
#include "transport_rdma.h"
+#include "../common/smbdirect/smbdirect_public.h"
-/*
- * This is a temporary solution until all code
- * is moved to smbdirect_all_c_files.c and we
- * have an smbdirect.ko that exports the required
- * functions.
- */
-#include "../common/smbdirect/smbdirect_all_c_files.c"
#define SMB_DIRECT_PORT_IWARP 5445
#define SMB_DIRECT_PORT_INFINIBAND 445
@@ -642,3 +627,11 @@ static const struct ksmbd_transport_ops ksmbd_smb_direct_transport_ops = {
.rdma_write = smb_direct_rdma_write,
.free_transport = smb_direct_free_transport,
};
+
+/*
+ * This is a temporary solution until all code
+ * is moved to smbdirect_all_c_files.c and we
+ * have an smbdirect.ko that exports the required
+ * functions.
+ */
+#include "../common/smbdirect/smbdirect_all_c_files.c"
diff --git a/fs/smb/server/transport_rdma.h b/fs/smb/server/transport_rdma.h
index 3f93c6a9f7e4..e16f625caed2 100644
--- a/fs/smb/server/transport_rdma.h
+++ b/fs/smb/server/transport_rdma.h
@@ -27,4 +27,6 @@ static inline void init_smbd_max_io_size(unsigned int sz) { }
static inline unsigned int get_smbd_max_read_write_size(struct ksmbd_transport *kt) { return 0; }
#endif
+#include "../common/smbdirect/smbdirect.h"
+
#endif /* __KSMBD_TRANSPORT_RDMA_H__ */
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* [PATCH v2 127/127] smb: server: make use of smbdirect.ko
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (125 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 126/127] smb: server: only use public smbdirect functions Stefan Metzmacher
@ 2025-10-29 13:21 ` Stefan Metzmacher
2025-11-04 10:49 ` [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
127 siblings, 0 replies; 130+ messages in thread
From: Stefan Metzmacher @ 2025-10-29 13:21 UTC (permalink / raw)
To: linux-cifs, samba-technical; +Cc: metze, Namjae Jeon, Steve French, Tom Talpey
This means we no longer inline the common smbdirect
.c files and use the exported functions from the
module instead.
Note the connection specific logging is still
redirect to ksmbd.ko functions via
smbdirect_socket_set_logging().
We still don't use real socket layer,
but we're very close...
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>
---
fs/smb/server/Kconfig | 4 ++--
fs/smb/server/transport_rdma.c | 10 ----------
2 files changed, 2 insertions(+), 12 deletions(-)
diff --git a/fs/smb/server/Kconfig b/fs/smb/server/Kconfig
index 098cac98d31e..59a059ecabec 100644
--- a/fs/smb/server/Kconfig
+++ b/fs/smb/server/Kconfig
@@ -49,8 +49,8 @@ if SMB_SERVER
config SMB_SERVER_SMBDIRECT
bool "Support for SMB Direct protocol"
- depends on SMB_SERVER=m && INFINIBAND && INFINIBAND_ADDR_TRANS || SMB_SERVER=y && INFINIBAND=y && INFINIBAND_ADDR_TRANS=y
- select SG_POOL
+ depends on SMB_SERVER && INFINIBAND && INFINIBAND_ADDR_TRANS
+ select SMB_COMMON_SMBDIRECT
default n
help
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index e7d54283ae47..c261082ff9c7 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -9,8 +9,6 @@
#define SUBMOD_NAME "smb_direct"
-#define SMBDIRECT_USE_INLINE_C_FILES 1
-
#include <linux/kthread.h>
#include <linux/list.h>
#include <linux/string_choices.h>
@@ -627,11 +625,3 @@ static const struct ksmbd_transport_ops ksmbd_smb_direct_transport_ops = {
.rdma_write = smb_direct_rdma_write,
.free_transport = smb_direct_free_transport,
};
-
-/*
- * This is a temporary solution until all code
- * is moved to smbdirect_all_c_files.c and we
- * have an smbdirect.ko that exports the required
- * functions.
- */
-#include "../common/smbdirect/smbdirect_all_c_files.c"
--
2.43.0
^ permalink raw reply related [flat|nested] 130+ messages in thread
* Re: [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
` (126 preceding siblings ...)
2025-10-29 13:21 ` [PATCH v2 127/127] smb: server: make use of smbdirect.ko Stefan Metzmacher
@ 2025-11-04 10:49 ` Stefan Metzmacher
2025-11-04 14:49 ` Namjae Jeon
127 siblings, 1 reply; 130+ messages in thread
From: Stefan Metzmacher @ 2025-11-04 10:49 UTC (permalink / raw)
To: linux-cifs, samba-technical
Cc: Steve French, Tom Talpey, Long Li, Namjae Jeon, David Howells
Hi,
I already used these debugging features:
CONFIG_KASAN_SHADOW_OFFSET=0xdffffc0000000000
CONFIG_HAVE_ARCH_KASAN=y
CONFIG_HAVE_ARCH_KASAN_VMALLOC=y
CONFIG_CC_HAS_KASAN_GENERIC=y
CONFIG_KASAN=y
CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX=y
CONFIG_KASAN_GENERIC=y
CONFIG_KASAN_INLINE=y
CONFIG_KASAN_STACK=y
CONFIG_KASAN_VMALLOC=y
CONFIG_KASAN_EXTRA_INFO=y
But now I turned on a lot more debugging features:
CONFIG_PRINTK_CALLER=y
CONFIG_STACKTRACE_BUILD_ID=y
CONFIG_DEBUG_INFO_COMPRESSED_ZSTD=y
CONFIG_DEBUG_SECTION_MISMATCH=y
CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0xffffffff
CONFIG_PAGE_EXTENSION=y
CONFIG_PAGE_OWNER=y
CONFIG_PAGE_TABLE_CHECK=y
CONFIG_DEBUG_PAGE_REF=y
CONFIG_PTDUMP_DEBUGFS=y
CONFIG_DEBUG_KMEMLEAK=y
CONFIG_DEBUG_KMEMLEAK_MEM_POOL_SIZE=16000
CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
CONFIG_DEBUG_OBJECTS=y
CONFIG_DEBUG_OBJECTS_FREE=y
CONFIG_DEBUG_OBJECTS_TIMERS=y
CONFIG_DEBUG_OBJECTS_WORK=y
CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=0
CONFIG_WQ_WATCHDOG=y
CONFIG_PROVE_LOCKING=y
CONFIG_PROVE_RAW_LOCK_NESTING=y
CONFIG_LOCK_STAT=y
CONFIG_DEBUG_RT_MUTEXES=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y
CONFIG_DEBUG_RWSEMS=y
CONFIG_DEBUG_LOCK_ALLOC=y
CONFIG_LOCKDEP=y
CONFIG_LOCKDEP_BITS=15
CONFIG_LOCKDEP_CHAINS_BITS=16
CONFIG_LOCKDEP_STACK_TRACE_BITS=19
CONFIG_LOCKDEP_STACK_TRACE_HASH_BITS=14
CONFIG_LOCKDEP_CIRCULAR_QUEUE_BITS=12
CONFIG_DEBUG_ATOMIC_SLEEP=y
CONFIG_TRACE_IRQFLAGS=y
CONFIG_TRACE_IRQFLAGS_NMI=y
CONFIG_DEBUG_IRQFLAGS=y
CONFIG_PROVE_RCU=y
CONFIG_RCU_TRACE=y
CONFIG_RING_BUFFER_ALLOW_SWAP=y
CONFIG_PREEMPTIRQ_TRACEPOINTS=y
CONFIG_TRACE_PREEMPT_TOGGLE=y
CONFIG_IRQSOFF_TRACER=y
CONFIG_PREEMPT_TRACER=y
CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP=y
And that luckily revealed some cases where
I called functions which might sleep in a
ib_post_recv completion function that
is called in a softirq as the client uses
IB_POLL_SOFTIRQ.
I means that I needed to deferr some of the
smbdirect_connect_negotiate_recv_done and
smbdirect_accept_negotiate_recv_done logic
to the workqueue.
And I added some includes to smbdirect_socket.h,
as some sparc cross compile bot was complaining
about a failing build.
I also did a few minor changes like using
sc->ib.dev consistently.
As well as setting sc->first_error as early as possible.
I took the current ksmbd-for-next-next at
commit 2bd117c715790585d69a06bd5f795520fc67ce86
and rebased it on v6.18-rc4 and then removed my patches
and added the modified once on top.
The result can be found in my for-6.19/fs-smb-20251104-v3 branch,
at commit a73e9e7470238121b87b2128da2ed1fff9fd6d4b:
git fetch https://git.samba.org/metze/linux/wip.git for-6.19/fs-smb-20251104-v3
https://git.samba.org/?p=metze/linux/wip.git;a=shortlog;h=refs/heads/for-6.19/fs-smb-20251104-v3
The whole diff between the old and new patchset
follows below:
The new branch should replace ksmbd-for-next-next...
Thanks!
metze
fs/smb/common/smbdirect/smbdirect_accept.c | 154 +++++++++++++++-------
fs/smb/common/smbdirect/smbdirect_connect.c | 171 +++++++++++++++++--------
fs/smb/common/smbdirect/smbdirect_connection.c | 91 +++++++++++--
fs/smb/common/smbdirect/smbdirect_socket.h | 15 +++
4 files changed, 316 insertions(+), 115 deletions(-)
diff --git a/fs/smb/common/smbdirect/smbdirect_accept.c b/fs/smb/common/smbdirect/smbdirect_accept.c
index 0ed3f43a7397..3455e7327663 100644
--- a/fs/smb/common/smbdirect/smbdirect_accept.c
+++ b/fs/smb/common/smbdirect/smbdirect_accept.c
@@ -192,25 +192,14 @@ static int smbdirect_accept_init_params(struct smbdirect_socket *sc)
return 0;
}
+static void smbdirect_accept_negotiate_recv_work(struct work_struct *work);
+
static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc *wc)
{
struct smbdirect_recv_io *recv_io =
container_of(wc->wr_cqe, struct smbdirect_recv_io, cqe);
struct smbdirect_socket *sc = recv_io->socket;
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- struct smbdirect_negotiate_req *nreq;
- u16 min_version;
- u16 max_version;
- u16 credits_requested;
- u32 preferred_send_size;
- u32 max_receive_size;
- u32 max_fragmented_size;
- struct smbdirect_send_io *send_io = NULL;
- struct smbdirect_negotiate_resp *nrep;
- struct ib_send_wr send_wr;
- u32 ntstatus;
- int posted;
- int ret;
+ const struct smbdirect_socket_parameters *sp = &sc->parameters;
if (unlikely(wc->status != IB_WC_SUCCESS || WARN_ON_ONCE(wc->opcode != IB_WC_RECV))) {
if (wc->status != IB_WC_WR_FLUSH_ERR)
@@ -235,18 +224,98 @@ static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
msecs_to_jiffies(sp->keepalive_interval_msec));
- ib_dma_sync_single_for_cpu(wc->qp->device,
+ ib_dma_sync_single_for_cpu(sc->ib.dev,
recv_io->sge.addr,
recv_io->sge.length,
DMA_FROM_DEVICE);
- if (wc->byte_len < sizeof(*nreq)) {
+ if (wc->byte_len < sizeof(struct smbdirect_negotiate_req)) {
smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
"wc->byte_len=%u < %zu\n",
- wc->byte_len, sizeof(*nreq));
+ wc->byte_len, sizeof(struct smbdirect_negotiate_req));
goto error;
}
+ /*
+ * We continue via the workqueue as we may have
+ * complex work that might sleep.
+ *
+ * The work should already/still be disabled,
+ * but smbdirect_connection_put_recv_io() disables
+ * it again.
+ *
+ * Note that smbdirect_connection_put_recv_io()
+ * only moved recv_io into the free list, but
+ * we didn't call smbdirect_connection_recv_io_refill()
+ * yet, so it won't be reused, but the cleanup code
+ * on disconnect is able to find it, disables
+ * recv_io->complex_work again.
+ */
+ smbdirect_connection_put_recv_io(recv_io);
+ INIT_WORK(&recv_io->complex_work, smbdirect_accept_negotiate_recv_work);
+ queue_work(sc->workqueue, &recv_io->complex_work);
+ return;
+
+error:
+ /*
+ * recv_io.posted.refill_work is still disabled,
+ * so smbdirect_connection_put_recv_io() won't
+ * start it.
+ */
+ smbdirect_connection_put_recv_io(recv_io);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+}
+
+static void smbdirect_accept_negotiate_recv_work(struct work_struct *work)
+{
+ struct smbdirect_recv_io *recv_io =
+ container_of(work, struct smbdirect_recv_io, complex_work);
+ struct smbdirect_socket *sc = recv_io->socket;
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+ struct smbdirect_negotiate_req *nreq;
+ u16 min_version;
+ u16 max_version;
+ u16 credits_requested;
+ u32 preferred_send_size;
+ u32 max_receive_size;
+ u32 max_fragmented_size;
+ struct smbdirect_send_io *send_io = NULL;
+ struct smbdirect_negotiate_resp *nrep;
+ struct ib_send_wr send_wr;
+ u32 ntstatus;
+ int posted;
+ int ret;
+
+ /*
+ * make sure we won't start again...
+ */
+ disable_work(work);
+
+ /*
+ * Note recv_io is already part of the free list,
+ * as smbdirect_connect_negotiate_recv_done() called
+ * smbdirect_connection_put_recv_io(), but
+ * it won't be reused before we call
+ * smbdirect_connection_recv_io_refill() below.
+ */
+
+ if (unlikely(sc->first_error))
+ return;
+
+ if (sc->status != SMBDIRECT_SOCKET_NEGOTIATE_RUNNING) {
+ /*
+ * Something went wrong...
+ */
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "status=%s first_error=%1pe local: %pISpsfc remote: %pISpsfc\n",
+ smbdirect_socket_status_string(sc->status),
+ SMBDIRECT_DEBUG_ERR_PTR(sc->first_error),
+ &sc->rdma.cm_id->route.addr.src_addr,
+ &sc->rdma.cm_id->route.addr.dst_addr);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+ return;
+ }
+
nreq = (struct smbdirect_negotiate_req *)recv_io->packet;
min_version = le16_to_cpu(nreq->min_version);
max_version = le16_to_cpu(nreq->max_version);
@@ -281,7 +350,8 @@ static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
if (credits_requested == 0) {
smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
"invalid: credits_requested == 0\n");
- goto error;
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+ return;
}
if (max_receive_size < SMBDIRECT_MIN_RECEIVE_SIZE) {
@@ -289,7 +359,8 @@ static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
"invalid: max_receive_size=%u < %u\n",
max_receive_size,
SMBDIRECT_MIN_RECEIVE_SIZE);
- goto error;
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+ return;
}
if (max_fragmented_size < SMBDIRECT_MIN_FRAGMENTED_SIZE) {
@@ -297,7 +368,8 @@ static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
"invalid: max_fragmented_size=%u < %u\n",
max_fragmented_size,
SMBDIRECT_MIN_FRAGMENTED_SIZE);
- goto error;
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+ return;
}
/*
@@ -327,12 +399,6 @@ static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
*/
sp->max_fragmented_send_size = max_fragmented_size;
- /*
- * Give recv_io back to the recv_io.free.list,
- * so that the refill can also post it.
- */
- smbdirect_connection_put_recv_io(recv_io);
-
/*
* Prepare for receiving data_transfer messages
*/
@@ -350,7 +416,8 @@ static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
"smbdirect_connection_recv_io_refill() failed %1pe\n",
SMBDIRECT_DEBUG_ERR_PTR(posted));
- goto error;
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+ return;
}
/*
@@ -365,11 +432,11 @@ static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
send_io = smbdirect_connection_alloc_send_io(sc);
if (IS_ERR(send_io)) {
ret = PTR_ERR(send_io);
- send_io = NULL;
smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
"smbdirect_connection_alloc_send_io() failed %1pe\n",
SMBDIRECT_DEBUG_ERR_PTR(ret));
- goto error;
+ smbdirect_connection_schedule_disconnect(sc, ret);
+ return;
}
send_io->cqe.done = smbdirect_accept_negotiate_send_done;
@@ -430,7 +497,9 @@ static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
"ib_dma_mapping_error() failed %1pe\n",
SMBDIRECT_DEBUG_ERR_PTR(ret));
- goto error;
+ smbdirect_connection_free_send_io(send_io);
+ smbdirect_connection_schedule_disconnect(sc, ret);
+ return;
}
send_io->sge[0].length = sizeof(*nrep);
@@ -455,30 +524,19 @@ static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
smbdirect_log_rdma_send(sc, SMBDIRECT_LOG_ERR,
"smbdirect_connection_post_send_wr() failed %1pe\n",
SMBDIRECT_DEBUG_ERR_PTR(ret));
- goto error;
+ /*
+ * Note smbdirect_connection_free_send_io()
+ * does ib_dma_unmap_page()
+ */
+ smbdirect_connection_free_send_io(send_io);
+ smbdirect_connection_schedule_disconnect(sc, ret);
+ return;
}
/*
* smbdirect_accept_negotiate_send_done
* will do all remaining work...
*/
- return;
-
-error:
- /*
- * recv_io.posted.refill_work is still disabled,
- * so smbdirect_connection_put_recv_io() won't
- * start it.
- */
- if (recv_io)
- smbdirect_connection_put_recv_io(recv_io);
- /*
- * Note smbdirect_connection_free_send_io()
- * does ib_dma_unmap_page()
- */
- if (send_io)
- smbdirect_connection_free_send_io(send_io);
- smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
}
static void smbdirect_accept_negotiate_send_done(struct ib_cq *cq, struct ib_wc *wc)
diff --git a/fs/smb/common/smbdirect/smbdirect_connect.c b/fs/smb/common/smbdirect/smbdirect_connect.c
index eb8e903c9fce..b9544a6ef59b 100644
--- a/fs/smb/common/smbdirect/smbdirect_connect.c
+++ b/fs/smb/common/smbdirect/smbdirect_connect.c
@@ -536,23 +536,14 @@ static void smbdirect_connect_negotiate_send_done(struct ib_cq *cq, struct ib_wc
}
}
+static void smbdirect_connect_negotiate_recv_work(struct work_struct *work);
+
static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc *wc)
{
struct smbdirect_recv_io *recv_io =
container_of(wc->wr_cqe, struct smbdirect_recv_io, cqe);
struct smbdirect_socket *sc = recv_io->socket;
- struct smbdirect_socket_parameters *sp = &sc->parameters;
- struct smbdirect_negotiate_resp *nrep;
- u16 negotiated_version;
- u16 credits_requested;
- u16 credits_granted;
- u32 status;
- u32 max_readwrite_size;
- u32 preferred_send_size;
- u32 max_receive_size;
- u32 max_fragmented_size;
- int posted;
- int ret;
+ const struct smbdirect_socket_parameters *sp = &sc->parameters;
if (unlikely(wc->status != IB_WC_SUCCESS || WARN_ON_ONCE(wc->opcode != IB_WC_RECV))) {
if (wc->status != IB_WC_WR_FLUSH_ERR)
@@ -574,18 +565,96 @@ static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
msecs_to_jiffies(sp->keepalive_interval_msec));
- ib_dma_sync_single_for_cpu(wc->qp->device,
+ ib_dma_sync_single_for_cpu(sc->ib.dev,
recv_io->sge.addr,
recv_io->sge.length,
DMA_FROM_DEVICE);
- if (wc->byte_len < sizeof(*nrep)) {
+ if (wc->byte_len < sizeof(struct smbdirect_negotiate_resp)) {
smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
"wc->byte_len=%u < %zu\n",
- wc->byte_len, sizeof(*nrep));
+ wc->byte_len, sizeof(struct smbdirect_negotiate_resp));
goto error;
}
+ /*
+ * We continue via the workqueue as we may have
+ * complex work that might sleep.
+ *
+ * The work should already/still be disabled,
+ * but smbdirect_connection_put_recv_io() disables
+ * it again.
+ *
+ * Note that smbdirect_connection_put_recv_io()
+ * only moved recv_io into the free list, but
+ * we didn't call smbdirect_connection_recv_io_refill()
+ * yet, so it won't be reused, but the cleanup code
+ * on disconnect is able to find it, disables
+ * recv_io->complex_work again.
+ */
+ smbdirect_connection_put_recv_io(recv_io);
+ INIT_WORK(&recv_io->complex_work, smbdirect_connect_negotiate_recv_work);
+ queue_work(sc->workqueue, &recv_io->complex_work);
+ return;
+
+error:
+ /*
+ * recv_io.posted.refill_work is still disabled,
+ * so smbdirect_connection_put_recv_io() won't
+ * start it.
+ */
+ smbdirect_connection_put_recv_io(recv_io);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+}
+
+static void smbdirect_connect_negotiate_recv_work(struct work_struct *work)
+{
+ struct smbdirect_recv_io *recv_io =
+ container_of(work, struct smbdirect_recv_io, complex_work);
+ struct smbdirect_socket *sc = recv_io->socket;
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+ struct smbdirect_negotiate_resp *nrep;
+ u16 negotiated_version;
+ u16 credits_requested;
+ u16 credits_granted;
+ u32 status;
+ u32 max_readwrite_size;
+ u32 preferred_send_size;
+ u32 max_receive_size;
+ u32 max_fragmented_size;
+ int posted;
+ int ret;
+
+ /*
+ * make sure we won't start again...
+ */
+ disable_work(work);
+
+ /*
+ * Note recv_io is already part of the free list,
+ * as smbdirect_connect_negotiate_recv_done() called
+ * smbdirect_connection_put_recv_io(), but
+ * it won't be reused before we call
+ * smbdirect_connection_recv_io_refill() below.
+ */
+
+ if (unlikely(sc->first_error))
+ return;
+
+ if (sc->status != SMBDIRECT_SOCKET_NEGOTIATE_RUNNING) {
+ /*
+ * Something went wrong...
+ */
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "status=%s first_error=%1pe local: %pISpsfc remote: %pISpsfc\n",
+ smbdirect_socket_status_string(sc->status),
+ SMBDIRECT_DEBUG_ERR_PTR(sc->first_error),
+ &sc->rdma.cm_id->route.addr.src_addr,
+ &sc->rdma.cm_id->route.addr.dst_addr);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+ return;
+ }
+
nrep = (struct smbdirect_negotiate_resp *)recv_io->packet;
negotiated_version = le16_to_cpu(nrep->negotiated_version);
credits_requested = le16_to_cpu(nrep->credits_requested);
@@ -623,7 +692,16 @@ static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
"invalid: negotiated_version=0x%x\n",
negotiated_version);
- goto error;
+ smbdirect_connection_schedule_disconnect(sc, -ECONNREFUSED);
+ return;
+ }
+
+ if (status != 0) {
+ smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
+ "invalid: status=0x%x != 0x0\n",
+ status);
+ smbdirect_connection_schedule_disconnect(sc, -ECONNREFUSED);
+ return;
}
if (max_receive_size < SMBDIRECT_MIN_RECEIVE_SIZE) {
@@ -631,7 +709,8 @@ static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
"invalid: max_receive_size=%u < %u\n",
max_receive_size,
SMBDIRECT_MIN_RECEIVE_SIZE);
- goto error;
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+ return;
}
if (max_fragmented_size < SMBDIRECT_MIN_FRAGMENTED_SIZE) {
@@ -639,19 +718,22 @@ static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
"invalid: max_fragmented_size=%u < %u\n",
max_fragmented_size,
SMBDIRECT_MIN_FRAGMENTED_SIZE);
- goto error;
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+ return;
}
if (credits_granted == 0) {
smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
"invalid: credits_granted == 0\n");
- goto error;
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+ return;
}
if (credits_requested == 0) {
smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
"invalid: credits_requested == 0\n");
- goto error;
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+ return;
}
if (preferred_send_size > sp->max_recv_size) {
@@ -659,14 +741,8 @@ static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
"invalid: preferred_send_size=%u < max_recv_size=%u\n",
preferred_send_size,
sp->max_recv_size);
- goto error;
- }
-
- if (status != 0) {
- smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
- "invalid: status=0x%x != 0x0\n",
- status);
- goto error;
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+ return;
}
/*
@@ -701,7 +777,8 @@ static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
"invalid: max_readwrite_size=%u < PAGE_SIZE(%lu)\n",
max_readwrite_size,
PAGE_SIZE);
- goto error;
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+ return;
}
sp->max_frmr_depth = sp->max_read_write_size / PAGE_SIZE;
@@ -716,11 +793,14 @@ static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
*/
sp->max_fragmented_send_size = max_fragmented_size;
- /*
- * Give recv_io back to the recv_io.free.list,
- * so that the refill can also post it.
- */
- smbdirect_connection_put_recv_io(recv_io);
+ ret = smbdirect_connection_create_mr_list(sc);
+ if (ret) {
+ smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
+ "smbdirect_connection_create_mr_list() failed %1pe\n",
+ SMBDIRECT_DEBUG_ERR_PTR(ret));
+ smbdirect_connection_schedule_disconnect(sc, ret);
+ return;
+ }
/*
* Prepare for receiving data_transfer messages
@@ -731,14 +811,6 @@ static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
recv_io->cqe.done = smbdirect_connection_recv_io_done;
recv_io = NULL;
- ret = smbdirect_connection_create_mr_list(sc);
- if (ret) {
- smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
- "smbdirect_connection_create_mr_list() failed %1pe\n",
- SMBDIRECT_DEBUG_ERR_PTR(ret));
- goto error;
- }
-
/*
* We should at least post 1 smbdirect_recv_io!
*/
@@ -747,7 +819,8 @@ static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
"smbdirect_connection_recv_io_refill() failed %1pe\n",
SMBDIRECT_DEBUG_ERR_PTR(ret));
- goto error;
+ smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
+ return;
}
/*
@@ -756,18 +829,6 @@ static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
* the waiter.
*/
smbdirect_connection_negotiation_done(sc);
-
- return;
-
-error:
- /*
- * recv_io.posted.refill_work is still disabled,
- * so smbdirect_connection_put_recv_io() won't
- * start it.
- */
- if (recv_io)
- smbdirect_connection_put_recv_io(recv_io);
- smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
}
__SMBDIRECT_PUBLIC__
diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
index ae9626888b5c..cc22e8b2f4d3 100644
--- a/fs/smb/common/smbdirect/smbdirect_connection.c
+++ b/fs/smb/common/smbdirect/smbdirect_connection.c
@@ -742,6 +742,8 @@ int smbdirect_connection_create_mem_pools(struct smbdirect_socket *sc)
goto err;
recv_io->socket = sc;
recv_io->sge.length = 0;
+ INIT_WORK(&recv_io->complex_work, __smbdirect_socket_disabled_work);
+ disable_work_sync(&recv_io->complex_work);
list_add_tail(&recv_io->list, &sc->recv_io.free.list);
}
@@ -757,6 +759,10 @@ void smbdirect_connection_destroy_mem_pools(struct smbdirect_socket *sc)
struct smbdirect_recv_io *recv_io, *next_io;
list_for_each_entry_safe(recv_io, next_io, &sc->recv_io.free.list, list) {
+ /*
+ * The work should already be disabled
+ */
+ disable_work_sync(&recv_io->complex_work);
list_del(&recv_io->list);
mempool_free(recv_io, sc->recv_io.mem.pool);
}
@@ -833,9 +839,10 @@ struct smbdirect_recv_io *smbdirect_connection_get_recv_io(struct smbdirect_sock
unsigned long flags;
spin_lock_irqsave(&sc->recv_io.free.lock, flags);
- msg = list_first_entry_or_null(&sc->recv_io.free.list,
- struct smbdirect_recv_io,
- list);
+ if (likely(!sc->first_error))
+ msg = list_first_entry_or_null(&sc->recv_io.free.list,
+ struct smbdirect_recv_io,
+ list);
if (likely(msg)) {
list_del(&msg->list);
sc->statistics.get_receive_buffer++;
@@ -851,6 +858,11 @@ void smbdirect_connection_put_recv_io(struct smbdirect_recv_io *msg)
struct smbdirect_socket *sc = msg->socket;
unsigned long flags;
+ /*
+ * Should already be disabled anyway.
+ */
+ disable_work(&msg->complex_work);
+
if (likely(msg->sge.length != 0)) {
ib_dma_unmap_single(sc->ib.dev,
msg->sge.addr,
@@ -874,6 +886,11 @@ static void smbdirect_connection_reassembly_append_recv_io(struct smbdirect_sock
{
unsigned long flags;
+ /*
+ * The work should already/still be disabled
+ */
+ disable_work(&msg->complex_work);
+
spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags);
list_add_tail(&msg->list, &sc->recv_io.reassembly.list);
sc->recv_io.reassembly.queue_length++;
@@ -968,6 +985,14 @@ __SMBDIRECT_PRIVATE__
void smbdirect_connection_schedule_disconnect(struct smbdirect_socket *sc,
int error)
{
+ struct smbdirect_recv_io *recv_io, *recv_tmp;
+ unsigned long flags;
+
+ if (sc->first_error == 0)
+ sc->first_error = error;
+ if (sc->first_error == 0)
+ sc->first_error = -ECONNABORTED;
+
/*
* make sure other work (than disconnect_work)
* is not queued again but here we don't block and avoid
@@ -979,10 +1004,19 @@ void smbdirect_connection_schedule_disconnect(struct smbdirect_socket *sc,
sc->idle.keepalive = SMBDIRECT_KEEPALIVE_NONE;
disable_delayed_work(&sc->idle.timer_work);
- if (sc->first_error == 0)
- sc->first_error = error;
- if (sc->first_error == 0)
- sc->first_error = -ECONNABORTED;
+ /*
+ * If any complex work was scheduled we
+ * should disable it (only happens during
+ * negotiation)...
+ *
+ * Note that sc->first_error is set before,
+ * so any future smbdirect_connection_get_recv_io()
+ * will see it and return NULL.
+ */
+ spin_lock_irqsave(&sc->recv_io.free.lock, flags);
+ list_for_each_entry_safe(recv_io, recv_tmp, &sc->recv_io.free.list, list)
+ disable_work(&recv_io->complex_work);
+ spin_unlock_irqrestore(&sc->recv_io.free.lock, flags);
switch (sc->status) {
case SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED:
@@ -1037,12 +1071,17 @@ static void smbdirect_connection_disconnect_work(struct work_struct *work)
{
struct smbdirect_socket *sc =
container_of(work, struct smbdirect_socket, disconnect_work);
+ struct smbdirect_recv_io *recv_io, *recv_tmp;
+ unsigned long flags;
/*
* This should not never be called in an interrupt!
*/
WARN_ON_ONCE(in_interrupt());
+ if (sc->first_error == 0)
+ sc->first_error = -ECONNABORTED;
+
/*
* make sure this and other work is not queued again
* but here we don't block and avoid
@@ -1055,8 +1094,19 @@ static void smbdirect_connection_disconnect_work(struct work_struct *work)
sc->idle.keepalive = SMBDIRECT_KEEPALIVE_NONE;
disable_delayed_work(&sc->idle.timer_work);
- if (sc->first_error == 0)
- sc->first_error = -ECONNABORTED;
+ /*
+ * If any complex work was scheduled we
+ * should disable it (only happens during
+ * negotiation)...
+ *
+ * Note that sc->first_error is set before,
+ * so any future smbdirect_connection_get_recv_io()
+ * will see it and return NULL.
+ */
+ spin_lock_irqsave(&sc->recv_io.free.lock, flags);
+ list_for_each_entry_safe(recv_io, recv_tmp, &sc->recv_io.free.list, list)
+ disable_work(&recv_io->complex_work);
+ spin_unlock_irqrestore(&sc->recv_io.free.lock, flags);
switch (sc->status) {
case SMBDIRECT_SOCKET_NEGOTIATE_NEEDED:
@@ -1216,6 +1266,24 @@ static void smbdirect_connection_destroy(struct smbdirect_socket *sc)
disable_work_sync(&sc->idle.immediate_work);
disable_delayed_work_sync(&sc->idle.timer_work);
+ /*
+ * If any complex work was scheduled we
+ * should disable it (only happens during
+ * negotiation)...
+ *
+ * Note was already set in sc->first_error in
+ * smbdirect_connection_schedule_disconnect() or
+ * smbdirect_connection_disconnect_work(), both
+ * before time before:
+ * spin_lock_irqsave(&sc->recv_io.free.lock, flags),
+ * so any future smbdirect_connection_get_recv_io()
+ * will see it and return NULL. And we don't
+ * need to get the lock here again, while
+ * trying disable_work_sync().
+ */
+ list_for_each_entry_safe(recv_io, recv_tmp, &sc->recv_io.free.list, list)
+ disable_work_sync(&recv_io->complex_work);
+
if (sc->rdma.cm_id)
rdma_lock_handler(sc->rdma.cm_id);
@@ -1231,9 +1299,8 @@ static void smbdirect_connection_destroy(struct smbdirect_socket *sc)
spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags);
list_splice_tail_init(&sc->recv_io.reassembly.list, &all_list);
spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags);
- list_for_each_entry_safe(recv_io, recv_tmp, &all_list, list) {
+ list_for_each_entry_safe(recv_io, recv_tmp, &all_list, list)
smbdirect_connection_put_recv_io(recv_io);
- }
sc->recv_io.reassembly.data_length = 0;
smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
@@ -2002,7 +2069,7 @@ void smbdirect_connection_recv_io_done(struct ib_cq *cq, struct ib_wc *wc)
mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
msecs_to_jiffies(sp->keepalive_interval_msec));
- ib_dma_sync_single_for_cpu(wc->qp->device,
+ ib_dma_sync_single_for_cpu(sc->ib.dev,
recv_io->sge.addr,
recv_io->sge.length,
DMA_FROM_DEVICE);
diff --git a/fs/smb/common/smbdirect/smbdirect_socket.h b/fs/smb/common/smbdirect/smbdirect_socket.h
index 65f25fc4b4a7..ef151ff1c02a 100644
--- a/fs/smb/common/smbdirect/smbdirect_socket.h
+++ b/fs/smb/common/smbdirect/smbdirect_socket.h
@@ -6,6 +6,13 @@
#ifndef __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_SOCKET_H__
#define __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_SOCKET_H__
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+#include <linux/kref.h>
+#include <linux/mempool.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
#include <rdma/rw.h>
enum smbdirect_socket_status {
@@ -617,6 +624,14 @@ struct smbdirect_recv_io {
#define SMBDIRECT_RECV_IO_MAX_SGE 1
struct ib_sge sge;
+ /*
+ * We may need to handle complex
+ * work that might sleep and are
+ * not allowed to run in an interrupt
+ * context.
+ */
+ struct work_struct complex_work;
+
/* Link to free or reassembly list */
struct list_head list;
^ permalink raw reply related [flat|nested] 130+ messages in thread
* Re: [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko
2025-11-04 10:49 ` [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
@ 2025-11-04 14:49 ` Namjae Jeon
0 siblings, 0 replies; 130+ messages in thread
From: Namjae Jeon @ 2025-11-04 14:49 UTC (permalink / raw)
To: Stefan Metzmacher
Cc: linux-cifs, samba-technical, Steve French, Tom Talpey, Long Li,
David Howells
On Tue, Nov 4, 2025 at 7:49 PM Stefan Metzmacher <metze@samba.org> wrote:
>
> Hi,
>
> I already used these debugging features:
>
> CONFIG_KASAN_SHADOW_OFFSET=0xdffffc0000000000
> CONFIG_HAVE_ARCH_KASAN=y
> CONFIG_HAVE_ARCH_KASAN_VMALLOC=y
> CONFIG_CC_HAS_KASAN_GENERIC=y
> CONFIG_KASAN=y
> CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX=y
> CONFIG_KASAN_GENERIC=y
> CONFIG_KASAN_INLINE=y
> CONFIG_KASAN_STACK=y
> CONFIG_KASAN_VMALLOC=y
> CONFIG_KASAN_EXTRA_INFO=y
>
> But now I turned on a lot more debugging features:
>
> CONFIG_PRINTK_CALLER=y
> CONFIG_STACKTRACE_BUILD_ID=y
> CONFIG_DEBUG_INFO_COMPRESSED_ZSTD=y
> CONFIG_DEBUG_SECTION_MISMATCH=y
> CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0xffffffff
> CONFIG_PAGE_EXTENSION=y
> CONFIG_PAGE_OWNER=y
> CONFIG_PAGE_TABLE_CHECK=y
> CONFIG_DEBUG_PAGE_REF=y
> CONFIG_PTDUMP_DEBUGFS=y
> CONFIG_DEBUG_KMEMLEAK=y
> CONFIG_DEBUG_KMEMLEAK_MEM_POOL_SIZE=16000
> CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
> CONFIG_DEBUG_OBJECTS=y
> CONFIG_DEBUG_OBJECTS_FREE=y
> CONFIG_DEBUG_OBJECTS_TIMERS=y
> CONFIG_DEBUG_OBJECTS_WORK=y
> CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
> CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
> CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=0
> CONFIG_WQ_WATCHDOG=y
> CONFIG_PROVE_LOCKING=y
> CONFIG_PROVE_RAW_LOCK_NESTING=y
> CONFIG_LOCK_STAT=y
> CONFIG_DEBUG_RT_MUTEXES=y
> CONFIG_DEBUG_SPINLOCK=y
> CONFIG_DEBUG_MUTEXES=y
> CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y
> CONFIG_DEBUG_RWSEMS=y
> CONFIG_DEBUG_LOCK_ALLOC=y
> CONFIG_LOCKDEP=y
> CONFIG_LOCKDEP_BITS=15
> CONFIG_LOCKDEP_CHAINS_BITS=16
> CONFIG_LOCKDEP_STACK_TRACE_BITS=19
> CONFIG_LOCKDEP_STACK_TRACE_HASH_BITS=14
> CONFIG_LOCKDEP_CIRCULAR_QUEUE_BITS=12
> CONFIG_DEBUG_ATOMIC_SLEEP=y
> CONFIG_TRACE_IRQFLAGS=y
> CONFIG_TRACE_IRQFLAGS_NMI=y
> CONFIG_DEBUG_IRQFLAGS=y
> CONFIG_PROVE_RCU=y
> CONFIG_RCU_TRACE=y
> CONFIG_RING_BUFFER_ALLOW_SWAP=y
> CONFIG_PREEMPTIRQ_TRACEPOINTS=y
> CONFIG_TRACE_PREEMPT_TOGGLE=y
> CONFIG_IRQSOFF_TRACER=y
> CONFIG_PREEMPT_TRACER=y
> CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP=y
>
> And that luckily revealed some cases where
> I called functions which might sleep in a
> ib_post_recv completion function that
> is called in a softirq as the client uses
> IB_POLL_SOFTIRQ.
>
> I means that I needed to deferr some of the
> smbdirect_connect_negotiate_recv_done and
> smbdirect_accept_negotiate_recv_done logic
> to the workqueue.
>
> And I added some includes to smbdirect_socket.h,
> as some sparc cross compile bot was complaining
> about a failing build.
>
> I also did a few minor changes like using
> sc->ib.dev consistently.
>
> As well as setting sc->first_error as early as possible.
>
> I took the current ksmbd-for-next-next at
> commit 2bd117c715790585d69a06bd5f795520fc67ce86
> and rebased it on v6.18-rc4 and then removed my patches
> and added the modified once on top.
>
> The result can be found in my for-6.19/fs-smb-20251104-v3 branch,
> at commit a73e9e7470238121b87b2128da2ed1fff9fd6d4b:
> git fetch https://git.samba.org/metze/linux/wip.git for-6.19/fs-smb-20251104-v3
> https://git.samba.org/?p=metze/linux/wip.git;a=shortlog;h=refs/heads/for-6.19/fs-smb-20251104-v3
>
> The whole diff between the old and new patchset
> follows below:
>
> The new branch should replace ksmbd-for-next-next...
I will replace them with new ones.
Thanks!
>
> Thanks!
> metze
>
> fs/smb/common/smbdirect/smbdirect_accept.c | 154 +++++++++++++++-------
> fs/smb/common/smbdirect/smbdirect_connect.c | 171 +++++++++++++++++--------
> fs/smb/common/smbdirect/smbdirect_connection.c | 91 +++++++++++--
> fs/smb/common/smbdirect/smbdirect_socket.h | 15 +++
> 4 files changed, 316 insertions(+), 115 deletions(-)
>
> diff --git a/fs/smb/common/smbdirect/smbdirect_accept.c b/fs/smb/common/smbdirect/smbdirect_accept.c
> index 0ed3f43a7397..3455e7327663 100644
> --- a/fs/smb/common/smbdirect/smbdirect_accept.c
> +++ b/fs/smb/common/smbdirect/smbdirect_accept.c
> @@ -192,25 +192,14 @@ static int smbdirect_accept_init_params(struct smbdirect_socket *sc)
> return 0;
> }
>
> +static void smbdirect_accept_negotiate_recv_work(struct work_struct *work);
> +
> static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc *wc)
> {
> struct smbdirect_recv_io *recv_io =
> container_of(wc->wr_cqe, struct smbdirect_recv_io, cqe);
> struct smbdirect_socket *sc = recv_io->socket;
> - struct smbdirect_socket_parameters *sp = &sc->parameters;
> - struct smbdirect_negotiate_req *nreq;
> - u16 min_version;
> - u16 max_version;
> - u16 credits_requested;
> - u32 preferred_send_size;
> - u32 max_receive_size;
> - u32 max_fragmented_size;
> - struct smbdirect_send_io *send_io = NULL;
> - struct smbdirect_negotiate_resp *nrep;
> - struct ib_send_wr send_wr;
> - u32 ntstatus;
> - int posted;
> - int ret;
> + const struct smbdirect_socket_parameters *sp = &sc->parameters;
>
> if (unlikely(wc->status != IB_WC_SUCCESS || WARN_ON_ONCE(wc->opcode != IB_WC_RECV))) {
> if (wc->status != IB_WC_WR_FLUSH_ERR)
> @@ -235,18 +224,98 @@ static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
> mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
> msecs_to_jiffies(sp->keepalive_interval_msec));
>
> - ib_dma_sync_single_for_cpu(wc->qp->device,
> + ib_dma_sync_single_for_cpu(sc->ib.dev,
> recv_io->sge.addr,
> recv_io->sge.length,
> DMA_FROM_DEVICE);
>
> - if (wc->byte_len < sizeof(*nreq)) {
> + if (wc->byte_len < sizeof(struct smbdirect_negotiate_req)) {
> smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
> "wc->byte_len=%u < %zu\n",
> - wc->byte_len, sizeof(*nreq));
> + wc->byte_len, sizeof(struct smbdirect_negotiate_req));
> goto error;
> }
>
> + /*
> + * We continue via the workqueue as we may have
> + * complex work that might sleep.
> + *
> + * The work should already/still be disabled,
> + * but smbdirect_connection_put_recv_io() disables
> + * it again.
> + *
> + * Note that smbdirect_connection_put_recv_io()
> + * only moved recv_io into the free list, but
> + * we didn't call smbdirect_connection_recv_io_refill()
> + * yet, so it won't be reused, but the cleanup code
> + * on disconnect is able to find it, disables
> + * recv_io->complex_work again.
> + */
> + smbdirect_connection_put_recv_io(recv_io);
> + INIT_WORK(&recv_io->complex_work, smbdirect_accept_negotiate_recv_work);
> + queue_work(sc->workqueue, &recv_io->complex_work);
> + return;
> +
> +error:
> + /*
> + * recv_io.posted.refill_work is still disabled,
> + * so smbdirect_connection_put_recv_io() won't
> + * start it.
> + */
> + smbdirect_connection_put_recv_io(recv_io);
> + smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
> +}
> +
> +static void smbdirect_accept_negotiate_recv_work(struct work_struct *work)
> +{
> + struct smbdirect_recv_io *recv_io =
> + container_of(work, struct smbdirect_recv_io, complex_work);
> + struct smbdirect_socket *sc = recv_io->socket;
> + struct smbdirect_socket_parameters *sp = &sc->parameters;
> + struct smbdirect_negotiate_req *nreq;
> + u16 min_version;
> + u16 max_version;
> + u16 credits_requested;
> + u32 preferred_send_size;
> + u32 max_receive_size;
> + u32 max_fragmented_size;
> + struct smbdirect_send_io *send_io = NULL;
> + struct smbdirect_negotiate_resp *nrep;
> + struct ib_send_wr send_wr;
> + u32 ntstatus;
> + int posted;
> + int ret;
> +
> + /*
> + * make sure we won't start again...
> + */
> + disable_work(work);
> +
> + /*
> + * Note recv_io is already part of the free list,
> + * as smbdirect_connect_negotiate_recv_done() called
> + * smbdirect_connection_put_recv_io(), but
> + * it won't be reused before we call
> + * smbdirect_connection_recv_io_refill() below.
> + */
> +
> + if (unlikely(sc->first_error))
> + return;
> +
> + if (sc->status != SMBDIRECT_SOCKET_NEGOTIATE_RUNNING) {
> + /*
> + * Something went wrong...
> + */
> + smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
> + "status=%s first_error=%1pe local: %pISpsfc remote: %pISpsfc\n",
> + smbdirect_socket_status_string(sc->status),
> + SMBDIRECT_DEBUG_ERR_PTR(sc->first_error),
> + &sc->rdma.cm_id->route.addr.src_addr,
> + &sc->rdma.cm_id->route.addr.dst_addr);
> + smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
> + return;
> + }
> +
> nreq = (struct smbdirect_negotiate_req *)recv_io->packet;
> min_version = le16_to_cpu(nreq->min_version);
> max_version = le16_to_cpu(nreq->max_version);
> @@ -281,7 +350,8 @@ static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
> if (credits_requested == 0) {
> smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
> "invalid: credits_requested == 0\n");
> - goto error;
> + smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
> + return;
> }
>
> if (max_receive_size < SMBDIRECT_MIN_RECEIVE_SIZE) {
> @@ -289,7 +359,8 @@ static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
> "invalid: max_receive_size=%u < %u\n",
> max_receive_size,
> SMBDIRECT_MIN_RECEIVE_SIZE);
> - goto error;
> + smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
> + return;
> }
>
> if (max_fragmented_size < SMBDIRECT_MIN_FRAGMENTED_SIZE) {
> @@ -297,7 +368,8 @@ static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
> "invalid: max_fragmented_size=%u < %u\n",
> max_fragmented_size,
> SMBDIRECT_MIN_FRAGMENTED_SIZE);
> - goto error;
> + smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
> + return;
> }
>
> /*
> @@ -327,12 +399,6 @@ static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
> */
> sp->max_fragmented_send_size = max_fragmented_size;
>
> - /*
> - * Give recv_io back to the recv_io.free.list,
> - * so that the refill can also post it.
> - */
> - smbdirect_connection_put_recv_io(recv_io);
> -
> /*
> * Prepare for receiving data_transfer messages
> */
> @@ -350,7 +416,8 @@ static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
> smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
> "smbdirect_connection_recv_io_refill() failed %1pe\n",
> SMBDIRECT_DEBUG_ERR_PTR(posted));
> - goto error;
> + smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
> + return;
> }
>
> /*
> @@ -365,11 +432,11 @@ static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
> send_io = smbdirect_connection_alloc_send_io(sc);
> if (IS_ERR(send_io)) {
> ret = PTR_ERR(send_io);
> - send_io = NULL;
> smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
> "smbdirect_connection_alloc_send_io() failed %1pe\n",
> SMBDIRECT_DEBUG_ERR_PTR(ret));
> - goto error;
> + smbdirect_connection_schedule_disconnect(sc, ret);
> + return;
> }
> send_io->cqe.done = smbdirect_accept_negotiate_send_done;
>
> @@ -430,7 +497,9 @@ static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
> smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
> "ib_dma_mapping_error() failed %1pe\n",
> SMBDIRECT_DEBUG_ERR_PTR(ret));
> - goto error;
> + smbdirect_connection_free_send_io(send_io);
> + smbdirect_connection_schedule_disconnect(sc, ret);
> + return;
> }
>
> send_io->sge[0].length = sizeof(*nrep);
> @@ -455,30 +524,19 @@ static void smbdirect_accept_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
> smbdirect_log_rdma_send(sc, SMBDIRECT_LOG_ERR,
> "smbdirect_connection_post_send_wr() failed %1pe\n",
> SMBDIRECT_DEBUG_ERR_PTR(ret));
> - goto error;
> + /*
> + * Note smbdirect_connection_free_send_io()
> + * does ib_dma_unmap_page()
> + */
> + smbdirect_connection_free_send_io(send_io);
> + smbdirect_connection_schedule_disconnect(sc, ret);
> + return;
> }
>
> /*
> * smbdirect_accept_negotiate_send_done
> * will do all remaining work...
> */
> - return;
> -
> -error:
> - /*
> - * recv_io.posted.refill_work is still disabled,
> - * so smbdirect_connection_put_recv_io() won't
> - * start it.
> - */
> - if (recv_io)
> - smbdirect_connection_put_recv_io(recv_io);
> - /*
> - * Note smbdirect_connection_free_send_io()
> - * does ib_dma_unmap_page()
> - */
> - if (send_io)
> - smbdirect_connection_free_send_io(send_io);
> - smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
> }
>
> static void smbdirect_accept_negotiate_send_done(struct ib_cq *cq, struct ib_wc *wc)
> diff --git a/fs/smb/common/smbdirect/smbdirect_connect.c b/fs/smb/common/smbdirect/smbdirect_connect.c
> index eb8e903c9fce..b9544a6ef59b 100644
> --- a/fs/smb/common/smbdirect/smbdirect_connect.c
> +++ b/fs/smb/common/smbdirect/smbdirect_connect.c
> @@ -536,23 +536,14 @@ static void smbdirect_connect_negotiate_send_done(struct ib_cq *cq, struct ib_wc
> }
> }
>
> +static void smbdirect_connect_negotiate_recv_work(struct work_struct *work);
> +
> static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc *wc)
> {
> struct smbdirect_recv_io *recv_io =
> container_of(wc->wr_cqe, struct smbdirect_recv_io, cqe);
> struct smbdirect_socket *sc = recv_io->socket;
> - struct smbdirect_socket_parameters *sp = &sc->parameters;
> - struct smbdirect_negotiate_resp *nrep;
> - u16 negotiated_version;
> - u16 credits_requested;
> - u16 credits_granted;
> - u32 status;
> - u32 max_readwrite_size;
> - u32 preferred_send_size;
> - u32 max_receive_size;
> - u32 max_fragmented_size;
> - int posted;
> - int ret;
> + const struct smbdirect_socket_parameters *sp = &sc->parameters;
>
> if (unlikely(wc->status != IB_WC_SUCCESS || WARN_ON_ONCE(wc->opcode != IB_WC_RECV))) {
> if (wc->status != IB_WC_WR_FLUSH_ERR)
> @@ -574,18 +565,96 @@ static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
> mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
> msecs_to_jiffies(sp->keepalive_interval_msec));
>
> - ib_dma_sync_single_for_cpu(wc->qp->device,
> + ib_dma_sync_single_for_cpu(sc->ib.dev,
> recv_io->sge.addr,
> recv_io->sge.length,
> DMA_FROM_DEVICE);
>
> - if (wc->byte_len < sizeof(*nrep)) {
> + if (wc->byte_len < sizeof(struct smbdirect_negotiate_resp)) {
> smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
> "wc->byte_len=%u < %zu\n",
> - wc->byte_len, sizeof(*nrep));
> + wc->byte_len, sizeof(struct smbdirect_negotiate_resp));
> goto error;
> }
>
> + /*
> + * We continue via the workqueue as we may have
> + * complex work that might sleep.
> + *
> + * The work should already/still be disabled,
> + * but smbdirect_connection_put_recv_io() disables
> + * it again.
> + *
> + * Note that smbdirect_connection_put_recv_io()
> + * only moved recv_io into the free list, but
> + * we didn't call smbdirect_connection_recv_io_refill()
> + * yet, so it won't be reused, but the cleanup code
> + * on disconnect is able to find it, disables
> + * recv_io->complex_work again.
> + */
> + smbdirect_connection_put_recv_io(recv_io);
> + INIT_WORK(&recv_io->complex_work, smbdirect_connect_negotiate_recv_work);
> + queue_work(sc->workqueue, &recv_io->complex_work);
> + return;
> +
> +error:
> + /*
> + * recv_io.posted.refill_work is still disabled,
> + * so smbdirect_connection_put_recv_io() won't
> + * start it.
> + */
> + smbdirect_connection_put_recv_io(recv_io);
> + smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
> +}
> +
> +static void smbdirect_connect_negotiate_recv_work(struct work_struct *work)
> +{
> + struct smbdirect_recv_io *recv_io =
> + container_of(work, struct smbdirect_recv_io, complex_work);
> + struct smbdirect_socket *sc = recv_io->socket;
> + struct smbdirect_socket_parameters *sp = &sc->parameters;
> + struct smbdirect_negotiate_resp *nrep;
> + u16 negotiated_version;
> + u16 credits_requested;
> + u16 credits_granted;
> + u32 status;
> + u32 max_readwrite_size;
> + u32 preferred_send_size;
> + u32 max_receive_size;
> + u32 max_fragmented_size;
> + int posted;
> + int ret;
> +
> + /*
> + * make sure we won't start again...
> + */
> + disable_work(work);
> +
> + /*
> + * Note recv_io is already part of the free list,
> + * as smbdirect_connect_negotiate_recv_done() called
> + * smbdirect_connection_put_recv_io(), but
> + * it won't be reused before we call
> + * smbdirect_connection_recv_io_refill() below.
> + */
> +
> + if (unlikely(sc->first_error))
> + return;
> +
> + if (sc->status != SMBDIRECT_SOCKET_NEGOTIATE_RUNNING) {
> + /*
> + * Something went wrong...
> + */
> + smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
> + "status=%s first_error=%1pe local: %pISpsfc remote: %pISpsfc\n",
> + smbdirect_socket_status_string(sc->status),
> + SMBDIRECT_DEBUG_ERR_PTR(sc->first_error),
> + &sc->rdma.cm_id->route.addr.src_addr,
> + &sc->rdma.cm_id->route.addr.dst_addr);
> + smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
> + return;
> + }
> +
> nrep = (struct smbdirect_negotiate_resp *)recv_io->packet;
> negotiated_version = le16_to_cpu(nrep->negotiated_version);
> credits_requested = le16_to_cpu(nrep->credits_requested);
> @@ -623,7 +692,16 @@ static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
> smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
> "invalid: negotiated_version=0x%x\n",
> negotiated_version);
> - goto error;
> + smbdirect_connection_schedule_disconnect(sc, -ECONNREFUSED);
> + return;
> + }
> +
> + if (status != 0) {
> + smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
> + "invalid: status=0x%x != 0x0\n",
> + status);
> + smbdirect_connection_schedule_disconnect(sc, -ECONNREFUSED);
> + return;
> }
>
> if (max_receive_size < SMBDIRECT_MIN_RECEIVE_SIZE) {
> @@ -631,7 +709,8 @@ static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
> "invalid: max_receive_size=%u < %u\n",
> max_receive_size,
> SMBDIRECT_MIN_RECEIVE_SIZE);
> - goto error;
> + smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
> + return;
> }
>
> if (max_fragmented_size < SMBDIRECT_MIN_FRAGMENTED_SIZE) {
> @@ -639,19 +718,22 @@ static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
> "invalid: max_fragmented_size=%u < %u\n",
> max_fragmented_size,
> SMBDIRECT_MIN_FRAGMENTED_SIZE);
> - goto error;
> + smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
> + return;
> }
>
> if (credits_granted == 0) {
> smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
> "invalid: credits_granted == 0\n");
> - goto error;
> + smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
> + return;
> }
>
> if (credits_requested == 0) {
> smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
> "invalid: credits_requested == 0\n");
> - goto error;
> + smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
> + return;
> }
>
> if (preferred_send_size > sp->max_recv_size) {
> @@ -659,14 +741,8 @@ static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
> "invalid: preferred_send_size=%u < max_recv_size=%u\n",
> preferred_send_size,
> sp->max_recv_size);
> - goto error;
> - }
> -
> - if (status != 0) {
> - smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
> - "invalid: status=0x%x != 0x0\n",
> - status);
> - goto error;
> + smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
> + return;
> }
>
> /*
> @@ -701,7 +777,8 @@ static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
> "invalid: max_readwrite_size=%u < PAGE_SIZE(%lu)\n",
> max_readwrite_size,
> PAGE_SIZE);
> - goto error;
> + smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
> + return;
> }
> sp->max_frmr_depth = sp->max_read_write_size / PAGE_SIZE;
>
> @@ -716,11 +793,14 @@ static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
> */
> sp->max_fragmented_send_size = max_fragmented_size;
>
> - /*
> - * Give recv_io back to the recv_io.free.list,
> - * so that the refill can also post it.
> - */
> - smbdirect_connection_put_recv_io(recv_io);
> + ret = smbdirect_connection_create_mr_list(sc);
> + if (ret) {
> + smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
> + "smbdirect_connection_create_mr_list() failed %1pe\n",
> + SMBDIRECT_DEBUG_ERR_PTR(ret));
> + smbdirect_connection_schedule_disconnect(sc, ret);
> + return;
> + }
>
> /*
> * Prepare for receiving data_transfer messages
> @@ -731,14 +811,6 @@ static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
> recv_io->cqe.done = smbdirect_connection_recv_io_done;
> recv_io = NULL;
>
> - ret = smbdirect_connection_create_mr_list(sc);
> - if (ret) {
> - smbdirect_log_rdma_mr(sc, SMBDIRECT_LOG_ERR,
> - "smbdirect_connection_create_mr_list() failed %1pe\n",
> - SMBDIRECT_DEBUG_ERR_PTR(ret));
> - goto error;
> - }
> -
> /*
> * We should at least post 1 smbdirect_recv_io!
> */
> @@ -747,7 +819,8 @@ static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
> smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
> "smbdirect_connection_recv_io_refill() failed %1pe\n",
> SMBDIRECT_DEBUG_ERR_PTR(ret));
> - goto error;
> + smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
> + return;
> }
>
> /*
> @@ -756,18 +829,6 @@ static void smbdirect_connect_negotiate_recv_done(struct ib_cq *cq, struct ib_wc
> * the waiter.
> */
> smbdirect_connection_negotiation_done(sc);
> -
> - return;
> -
> -error:
> - /*
> - * recv_io.posted.refill_work is still disabled,
> - * so smbdirect_connection_put_recv_io() won't
> - * start it.
> - */
> - if (recv_io)
> - smbdirect_connection_put_recv_io(recv_io);
> - smbdirect_connection_schedule_disconnect(sc, -ECONNABORTED);
> }
>
> __SMBDIRECT_PUBLIC__
> diff --git a/fs/smb/common/smbdirect/smbdirect_connection.c b/fs/smb/common/smbdirect/smbdirect_connection.c
> index ae9626888b5c..cc22e8b2f4d3 100644
> --- a/fs/smb/common/smbdirect/smbdirect_connection.c
> +++ b/fs/smb/common/smbdirect/smbdirect_connection.c
> @@ -742,6 +742,8 @@ int smbdirect_connection_create_mem_pools(struct smbdirect_socket *sc)
> goto err;
> recv_io->socket = sc;
> recv_io->sge.length = 0;
> + INIT_WORK(&recv_io->complex_work, __smbdirect_socket_disabled_work);
> + disable_work_sync(&recv_io->complex_work);
> list_add_tail(&recv_io->list, &sc->recv_io.free.list);
> }
>
> @@ -757,6 +759,10 @@ void smbdirect_connection_destroy_mem_pools(struct smbdirect_socket *sc)
> struct smbdirect_recv_io *recv_io, *next_io;
>
> list_for_each_entry_safe(recv_io, next_io, &sc->recv_io.free.list, list) {
> + /*
> + * The work should already be disabled
> + */
> + disable_work_sync(&recv_io->complex_work);
> list_del(&recv_io->list);
> mempool_free(recv_io, sc->recv_io.mem.pool);
> }
> @@ -833,9 +839,10 @@ struct smbdirect_recv_io *smbdirect_connection_get_recv_io(struct smbdirect_sock
> unsigned long flags;
>
> spin_lock_irqsave(&sc->recv_io.free.lock, flags);
> - msg = list_first_entry_or_null(&sc->recv_io.free.list,
> - struct smbdirect_recv_io,
> - list);
> + if (likely(!sc->first_error))
> + msg = list_first_entry_or_null(&sc->recv_io.free.list,
> + struct smbdirect_recv_io,
> + list);
> if (likely(msg)) {
> list_del(&msg->list);
> sc->statistics.get_receive_buffer++;
> @@ -851,6 +858,11 @@ void smbdirect_connection_put_recv_io(struct smbdirect_recv_io *msg)
> struct smbdirect_socket *sc = msg->socket;
> unsigned long flags;
>
> + /*
> + * Should already be disabled anyway.
> + */
> + disable_work(&msg->complex_work);
> +
> if (likely(msg->sge.length != 0)) {
> ib_dma_unmap_single(sc->ib.dev,
> msg->sge.addr,
> @@ -874,6 +886,11 @@ static void smbdirect_connection_reassembly_append_recv_io(struct smbdirect_sock
> {
> unsigned long flags;
>
> + /*
> + * The work should already/still be disabled
> + */
> + disable_work(&msg->complex_work);
> +
> spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags);
> list_add_tail(&msg->list, &sc->recv_io.reassembly.list);
> sc->recv_io.reassembly.queue_length++;
> @@ -968,6 +985,14 @@ __SMBDIRECT_PRIVATE__
> void smbdirect_connection_schedule_disconnect(struct smbdirect_socket *sc,
> int error)
> {
> + struct smbdirect_recv_io *recv_io, *recv_tmp;
> + unsigned long flags;
> +
> + if (sc->first_error == 0)
> + sc->first_error = error;
> + if (sc->first_error == 0)
> + sc->first_error = -ECONNABORTED;
> +
> /*
> * make sure other work (than disconnect_work)
> * is not queued again but here we don't block and avoid
> @@ -979,10 +1004,19 @@ void smbdirect_connection_schedule_disconnect(struct smbdirect_socket *sc,
> sc->idle.keepalive = SMBDIRECT_KEEPALIVE_NONE;
> disable_delayed_work(&sc->idle.timer_work);
>
> - if (sc->first_error == 0)
> - sc->first_error = error;
> - if (sc->first_error == 0)
> - sc->first_error = -ECONNABORTED;
> + /*
> + * If any complex work was scheduled we
> + * should disable it (only happens during
> + * negotiation)...
> + *
> + * Note that sc->first_error is set before,
> + * so any future smbdirect_connection_get_recv_io()
> + * will see it and return NULL.
> + */
> + spin_lock_irqsave(&sc->recv_io.free.lock, flags);
> + list_for_each_entry_safe(recv_io, recv_tmp, &sc->recv_io.free.list, list)
> + disable_work(&recv_io->complex_work);
> + spin_unlock_irqrestore(&sc->recv_io.free.lock, flags);
>
> switch (sc->status) {
> case SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED:
> @@ -1037,12 +1071,17 @@ static void smbdirect_connection_disconnect_work(struct work_struct *work)
> {
> struct smbdirect_socket *sc =
> container_of(work, struct smbdirect_socket, disconnect_work);
> + struct smbdirect_recv_io *recv_io, *recv_tmp;
> + unsigned long flags;
>
> /*
> * This should not never be called in an interrupt!
> */
> WARN_ON_ONCE(in_interrupt());
>
> + if (sc->first_error == 0)
> + sc->first_error = -ECONNABORTED;
> +
> /*
> * make sure this and other work is not queued again
> * but here we don't block and avoid
> @@ -1055,8 +1094,19 @@ static void smbdirect_connection_disconnect_work(struct work_struct *work)
> sc->idle.keepalive = SMBDIRECT_KEEPALIVE_NONE;
> disable_delayed_work(&sc->idle.timer_work);
>
> - if (sc->first_error == 0)
> - sc->first_error = -ECONNABORTED;
> + /*
> + * If any complex work was scheduled we
> + * should disable it (only happens during
> + * negotiation)...
> + *
> + * Note that sc->first_error is set before,
> + * so any future smbdirect_connection_get_recv_io()
> + * will see it and return NULL.
> + */
> + spin_lock_irqsave(&sc->recv_io.free.lock, flags);
> + list_for_each_entry_safe(recv_io, recv_tmp, &sc->recv_io.free.list, list)
> + disable_work(&recv_io->complex_work);
> + spin_unlock_irqrestore(&sc->recv_io.free.lock, flags);
>
> switch (sc->status) {
> case SMBDIRECT_SOCKET_NEGOTIATE_NEEDED:
> @@ -1216,6 +1266,24 @@ static void smbdirect_connection_destroy(struct smbdirect_socket *sc)
> disable_work_sync(&sc->idle.immediate_work);
> disable_delayed_work_sync(&sc->idle.timer_work);
>
> + /*
> + * If any complex work was scheduled we
> + * should disable it (only happens during
> + * negotiation)...
> + *
> + * Note was already set in sc->first_error in
> + * smbdirect_connection_schedule_disconnect() or
> + * smbdirect_connection_disconnect_work(), both
> + * before time before:
> + * spin_lock_irqsave(&sc->recv_io.free.lock, flags),
> + * so any future smbdirect_connection_get_recv_io()
> + * will see it and return NULL. And we don't
> + * need to get the lock here again, while
> + * trying disable_work_sync().
> + */
> + list_for_each_entry_safe(recv_io, recv_tmp, &sc->recv_io.free.list, list)
> + disable_work_sync(&recv_io->complex_work);
> +
> if (sc->rdma.cm_id)
> rdma_lock_handler(sc->rdma.cm_id);
>
> @@ -1231,9 +1299,8 @@ static void smbdirect_connection_destroy(struct smbdirect_socket *sc)
> spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags);
> list_splice_tail_init(&sc->recv_io.reassembly.list, &all_list);
> spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags);
> - list_for_each_entry_safe(recv_io, recv_tmp, &all_list, list) {
> + list_for_each_entry_safe(recv_io, recv_tmp, &all_list, list)
> smbdirect_connection_put_recv_io(recv_io);
> - }
> sc->recv_io.reassembly.data_length = 0;
>
> smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
> @@ -2002,7 +2069,7 @@ void smbdirect_connection_recv_io_done(struct ib_cq *cq, struct ib_wc *wc)
> mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
> msecs_to_jiffies(sp->keepalive_interval_msec));
>
> - ib_dma_sync_single_for_cpu(wc->qp->device,
> + ib_dma_sync_single_for_cpu(sc->ib.dev,
> recv_io->sge.addr,
> recv_io->sge.length,
> DMA_FROM_DEVICE);
> diff --git a/fs/smb/common/smbdirect/smbdirect_socket.h b/fs/smb/common/smbdirect/smbdirect_socket.h
> index 65f25fc4b4a7..ef151ff1c02a 100644
> --- a/fs/smb/common/smbdirect/smbdirect_socket.h
> +++ b/fs/smb/common/smbdirect/smbdirect_socket.h
> @@ -6,6 +6,13 @@
> #ifndef __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_SOCKET_H__
> #define __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_SOCKET_H__
>
> +#include <linux/wait.h>
> +#include <linux/workqueue.h>
> +#include <linux/kref.h>
> +#include <linux/mempool.h>
> +#include <linux/spinlock.h>
> +#include <linux/mutex.h>
> +#include <linux/completion.h>
> #include <rdma/rw.h>
>
> enum smbdirect_socket_status {
> @@ -617,6 +624,14 @@ struct smbdirect_recv_io {
> #define SMBDIRECT_RECV_IO_MAX_SGE 1
> struct ib_sge sge;
>
> + /*
> + * We may need to handle complex
> + * work that might sleep and are
> + * not allowed to run in an interrupt
> + * context.
> + */
> + struct work_struct complex_work;
> +
> /* Link to free or reassembly list */
> struct list_head list;
>
>
^ permalink raw reply [flat|nested] 130+ messages in thread
end of thread, other threads:[~2025-11-04 14:50 UTC | newest]
Thread overview: 130+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-29 13:19 [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 001/127] smb: smbdirect: let smbdirect.h include #include <linux/types.h> Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 002/127] smb: smbdirect: introduce SMBDIRECT_DEBUG_ERR_PTR() helper Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 003/127] smb: smbdirect: introduce smbdirect_socket.logging infrastructure Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 004/127] smb: smbdirect: introduce smbdirect_all_c_files.c Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 005/127] smb: smbdirect: introduce smbdirect_internal.h Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 006/127] smb: client: include smbdirect_all_c_files.c Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 007/127] smb: server: " Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 008/127] smb: smbdirect: introduce smbdirect_connection.c with the first helper function Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 009/127] smb: smbdirect: introduce smbdirect_socket_set_logging() Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 010/127] smb: smbdirect: introduce smbd_disconnect_wake_up_all() Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 011/127] smb: smbdirect: introduce smbdirect_connection_disconnect_work() Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 012/127] smb: smbdirect: introduce smbdirect_connection_schedule_disconnect() Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 013/127] smb: smbdirect: introduce smbdirect_connection_{get,put}_recv_io() Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 014/127] smb: smbdirect: introduce smbdirect_connection_reassembly_{append,first}_recv_io() Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 015/127] smb: smbdirect: introduce smbdirect_connection_idle_timer_work() Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 016/127] smb: smbdirect: set SMBDIRECT_KEEPALIVE_NONE before disable_delayed_work(&sc->idle.timer_work); Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 017/127] smb: smbdirect: introduce smbdirect_frwr_is_supported() Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 018/127] smb: smbdirect: introduce smbdirect_socket.{send,recv}_io.mem.gfp_mask Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 019/127] smb: smbdirect: introduce smbdirect_connection_{alloc,free}_send_io() Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 020/127] smb: smbdirect: introduce smbdirect_connection_send_io_done() Stefan Metzmacher
2025-10-29 13:19 ` [PATCH v2 021/127] smb: smbdirect: introduce smbdirect_connection_{create,destroy}_mem_pools() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 022/127] smb: smbdirect: introduce smbdirect_map_sges_from_iter() and helper functions Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 023/127] smb: smbdirect: introduce smbdirect_connection_qp_event_handler() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 024/127] smb: smbdirect: introduce smbdirect_connection_negotiate_rdma_resources() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 025/127] smb: smbdirect: introduce smbdirect_connection_{create,destroy}_qp() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 026/127] smb: smbdirect: introduce smbdirect_connection_post_recv_io() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 027/127] smb: smbdirect: introduce smbdirect_connection_recv_io_refill_work() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 028/127] smb: smbdirect: split out smbdirect_connection_recv_io_refill() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 029/127] smb: smbdirect: introduce smbdirect_get_buf_page_count() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 030/127] smb: smbdirect: introduce smbdirect_connection_wait_for_credits() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 031/127] smb: smbdirect: introduce smbdirect_mr.c with client mr code Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 032/127] smb: smbdirect: introduce smbdirect_rw.c with server rw code Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 033/127] smb: smbdirect: define SMBDIRECT_MIN_{RECEIVE,FRAGMENTED}_SIZE Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 034/127] smb: smbdirect: define SMBDIRECT_RDMA_CM_[RNR_]RETRY Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 035/127] smb: smbdirect: introduce smbdirect_connection_recv_io_done() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 036/127] smb: smbdirect: introduce smbdirect_connection_destroy[_sync]() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 037/127] smb: smbdirect: introduce smbdirect_connection_rdma_{established,event_handler}() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 038/127] smb: smbdirect: introduce smbdirect_connection_recvmsg() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 039/127] smb: smbdirect: introduce smbdirect_connection_grant_recv_credits() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 040/127] smb: smbdirect: introduce smbdirect_connection_request_keep_alive() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 041/127] smb: smbdirect: introduce smbdirect_connection_send_iter() and related functions Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 042/127] smb: smbdirect: introduce smbdirect_connection_send_immediate_work() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 043/127] smb: smbdirect: introduce smbdirect_connection_negotiation_done() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 044/127] smb: smbdirect: introduce smbdirect_mr_io_fill_buffer_descriptor() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 045/127] smb: smbdirect: introduce smbdirect_connection_legacy_debug_proc_show() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 046/127] smb: smbdirect: introduce smbdirect_connection_wait_for_connected() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 047/127] smb: smbdirect: introduce smbdirect_connection_is_connected() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 048/127] smb: smbdirect: introduce smbdirect_socket_shutdown() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 049/127] smb: smbdirect: introduce smbdirect_socket_init_{new,accepting}() and helpers Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 050/127] smb: smbdirect: introduce smbdirect_connect[_sync]() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 051/127] smb: smbdirect: introduce smbdirect_accept_connect_request() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 052/127] smb: smbdirect: introduce smbdirect_socket_create_{kern,accepting}() and smbdirect_socket_release() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 053/127] smb: smbdirect: let smbdirect_internal.h define pr_fmt without SMBDIRECT_USE_INLINE_C_FILES Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 054/127] smb: smbdirect: introduce smbdirect_public.h with prototypes Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 055/127] smb: smbdirect: introduce smbdirect_private.h " Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 056/127] smb: smbdirect: introduce the basic smbdirect.ko Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 057/127] smb: client: make use of smbdirect_socket_prepare_create() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 058/127] smb: client: make use of smbdirect_socket_set_logging() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 059/127] smb: client: make use of smbdirect_connection_wake_up_all() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 060/127] smb: client: make use of smbdirect_connection_disconnect_work() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 061/127] smb: client: make use of smbdirect_connection_schedule_disconnect() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 062/127] smb: client: make use of smbdirect_connection_{get,put}_recv_io() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 063/127] smb: client: make use of smbdirect_connection_reassembly_{append,first}_recv_io() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 064/127] smb: client: make use of smbdirect_connection_idle_timer_work() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 065/127] smb: client: make use of smbdirect_frwr_is_supported() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 066/127] smb: client: make use of smbdirect_connection_{alloc,free}_send_io() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 067/127] smb: client: make use of smbdirect_connection_send_io_done() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 068/127] smb: client: make use of smbdirect_connection_{create,destroy}_mem_pools() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 069/127] smb: client: make use of smbdirect_map_sges_from_iter() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 070/127] smb: client: make use of smbdirect_connection_qp_event_handler() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 071/127] smb: client: make use of smbdirect_connection_negotiate_rdma_resources() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 072/127] smb: client: make use of smbdirect_connection_{create,destroy}_qp() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 073/127] smb: client: initialize recv_io->cqe.done = recv_done just once Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 074/127] smb: client: make use of smbdirect_connection_post_recv_io() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 075/127] smb: client: make use of smbdirect_connection_recv_io_refill_work() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 076/127] smb: client: make use of functions from smbdirect_mr.c Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 077/127] smb: client: make use of smbdirect_connection_destroy_sync() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 078/127] smb: client: make use of smbdirect_connection_recvmsg() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 079/127] smb: client: let smbd_post_send() make use of request->wr Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 080/127] smb: client: make use of smbdirect_connection_grant_recv_credits() Stefan Metzmacher
2025-10-29 13:20 ` [PATCH v2 081/127] smb: client: make use of smbdirect_connection_request_keep_alive() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 082/127] smb: client: change smbd_post_send_empty() to void return Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 083/127] smb: client: let smbd_post_send_iter() get remaining_length and return data_length Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 084/127] smb: client: let smbd_post_send_full_iter() " Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 085/127] smb: client: make use of smbdirect_connection_send_{single_iter,immediate_work}() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 086/127] smb: client: introduce and use smbd_mr_fill_buffer_descriptor() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 087/127] smb: client: introduce and use smbd_debug_proc_show() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 088/127] smb: client: make use of smbdirect_socket_init_new() and smbdirect_connect_sync() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 089/127] smb: client: make use of smbdirect_socket_create_kern()/smbdirect_socket_release() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 090/127] smb: client: only use public smbdirect functions Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 091/127] smb: client: make use of smbdirect.ko Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 092/127] smb: server: make use of smbdirect_socket_prepare_create() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 093/127] smb: server: make use of smbdirect_socket_set_logging() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 094/127] smb: server: make use of smbdirect_connection_wake_up_all() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 095/127] smb: server: make use of smbdirect_connection_disconnect_work() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 096/127] smb: server: make use of smbdirect_connection_schedule_disconnect() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 097/127] smb: server: make use of smbdirect_connection_{get,put}_recv_io() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 098/127] smb: server: make use of smbdirect_connection_reassembly_{append,first}_recv_io() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 099/127] smb: server: make use of smbdirect_connection_idle_timer_work() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 100/127] smb: server: make use of smbdirect_frwr_is_supported() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 101/127] smb: server: make use of smbdirect_connection_{alloc,free}_send_io() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 102/127] smb: server: make use of smbdirect_connection_send_io_done() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 103/127] smb: server: make use of smbdirect_connection_{create,destroy}_mem_pools() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 104/127] smb: server: make use of smbdirect_map_sges_from_iter() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 105/127] smb: server: make use of smbdirect_connection_qp_event_handler() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 106/127] smb: server: make use of smbdirect_connection_negotiate_rdma_resources() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 107/127] smb: server: make use of smbdirect_connection_{create,destroy}_qp() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 108/127] smb: server: initialize recv_io->cqe.done = recv_done just once Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 109/127] smb: server: make use of smbdirect_connection_post_recv_io() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 110/127] smb: server: make use of smbdirect_connection_recv_io_refill[_work]() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 111/127] smb: server: make use of smbdirect_get_buf_page_count() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 112/127] smb: server: make use of smbdirect_connection_wait_for_credits() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 113/127] smb: server: make use of functions from smbdirect_rw.c Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 114/127] smb: server: make use of smbdirect_connection_destroy_sync() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 115/127] smb: server: make use of smbdirect_connection_recvmsg() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 116/127] smb: server: make use of smbdirect_connection_grant_recv_credits() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 117/127] smb: server: make use of smbdirect_connection_request_keep_alive() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 118/127] smb: server: move iov_iter_kvec() out of smb_direct_post_send_data() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 119/127] smb: server: inline smb_direct_create_header() into smb_direct_post_send_data() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 120/127] smb: server: let smbdirect_map_sges_from_iter() truncate the message boundary Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 121/127] smb: server: split out smb_direct_send_iter() out of smb_direct_writev() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 122/127] smb: server: let smb_direct_post_send_data() return data_length Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 123/127] smb: server: make use of smbdirect_connection_send_iter() and related functions Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 124/127] smb: server: make use of smbdirect_{socket_init_accepting,connection_wait_for_connected}() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 125/127] smb: server: make use of smbdirect_socket_create_accepting()/smbdirect_socket_release() Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 126/127] smb: server: only use public smbdirect functions Stefan Metzmacher
2025-10-29 13:21 ` [PATCH v2 127/127] smb: server: make use of smbdirect.ko Stefan Metzmacher
2025-11-04 10:49 ` [PATCH v2 000/127] smb: smbdirect/client/server: moving to common functions and smbdirect.ko Stefan Metzmacher
2025-11-04 14:49 ` Namjae Jeon
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).