fourteen smb3 client fixes, most smbdirect related

-----BEGIN PGP SIGNATURE-----
 
 iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmhEsJkACgkQiiy9cAdy
 T1Gjlgv+P1I4uD8iDbkJvyrh7mVcnIDnjttbgN1pTZZnpcX7JIyMPR9YPUn+QTKf
 3GStGgLHqKtnXYYCdrkpPipsH/fjt7kjVLUC/YMhUGEr5dSFKzygOVaRTo4LDgNO
 sSlOxTPyTaPgxdvIXriU5CeJGtm95GqowLDG29We9ubX1P5GLjIjGlMbAisAk4/Q
 ek478D0qBSO5u6FkMYUFuSbjGwOYWAlabMxeOVHpjgEH/36tVtDKOc/bORnVZtHB
 6bRjhymn9CZQOE2P+gDSqF6pZwHWhU7uYJYW+kbDbmDIgWDk9xl5/kbbqZ6RR3t5
 joPWzZkO1I58avmJ31aauhvRpYIOXfOhx2dHB6VM/7bSHTvE6CW60RIlpXo1xbO6
 d30pTy7ICqP/RWNZlt5ZgoPTDB1hPmVDdMXoELp7uZzChhrAz4qc/2BSD0Y5fCjE
 e/U0bPfsyjscB7NtpcrQYVMbOsrweQ4qKUgolEk1klLolsKxDGE176wbPmLNAzo4
 C9SzyxU3
 =RvlW
 -----END PGP SIGNATURE-----

Merge tag '6.16-rc-part2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull more smb client updates from Steve French:

 - multichannel/reconnect fixes

 - move smbdirect (smb over RDMA) defines to fs/smb/common so they will
   be able to be used in the future more broadly, and a documentation
   update explaining setting up smbdirect mounts

 - update email address for Paulo

* tag '6.16-rc-part2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: update internal version number
  MAINTAINERS, mailmap: Update Paulo Alcantara's email address
  cifs: add documentation for smbdirect setup
  cifs: do not disable interface polling on failure
  cifs: serialize other channels when query server interfaces is pending
  cifs: deal with the channel loading lag while picking channels
  smb: client: make use of common smbdirect_socket_parameters
  smb: smbdirect: introduce smbdirect_socket_parameters
  smb: client: make use of common smbdirect_socket
  smb: smbdirect: add smbdirect_socket.h
  smb: client: make use of common smbdirect.h
  smb: smbdirect: add smbdirect.h with public structures
  smb: client: make use of common smbdirect_pdu.h
  smb: smbdirect: add smbdirect_pdu.h with protocol definitions
This commit is contained in:
Linus Torvalds 2025-06-08 10:20:21 -07:00
commit 522cd6acd2
16 changed files with 532 additions and 287 deletions

View file

@ -602,6 +602,12 @@ Paul Mackerras <paulus@ozlabs.org> <paulus@samba.org>
Paul Mackerras <paulus@ozlabs.org> <paulus@au1.ibm.com>
Paul Moore <paul@paul-moore.com> <paul.moore@hp.com>
Paul Moore <paul@paul-moore.com> <pmoore@redhat.com>
Paulo Alcantara <pc@manguebit.org> <pcacjr@zytor.com>
Paulo Alcantara <pc@manguebit.org> <paulo@paulo.ac>
Paulo Alcantara <pc@manguebit.org> <pc@cjr.nz>
Paulo Alcantara <pc@manguebit.org> <palcantara@suse.de>
Paulo Alcantara <pc@manguebit.org> <palcantara@suse.com>
Paulo Alcantara <pc@manguebit.org> <pc@manguebit.com>
Pavankumar Kondeti <quic_pkondeti@quicinc.com> <pkondeti@codeaurora.org>
Peter A Jonsson <pj@ludd.ltu.se>
Peter Oruba <peter.oruba@amd.com>

View file

@ -8,3 +8,4 @@ CIFS
ksmbd
cifsroot
smbdirect

View file

@ -0,0 +1,103 @@
.. SPDX-License-Identifier: GPL-2.0
===========================
SMB Direct - SMB3 over RDMA
===========================
This document describes how to set up the Linux SMB client and server to
use RDMA.
Overview
========
The Linux SMB kernel client supports SMB Direct, which is a transport
scheme for SMB3 that uses RDMA (Remote Direct Memory Access) to provide
high throughput and low latencies by bypassing the traditional TCP/IP
stack.
SMB Direct on the Linux SMB client can be tested against KSMBD - a
kernel-space SMB server.
Installation
=============
- Install an RDMA device. As long as the RDMA device driver is supported
by the kernel, it should work. This includes both software emulators (soft
RoCE, soft iWARP) and hardware devices (InfiniBand, RoCE, iWARP).
- Install a kernel with SMB Direct support. The first kernel release to
support SMB Direct on both the client and server side is 5.15. Therefore,
a distribution compatible with kernel 5.15 or later is required.
- Install cifs-utils, which provides the `mount.cifs` command to mount SMB
shares.
- Configure the RDMA stack
Make sure that your kernel configuration has RDMA support enabled. Under
Device Drivers -> Infiniband support, update the kernel configuration to
enable Infiniband support.
Enable the appropriate IB HCA support or iWARP adapter support,
depending on your hardware.
If you are using InfiniBand, enable IP-over-InfiniBand support.
For soft RDMA, enable either the soft iWARP (`RDMA _SIW`) or soft RoCE
(`RDMA_RXE`) module. Install the `iproute2` package and use the
`rdma link add` command to load the module and create an
RDMA interface.
e.g. if your local ethernet interface is `eth0`, you can use:
.. code-block:: bash
sudo rdma link add siw0 type siw netdev eth0
- Enable SMB Direct support for both the server and the client in the kernel
configuration.
Server Setup
.. code-block:: text
Network File Systems --->
<M> SMB3 server support
[*] Support for SMB Direct protocol
Client Setup
.. code-block:: text
Network File Systems --->
<M> SMB3 and CIFS support (advanced network filesystem)
[*] SMB Direct support
- Build and install the kernel. SMB Direct support will be enabled in the
cifs.ko and ksmbd.ko modules.
Setup and Usage
================
- Set up and start a KSMBD server as described in the `KSMBD documentation
<https://www.kernel.org/doc/Documentation/filesystems/smb/ksmbd.rst>`_.
Also add the "server multi channel support = yes" parameter to ksmbd.conf.
- On the client, mount the share with `rdma` mount option to use SMB Direct
(specify a SMB version 3.0 or higher using `vers`).
For example:
.. code-block:: bash
mount -t cifs //server/share /mnt/point -o vers=3.1.1,rdma
- To verify that the mount is using SMB Direct, you can check dmesg for the
following log line after mounting:
.. code-block:: text
CIFS: VFS: RDMA transport established
Or, verify `rdma` mount option for the share in `/proc/mounts`:
.. code-block:: bash
cat /proc/mounts | grep cifs

View file

@ -5986,7 +5986,7 @@ X: drivers/clk/clkdev.c
COMMON INTERNET FILE SYSTEM CLIENT (CIFS and SMB3)
M: Steve French <sfrench@samba.org>
M: Steve French <smfrench@gmail.com>
R: Paulo Alcantara <pc@manguebit.com> (DFS, global name space)
R: Paulo Alcantara <pc@manguebit.org> (DFS, global name space)
R: Ronnie Sahlberg <ronniesahlberg@gmail.com> (directory leases, sparse files)
R: Shyam Prasad N <sprasad@microsoft.com> (multichannel)
R: Tom Talpey <tom@talpey.com> (RDMA, smbdirect)
@ -9280,7 +9280,7 @@ F: include/linux/iomap.h
FILESYSTEMS [NETFS LIBRARY]
M: David Howells <dhowells@redhat.com>
M: Paulo Alcantara <pc@manguebit.com>
M: Paulo Alcantara <pc@manguebit.org>
L: netfs@lists.linux.dev
L: linux-fsdevel@vger.kernel.org
S: Supported

View file

@ -362,6 +362,10 @@ 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_parameters *sp;
#endif
/* channel info will be printed as a part of sessions below */
if (SERVER_IS_CHAN(server))
continue;
@ -383,25 +387,26 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
seq_printf(m, "\nSMBDirect transport not available");
goto skip_rdma;
}
sp = &server->smbd_conn->socket.parameters;
seq_printf(m, "\nSMBDirect (in hex) protocol version: %x "
"transport status: %x",
server->smbd_conn->protocol,
server->smbd_conn->transport_status);
server->smbd_conn->socket.status);
seq_printf(m, "\nConn receive_credit_max: %x "
"send_credit_target: %x max_send_size: %x",
server->smbd_conn->receive_credit_max,
server->smbd_conn->send_credit_target,
server->smbd_conn->max_send_size);
sp->recv_credit_max,
sp->send_credit_target,
sp->max_send_size);
seq_printf(m, "\nConn max_fragmented_recv_size: %x "
"max_fragmented_send_size: %x max_receive_size:%x",
server->smbd_conn->max_fragmented_recv_size,
server->smbd_conn->max_fragmented_send_size,
server->smbd_conn->max_receive_size);
sp->max_fragmented_recv_size,
sp->max_fragmented_send_size,
sp->max_recv_size);
seq_printf(m, "\nConn keep_alive_interval: %x "
"max_readwrite_size: %x rdma_readwrite_threshold: %x",
server->smbd_conn->keep_alive_interval,
server->smbd_conn->max_readwrite_size,
sp->keepalive_interval_msec * 1000,
sp->max_read_write_size,
server->smbd_conn->rdma_readwrite_threshold);
seq_printf(m, "\nDebug count_get_receive_buffer: %x "
"count_put_receive_buffer: %x count_send_empty: %x",

View file

@ -145,6 +145,6 @@ extern const struct export_operations cifs_export_ops;
#endif /* CONFIG_CIFS_NFSD_EXPORT */
/* when changing internal version - update following two lines at same time */
#define SMB3_PRODUCT_BUILD 54
#define CIFS_VERSION "2.54"
#define SMB3_PRODUCT_BUILD 55
#define CIFS_VERSION "2.55"
#endif /* _CIFSFS_H */

View file

@ -1085,6 +1085,7 @@ struct cifs_chan {
};
#define CIFS_SES_FLAG_SCALE_CHANNELS (0x1)
#define CIFS_SES_FLAGS_PENDING_QUERY_INTERFACES (0x2)
/*
* Session structure. One of these for each uid session with a particular host

View file

@ -116,13 +116,9 @@ static void smb2_query_server_interfaces(struct work_struct *work)
rc = server->ops->query_server_interfaces(xid, tcon, false);
free_xid(xid);
if (rc) {
if (rc == -EOPNOTSUPP)
return;
if (rc)
cifs_dbg(FYI, "%s: failed to query server interfaces: %d\n",
__func__, rc);
}
queue_delayed_work(cifsiod_wq, &tcon->query_interfaces,
(SMB_INTERFACE_POLL_INTERVAL * HZ));

View file

@ -504,6 +504,9 @@ smb3_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
wsize = min_t(unsigned int, wsize, server->max_write);
#ifdef CONFIG_CIFS_SMB_DIRECT
if (server->rdma) {
struct smbdirect_socket_parameters *sp =
&server->smbd_conn->socket.parameters;
if (server->sign)
/*
* Account for SMB2 data transfer packet header and
@ -511,12 +514,12 @@ smb3_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
*/
wsize = min_t(unsigned int,
wsize,
server->smbd_conn->max_fragmented_send_size -
sp->max_fragmented_send_size -
SMB2_READWRITE_PDU_HEADER_SIZE -
sizeof(struct smb2_transform_hdr));
else
wsize = min_t(unsigned int,
wsize, server->smbd_conn->max_readwrite_size);
wsize, sp->max_read_write_size);
}
#endif
if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
@ -552,6 +555,9 @@ smb3_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
rsize = min_t(unsigned int, rsize, server->max_read);
#ifdef CONFIG_CIFS_SMB_DIRECT
if (server->rdma) {
struct smbdirect_socket_parameters *sp =
&server->smbd_conn->socket.parameters;
if (server->sign)
/*
* Account for SMB2 data transfer packet header and
@ -559,12 +565,12 @@ smb3_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
*/
rsize = min_t(unsigned int,
rsize,
server->smbd_conn->max_fragmented_recv_size -
sp->max_fragmented_recv_size -
SMB2_READWRITE_PDU_HEADER_SIZE -
sizeof(struct smb2_transform_hdr));
else
rsize = min_t(unsigned int,
rsize, server->smbd_conn->max_readwrite_size);
rsize, sp->max_read_write_size);
}
#endif

View file

@ -36,6 +36,7 @@
#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
@ -411,14 +412,23 @@ skip_sess_setup:
if (!rc &&
(server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL) &&
server->ops->query_server_interfaces) {
mutex_unlock(&ses->session_mutex);
/*
* query server network interfaces, in case they change
* query server network interfaces, in case they change.
* Also mark the session as pending this update while the query
* is in progress. This will be used to avoid calling
* smb2_reconnect recursively.
*/
ses->flags |= CIFS_SES_FLAGS_PENDING_QUERY_INTERFACES;
xid = get_xid();
rc = server->ops->query_server_interfaces(xid, tcon, false);
free_xid(xid);
ses->flags &= ~CIFS_SES_FLAGS_PENDING_QUERY_INTERFACES;
/* regardless of rc value, setup polling */
queue_delayed_work(cifsiod_wq, &tcon->query_interfaces,
(SMB_INTERFACE_POLL_INTERVAL * HZ));
mutex_unlock(&ses->session_mutex);
if (rc == -EOPNOTSUPP && ses->chan_count > 1) {
/*
@ -438,11 +448,8 @@ skip_sess_setup:
if (ses->chan_max > ses->chan_count &&
ses->iface_count &&
!SERVER_IS_CHAN(server)) {
if (ses->chan_count == 1) {
if (ses->chan_count == 1)
cifs_server_dbg(VFS, "supports multichannel now\n");
queue_delayed_work(cifsiod_wq, &tcon->query_interfaces,
(SMB_INTERFACE_POLL_INTERVAL * HZ));
}
cifs_try_adding_channels(ses);
}
@ -560,11 +567,18 @@ static int smb2_ioctl_req_init(u32 opcode, struct cifs_tcon *tcon,
struct TCP_Server_Info *server,
void **request_buf, unsigned int *total_len)
{
/* Skip reconnect only for FSCTL_VALIDATE_NEGOTIATE_INFO IOCTLs */
if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO) {
/*
* Skip reconnect in one of the following cases:
* 1. For FSCTL_VALIDATE_NEGOTIATE_INFO IOCTLs
* 2. For FSCTL_QUERY_NETWORK_INTERFACE_INFO IOCTL when called from
* smb2_reconnect (indicated by CIFS_SES_FLAG_SCALE_CHANNELS ses flag)
*/
if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO ||
(opcode == FSCTL_QUERY_NETWORK_INTERFACE_INFO &&
(tcon->ses->flags & CIFS_SES_FLAGS_PENDING_QUERY_INTERFACES)))
return __smb2_plain_req_init(SMB2_IOCTL, tcon, server,
request_buf, total_len);
}
return smb2_plain_req_init(SMB2_IOCTL, tcon, server,
request_buf, total_len);
}
@ -4449,10 +4463,10 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
#ifdef CONFIG_CIFS_SMB_DIRECT
/*
* If we want to do a RDMA write, fill in and append
* smbd_buffer_descriptor_v1 to the end of read request
* smbdirect_buffer_descriptor_v1 to the end of read request
*/
if (rdata && smb3_use_rdma_offload(io_parms)) {
struct smbd_buffer_descriptor_v1 *v1;
struct smbdirect_buffer_descriptor_v1 *v1;
bool need_invalidate = server->dialect == SMB30_PROT_ID;
rdata->mr = smbd_register_mr(server->smbd_conn, &rdata->subreq.io_iter,
@ -4466,8 +4480,8 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
req->ReadChannelInfoOffset =
cpu_to_le16(offsetof(struct smb2_read_req, Buffer));
req->ReadChannelInfoLength =
cpu_to_le16(sizeof(struct smbd_buffer_descriptor_v1));
v1 = (struct smbd_buffer_descriptor_v1 *) &req->Buffer[0];
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);
@ -4975,10 +4989,10 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
#ifdef CONFIG_CIFS_SMB_DIRECT
/*
* If we want to do a server RDMA read, fill in and append
* smbd_buffer_descriptor_v1 to the end of write request
* smbdirect_buffer_descriptor_v1 to the end of write request
*/
if (smb3_use_rdma_offload(io_parms)) {
struct smbd_buffer_descriptor_v1 *v1;
struct smbdirect_buffer_descriptor_v1 *v1;
bool need_invalidate = server->dialect == SMB30_PROT_ID;
wdata->mr = smbd_register_mr(server->smbd_conn, &wdata->subreq.io_iter,
@ -4997,8 +5011,8 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
req->WriteChannelInfoOffset =
cpu_to_le16(offsetof(struct smb2_write_req, Buffer));
req->WriteChannelInfoLength =
cpu_to_le16(sizeof(struct smbd_buffer_descriptor_v1));
v1 = (struct smbd_buffer_descriptor_v1 *) &req->Buffer[0];
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);

File diff suppressed because it is too large Load diff

View file

@ -15,6 +15,9 @@
#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;
extern int smbd_keep_alive_interval;
@ -50,14 +53,8 @@ enum smbd_connection_status {
* 5. mempools for allocating packets
*/
struct smbd_connection {
enum smbd_connection_status transport_status;
struct smbdirect_socket socket;
/* RDMA related */
struct rdma_cm_id *id;
struct ib_qp_init_attr qp_attr;
struct ib_pd *pd;
struct ib_cq *send_cq, *recv_cq;
struct ib_device_attr dev_attr;
int ri_rc;
struct completion ri_done;
wait_queue_head_t conn_wait;
@ -72,15 +69,7 @@ struct smbd_connection {
spinlock_t lock_new_credits_offered;
int new_credits_offered;
/* Connection parameters defined in [MS-SMBD] 3.1.1.1 */
int receive_credit_max;
int send_credit_target;
int max_send_size;
int max_fragmented_recv_size;
int max_fragmented_send_size;
int max_receive_size;
int keep_alive_interval;
int max_readwrite_size;
/* dynamic connection parameters defined in [MS-SMBD] 3.1.1.1 */
enum keep_alive_status keep_alive_requested;
int protocol;
atomic_t send_credits;
@ -177,54 +166,6 @@ enum smbd_message_type {
SMBD_TRANSFER_DATA,
};
#define SMB_DIRECT_RESPONSE_REQUESTED 0x0001
/* SMBD negotiation request packet [MS-SMBD] 2.2.1 */
struct smbd_negotiate_req {
__le16 min_version;
__le16 max_version;
__le16 reserved;
__le16 credits_requested;
__le32 preferred_send_size;
__le32 max_receive_size;
__le32 max_fragmented_size;
} __packed;
/* SMBD negotiation response packet [MS-SMBD] 2.2.2 */
struct smbd_negotiate_resp {
__le16 min_version;
__le16 max_version;
__le16 negotiated_version;
__le16 reserved;
__le16 credits_requested;
__le16 credits_granted;
__le32 status;
__le32 max_readwrite_size;
__le32 preferred_send_size;
__le32 max_receive_size;
__le32 max_fragmented_size;
} __packed;
/* SMBD data transfer packet with payload [MS-SMBD] 2.2.3 */
struct smbd_data_transfer {
__le16 credits_requested;
__le16 credits_granted;
__le16 flags;
__le16 reserved;
__le32 remaining_data_length;
__le32 data_offset;
__le32 data_length;
__le32 padding;
__u8 buffer[];
} __packed;
/* The packet fields for a registered RDMA buffer */
struct smbd_buffer_descriptor_v1 {
__le64 offset;
__le32 token;
__le32 length;
} __packed;
/* Maximum number of SGEs used by smbdirect.c in any send work request */
#define SMBDIRECT_MAX_SEND_SGE 6

View file

@ -1018,14 +1018,16 @@ struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses)
uint index = 0;
unsigned int min_in_flight = UINT_MAX, max_in_flight = 0;
struct TCP_Server_Info *server = NULL;
int i;
int i, start, cur;
if (!ses)
return NULL;
spin_lock(&ses->chan_lock);
start = atomic_inc_return(&ses->chan_seq);
for (i = 0; i < ses->chan_count; i++) {
server = ses->chans[i].server;
cur = (start + i) % ses->chan_count;
server = ses->chans[cur].server;
if (!server || server->terminate)
continue;
@ -1042,17 +1044,15 @@ struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses)
*/
if (server->in_flight < min_in_flight) {
min_in_flight = server->in_flight;
index = i;
index = cur;
}
if (server->in_flight > max_in_flight)
max_in_flight = server->in_flight;
}
/* if all channels are equally loaded, fall back to round-robin */
if (min_in_flight == max_in_flight) {
index = (uint)atomic_inc_return(&ses->chan_seq);
index %= ses->chan_count;
}
if (min_in_flight == max_in_flight)
index = (uint)start % ses->chan_count;
server = ses->chans[index].server;
spin_unlock(&ses->chan_lock);

View file

@ -0,0 +1,37 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2017, Microsoft Corporation.
* Copyright (C) 2018, LG Electronics.
*/
#ifndef __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_H__
#define __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_H__
/* SMB-DIRECT buffer descriptor V1 structure [MS-SMBD] 2.2.3.1 */
struct smbdirect_buffer_descriptor_v1 {
__le64 offset;
__le32 token;
__le32 length;
} __packed;
/*
* Connection parameters mostly from [MS-SMBD] 3.1.1.1
*
* These are setup and negotiated at the beginning of a
* connection and remain constant unless explicitly changed.
*
* Some values are important for the upper layer.
*/
struct smbdirect_socket_parameters {
__u16 recv_credit_max;
__u16 send_credit_target;
__u32 max_send_size;
__u32 max_fragmented_send_size;
__u32 max_recv_size;
__u32 max_fragmented_recv_size;
__u32 max_read_write_size;
__u32 keepalive_interval_msec;
__u32 keepalive_timeout_msec;
} __packed;
#endif /* __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_H__ */

View file

@ -0,0 +1,55 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (c) 2017 Stefan Metzmacher
*/
#ifndef __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_PDU_H__
#define __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_PDU_H__
#define SMBDIRECT_V1 0x0100
/* SMBD negotiation request packet [MS-SMBD] 2.2.1 */
struct smbdirect_negotiate_req {
__le16 min_version;
__le16 max_version;
__le16 reserved;
__le16 credits_requested;
__le32 preferred_send_size;
__le32 max_receive_size;
__le32 max_fragmented_size;
} __packed;
/* SMBD negotiation response packet [MS-SMBD] 2.2.2 */
struct smbdirect_negotiate_resp {
__le16 min_version;
__le16 max_version;
__le16 negotiated_version;
__le16 reserved;
__le16 credits_requested;
__le16 credits_granted;
__le32 status;
__le32 max_readwrite_size;
__le32 preferred_send_size;
__le32 max_receive_size;
__le32 max_fragmented_size;
} __packed;
#define SMBDIRECT_DATA_MIN_HDR_SIZE 0x14
#define SMBDIRECT_DATA_OFFSET 0x18
#define SMBDIRECT_FLAG_RESPONSE_REQUESTED 0x0001
/* SMBD data transfer packet with payload [MS-SMBD] 2.2.3 */
struct smbdirect_data_transfer {
__le16 credits_requested;
__le16 credits_granted;
__le16 flags;
__le16 reserved;
__le32 remaining_data_length;
__le32 data_offset;
__le32 data_length;
__le32 padding;
__u8 buffer[];
} __packed;
#endif /* __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_PDU_H__ */

View file

@ -0,0 +1,43 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (c) 2025 Stefan Metzmacher
*/
#ifndef __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_SOCKET_H__
#define __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_SOCKET_H__
enum smbdirect_socket_status {
SMBDIRECT_SOCKET_CREATED,
SMBDIRECT_SOCKET_CONNECTING,
SMBDIRECT_SOCKET_CONNECTED,
SMBDIRECT_SOCKET_NEGOTIATE_FAILED,
SMBDIRECT_SOCKET_DISCONNECTING,
SMBDIRECT_SOCKET_DISCONNECTED,
SMBDIRECT_SOCKET_DESTROYED
};
struct smbdirect_socket {
enum smbdirect_socket_status status;
/* RDMA related */
struct {
struct rdma_cm_id *cm_id;
} rdma;
/* IB verbs related */
struct {
struct ib_pd *pd;
struct ib_cq *send_cq;
struct ib_cq *recv_cq;
/*
* shortcuts for rdma.cm_id->{qp,device};
*/
struct ib_qp *qp;
struct ib_device *dev;
} ib;
struct smbdirect_socket_parameters parameters;
};
#endif /* __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_SOCKET_H__ */