mirror of https://github.com/torvalds/linux.git
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:
commit
522cd6acd2
6
.mailmap
6
.mailmap
|
|
@ -602,6 +602,12 @@ Paul Mackerras <paulus@ozlabs.org> <paulus@samba.org>
|
||||||
Paul Mackerras <paulus@ozlabs.org> <paulus@au1.ibm.com>
|
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> <paul.moore@hp.com>
|
||||||
Paul Moore <paul@paul-moore.com> <pmoore@redhat.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>
|
Pavankumar Kondeti <quic_pkondeti@quicinc.com> <pkondeti@codeaurora.org>
|
||||||
Peter A Jonsson <pj@ludd.ltu.se>
|
Peter A Jonsson <pj@ludd.ltu.se>
|
||||||
Peter Oruba <peter.oruba@amd.com>
|
Peter Oruba <peter.oruba@amd.com>
|
||||||
|
|
|
||||||
|
|
@ -8,3 +8,4 @@ CIFS
|
||||||
|
|
||||||
ksmbd
|
ksmbd
|
||||||
cifsroot
|
cifsroot
|
||||||
|
smbdirect
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -5986,7 +5986,7 @@ X: drivers/clk/clkdev.c
|
||||||
COMMON INTERNET FILE SYSTEM CLIENT (CIFS and SMB3)
|
COMMON INTERNET FILE SYSTEM CLIENT (CIFS and SMB3)
|
||||||
M: Steve French <sfrench@samba.org>
|
M: Steve French <sfrench@samba.org>
|
||||||
M: Steve French <smfrench@gmail.com>
|
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: Ronnie Sahlberg <ronniesahlberg@gmail.com> (directory leases, sparse files)
|
||||||
R: Shyam Prasad N <sprasad@microsoft.com> (multichannel)
|
R: Shyam Prasad N <sprasad@microsoft.com> (multichannel)
|
||||||
R: Tom Talpey <tom@talpey.com> (RDMA, smbdirect)
|
R: Tom Talpey <tom@talpey.com> (RDMA, smbdirect)
|
||||||
|
|
@ -9280,7 +9280,7 @@ F: include/linux/iomap.h
|
||||||
|
|
||||||
FILESYSTEMS [NETFS LIBRARY]
|
FILESYSTEMS [NETFS LIBRARY]
|
||||||
M: David Howells <dhowells@redhat.com>
|
M: David Howells <dhowells@redhat.com>
|
||||||
M: Paulo Alcantara <pc@manguebit.com>
|
M: Paulo Alcantara <pc@manguebit.org>
|
||||||
L: netfs@lists.linux.dev
|
L: netfs@lists.linux.dev
|
||||||
L: linux-fsdevel@vger.kernel.org
|
L: linux-fsdevel@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
|
|
|
||||||
|
|
@ -362,6 +362,10 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
|
||||||
c = 0;
|
c = 0;
|
||||||
spin_lock(&cifs_tcp_ses_lock);
|
spin_lock(&cifs_tcp_ses_lock);
|
||||||
list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
|
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 */
|
/* channel info will be printed as a part of sessions below */
|
||||||
if (SERVER_IS_CHAN(server))
|
if (SERVER_IS_CHAN(server))
|
||||||
continue;
|
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");
|
seq_printf(m, "\nSMBDirect transport not available");
|
||||||
goto skip_rdma;
|
goto skip_rdma;
|
||||||
}
|
}
|
||||||
|
sp = &server->smbd_conn->socket.parameters;
|
||||||
|
|
||||||
seq_printf(m, "\nSMBDirect (in hex) protocol version: %x "
|
seq_printf(m, "\nSMBDirect (in hex) protocol version: %x "
|
||||||
"transport status: %x",
|
"transport status: %x",
|
||||||
server->smbd_conn->protocol,
|
server->smbd_conn->protocol,
|
||||||
server->smbd_conn->transport_status);
|
server->smbd_conn->socket.status);
|
||||||
seq_printf(m, "\nConn receive_credit_max: %x "
|
seq_printf(m, "\nConn receive_credit_max: %x "
|
||||||
"send_credit_target: %x max_send_size: %x",
|
"send_credit_target: %x max_send_size: %x",
|
||||||
server->smbd_conn->receive_credit_max,
|
sp->recv_credit_max,
|
||||||
server->smbd_conn->send_credit_target,
|
sp->send_credit_target,
|
||||||
server->smbd_conn->max_send_size);
|
sp->max_send_size);
|
||||||
seq_printf(m, "\nConn max_fragmented_recv_size: %x "
|
seq_printf(m, "\nConn max_fragmented_recv_size: %x "
|
||||||
"max_fragmented_send_size: %x max_receive_size:%x",
|
"max_fragmented_send_size: %x max_receive_size:%x",
|
||||||
server->smbd_conn->max_fragmented_recv_size,
|
sp->max_fragmented_recv_size,
|
||||||
server->smbd_conn->max_fragmented_send_size,
|
sp->max_fragmented_send_size,
|
||||||
server->smbd_conn->max_receive_size);
|
sp->max_recv_size);
|
||||||
seq_printf(m, "\nConn keep_alive_interval: %x "
|
seq_printf(m, "\nConn keep_alive_interval: %x "
|
||||||
"max_readwrite_size: %x rdma_readwrite_threshold: %x",
|
"max_readwrite_size: %x rdma_readwrite_threshold: %x",
|
||||||
server->smbd_conn->keep_alive_interval,
|
sp->keepalive_interval_msec * 1000,
|
||||||
server->smbd_conn->max_readwrite_size,
|
sp->max_read_write_size,
|
||||||
server->smbd_conn->rdma_readwrite_threshold);
|
server->smbd_conn->rdma_readwrite_threshold);
|
||||||
seq_printf(m, "\nDebug count_get_receive_buffer: %x "
|
seq_printf(m, "\nDebug count_get_receive_buffer: %x "
|
||||||
"count_put_receive_buffer: %x count_send_empty: %x",
|
"count_put_receive_buffer: %x count_send_empty: %x",
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,6 @@ extern const struct export_operations cifs_export_ops;
|
||||||
#endif /* CONFIG_CIFS_NFSD_EXPORT */
|
#endif /* CONFIG_CIFS_NFSD_EXPORT */
|
||||||
|
|
||||||
/* when changing internal version - update following two lines at same time */
|
/* when changing internal version - update following two lines at same time */
|
||||||
#define SMB3_PRODUCT_BUILD 54
|
#define SMB3_PRODUCT_BUILD 55
|
||||||
#define CIFS_VERSION "2.54"
|
#define CIFS_VERSION "2.55"
|
||||||
#endif /* _CIFSFS_H */
|
#endif /* _CIFSFS_H */
|
||||||
|
|
|
||||||
|
|
@ -1085,6 +1085,7 @@ struct cifs_chan {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CIFS_SES_FLAG_SCALE_CHANNELS (0x1)
|
#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
|
* Session structure. One of these for each uid session with a particular host
|
||||||
|
|
|
||||||
|
|
@ -116,13 +116,9 @@ static void smb2_query_server_interfaces(struct work_struct *work)
|
||||||
rc = server->ops->query_server_interfaces(xid, tcon, false);
|
rc = server->ops->query_server_interfaces(xid, tcon, false);
|
||||||
free_xid(xid);
|
free_xid(xid);
|
||||||
|
|
||||||
if (rc) {
|
if (rc)
|
||||||
if (rc == -EOPNOTSUPP)
|
|
||||||
return;
|
|
||||||
|
|
||||||
cifs_dbg(FYI, "%s: failed to query server interfaces: %d\n",
|
cifs_dbg(FYI, "%s: failed to query server interfaces: %d\n",
|
||||||
__func__, rc);
|
__func__, rc);
|
||||||
}
|
|
||||||
|
|
||||||
queue_delayed_work(cifsiod_wq, &tcon->query_interfaces,
|
queue_delayed_work(cifsiod_wq, &tcon->query_interfaces,
|
||||||
(SMB_INTERFACE_POLL_INTERVAL * HZ));
|
(SMB_INTERFACE_POLL_INTERVAL * HZ));
|
||||||
|
|
|
||||||
|
|
@ -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);
|
wsize = min_t(unsigned int, wsize, server->max_write);
|
||||||
#ifdef CONFIG_CIFS_SMB_DIRECT
|
#ifdef CONFIG_CIFS_SMB_DIRECT
|
||||||
if (server->rdma) {
|
if (server->rdma) {
|
||||||
|
struct smbdirect_socket_parameters *sp =
|
||||||
|
&server->smbd_conn->socket.parameters;
|
||||||
|
|
||||||
if (server->sign)
|
if (server->sign)
|
||||||
/*
|
/*
|
||||||
* Account for SMB2 data transfer packet header and
|
* 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 = min_t(unsigned int,
|
||||||
wsize,
|
wsize,
|
||||||
server->smbd_conn->max_fragmented_send_size -
|
sp->max_fragmented_send_size -
|
||||||
SMB2_READWRITE_PDU_HEADER_SIZE -
|
SMB2_READWRITE_PDU_HEADER_SIZE -
|
||||||
sizeof(struct smb2_transform_hdr));
|
sizeof(struct smb2_transform_hdr));
|
||||||
else
|
else
|
||||||
wsize = min_t(unsigned int,
|
wsize = min_t(unsigned int,
|
||||||
wsize, server->smbd_conn->max_readwrite_size);
|
wsize, sp->max_read_write_size);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
|
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);
|
rsize = min_t(unsigned int, rsize, server->max_read);
|
||||||
#ifdef CONFIG_CIFS_SMB_DIRECT
|
#ifdef CONFIG_CIFS_SMB_DIRECT
|
||||||
if (server->rdma) {
|
if (server->rdma) {
|
||||||
|
struct smbdirect_socket_parameters *sp =
|
||||||
|
&server->smbd_conn->socket.parameters;
|
||||||
|
|
||||||
if (server->sign)
|
if (server->sign)
|
||||||
/*
|
/*
|
||||||
* Account for SMB2 data transfer packet header and
|
* 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 = min_t(unsigned int,
|
||||||
rsize,
|
rsize,
|
||||||
server->smbd_conn->max_fragmented_recv_size -
|
sp->max_fragmented_recv_size -
|
||||||
SMB2_READWRITE_PDU_HEADER_SIZE -
|
SMB2_READWRITE_PDU_HEADER_SIZE -
|
||||||
sizeof(struct smb2_transform_hdr));
|
sizeof(struct smb2_transform_hdr));
|
||||||
else
|
else
|
||||||
rsize = min_t(unsigned int,
|
rsize = min_t(unsigned int,
|
||||||
rsize, server->smbd_conn->max_readwrite_size);
|
rsize, sp->max_read_write_size);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@
|
||||||
#include "smb2glob.h"
|
#include "smb2glob.h"
|
||||||
#include "cifspdu.h"
|
#include "cifspdu.h"
|
||||||
#include "cifs_spnego.h"
|
#include "cifs_spnego.h"
|
||||||
|
#include "../common/smbdirect/smbdirect.h"
|
||||||
#include "smbdirect.h"
|
#include "smbdirect.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#ifdef CONFIG_CIFS_DFS_UPCALL
|
#ifdef CONFIG_CIFS_DFS_UPCALL
|
||||||
|
|
@ -411,14 +412,23 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
|
||||||
if (!rc &&
|
if (!rc &&
|
||||||
(server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL) &&
|
(server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL) &&
|
||||||
server->ops->query_server_interfaces) {
|
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();
|
xid = get_xid();
|
||||||
rc = server->ops->query_server_interfaces(xid, tcon, false);
|
rc = server->ops->query_server_interfaces(xid, tcon, false);
|
||||||
free_xid(xid);
|
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) {
|
if (rc == -EOPNOTSUPP && ses->chan_count > 1) {
|
||||||
/*
|
/*
|
||||||
|
|
@ -438,11 +448,8 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
|
||||||
if (ses->chan_max > ses->chan_count &&
|
if (ses->chan_max > ses->chan_count &&
|
||||||
ses->iface_count &&
|
ses->iface_count &&
|
||||||
!SERVER_IS_CHAN(server)) {
|
!SERVER_IS_CHAN(server)) {
|
||||||
if (ses->chan_count == 1) {
|
if (ses->chan_count == 1)
|
||||||
cifs_server_dbg(VFS, "supports multichannel now\n");
|
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);
|
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,
|
struct TCP_Server_Info *server,
|
||||||
void **request_buf, unsigned int *total_len)
|
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,
|
return __smb2_plain_req_init(SMB2_IOCTL, tcon, server,
|
||||||
request_buf, total_len);
|
request_buf, total_len);
|
||||||
}
|
|
||||||
return smb2_plain_req_init(SMB2_IOCTL, tcon, server,
|
return smb2_plain_req_init(SMB2_IOCTL, tcon, server,
|
||||||
request_buf, total_len);
|
request_buf, total_len);
|
||||||
}
|
}
|
||||||
|
|
@ -4449,10 +4463,10 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
|
||||||
#ifdef CONFIG_CIFS_SMB_DIRECT
|
#ifdef CONFIG_CIFS_SMB_DIRECT
|
||||||
/*
|
/*
|
||||||
* If we want to do a RDMA write, fill in and append
|
* 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)) {
|
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;
|
bool need_invalidate = server->dialect == SMB30_PROT_ID;
|
||||||
|
|
||||||
rdata->mr = smbd_register_mr(server->smbd_conn, &rdata->subreq.io_iter,
|
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 =
|
req->ReadChannelInfoOffset =
|
||||||
cpu_to_le16(offsetof(struct smb2_read_req, Buffer));
|
cpu_to_le16(offsetof(struct smb2_read_req, Buffer));
|
||||||
req->ReadChannelInfoLength =
|
req->ReadChannelInfoLength =
|
||||||
cpu_to_le16(sizeof(struct smbd_buffer_descriptor_v1));
|
cpu_to_le16(sizeof(struct smbdirect_buffer_descriptor_v1));
|
||||||
v1 = (struct smbd_buffer_descriptor_v1 *) &req->Buffer[0];
|
v1 = (struct smbdirect_buffer_descriptor_v1 *) &req->Buffer[0];
|
||||||
v1->offset = cpu_to_le64(rdata->mr->mr->iova);
|
v1->offset = cpu_to_le64(rdata->mr->mr->iova);
|
||||||
v1->token = cpu_to_le32(rdata->mr->mr->rkey);
|
v1->token = cpu_to_le32(rdata->mr->mr->rkey);
|
||||||
v1->length = cpu_to_le32(rdata->mr->mr->length);
|
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
|
#ifdef CONFIG_CIFS_SMB_DIRECT
|
||||||
/*
|
/*
|
||||||
* If we want to do a server RDMA read, fill in and append
|
* 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)) {
|
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;
|
bool need_invalidate = server->dialect == SMB30_PROT_ID;
|
||||||
|
|
||||||
wdata->mr = smbd_register_mr(server->smbd_conn, &wdata->subreq.io_iter,
|
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 =
|
req->WriteChannelInfoOffset =
|
||||||
cpu_to_le16(offsetof(struct smb2_write_req, Buffer));
|
cpu_to_le16(offsetof(struct smb2_write_req, Buffer));
|
||||||
req->WriteChannelInfoLength =
|
req->WriteChannelInfoLength =
|
||||||
cpu_to_le16(sizeof(struct smbd_buffer_descriptor_v1));
|
cpu_to_le16(sizeof(struct smbdirect_buffer_descriptor_v1));
|
||||||
v1 = (struct smbd_buffer_descriptor_v1 *) &req->Buffer[0];
|
v1 = (struct smbdirect_buffer_descriptor_v1 *) &req->Buffer[0];
|
||||||
v1->offset = cpu_to_le64(wdata->mr->mr->iova);
|
v1->offset = cpu_to_le64(wdata->mr->mr->iova);
|
||||||
v1->token = cpu_to_le32(wdata->mr->mr->rkey);
|
v1->token = cpu_to_le32(wdata->mr->mr->rkey);
|
||||||
v1->length = cpu_to_le32(wdata->mr->mr->length);
|
v1->length = cpu_to_le32(wdata->mr->mr->length);
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -15,6 +15,9 @@
|
||||||
#include <rdma/rdma_cm.h>
|
#include <rdma/rdma_cm.h>
|
||||||
#include <linux/mempool.h>
|
#include <linux/mempool.h>
|
||||||
|
|
||||||
|
#include "../common/smbdirect/smbdirect.h"
|
||||||
|
#include "../common/smbdirect/smbdirect_socket.h"
|
||||||
|
|
||||||
extern int rdma_readwrite_threshold;
|
extern int rdma_readwrite_threshold;
|
||||||
extern int smbd_max_frmr_depth;
|
extern int smbd_max_frmr_depth;
|
||||||
extern int smbd_keep_alive_interval;
|
extern int smbd_keep_alive_interval;
|
||||||
|
|
@ -50,14 +53,8 @@ enum smbd_connection_status {
|
||||||
* 5. mempools for allocating packets
|
* 5. mempools for allocating packets
|
||||||
*/
|
*/
|
||||||
struct smbd_connection {
|
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;
|
int ri_rc;
|
||||||
struct completion ri_done;
|
struct completion ri_done;
|
||||||
wait_queue_head_t conn_wait;
|
wait_queue_head_t conn_wait;
|
||||||
|
|
@ -72,15 +69,7 @@ struct smbd_connection {
|
||||||
spinlock_t lock_new_credits_offered;
|
spinlock_t lock_new_credits_offered;
|
||||||
int new_credits_offered;
|
int new_credits_offered;
|
||||||
|
|
||||||
/* Connection parameters defined in [MS-SMBD] 3.1.1.1 */
|
/* dynamic 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;
|
|
||||||
enum keep_alive_status keep_alive_requested;
|
enum keep_alive_status keep_alive_requested;
|
||||||
int protocol;
|
int protocol;
|
||||||
atomic_t send_credits;
|
atomic_t send_credits;
|
||||||
|
|
@ -177,54 +166,6 @@ enum smbd_message_type {
|
||||||
SMBD_TRANSFER_DATA,
|
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 */
|
/* Maximum number of SGEs used by smbdirect.c in any send work request */
|
||||||
#define SMBDIRECT_MAX_SEND_SGE 6
|
#define SMBDIRECT_MAX_SEND_SGE 6
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1018,14 +1018,16 @@ struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses)
|
||||||
uint index = 0;
|
uint index = 0;
|
||||||
unsigned int min_in_flight = UINT_MAX, max_in_flight = 0;
|
unsigned int min_in_flight = UINT_MAX, max_in_flight = 0;
|
||||||
struct TCP_Server_Info *server = NULL;
|
struct TCP_Server_Info *server = NULL;
|
||||||
int i;
|
int i, start, cur;
|
||||||
|
|
||||||
if (!ses)
|
if (!ses)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
spin_lock(&ses->chan_lock);
|
spin_lock(&ses->chan_lock);
|
||||||
|
start = atomic_inc_return(&ses->chan_seq);
|
||||||
for (i = 0; i < ses->chan_count; i++) {
|
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)
|
if (!server || server->terminate)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
@ -1042,17 +1044,15 @@ struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses)
|
||||||
*/
|
*/
|
||||||
if (server->in_flight < min_in_flight) {
|
if (server->in_flight < min_in_flight) {
|
||||||
min_in_flight = server->in_flight;
|
min_in_flight = server->in_flight;
|
||||||
index = i;
|
index = cur;
|
||||||
}
|
}
|
||||||
if (server->in_flight > max_in_flight)
|
if (server->in_flight > max_in_flight)
|
||||||
max_in_flight = server->in_flight;
|
max_in_flight = server->in_flight;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if all channels are equally loaded, fall back to round-robin */
|
/* if all channels are equally loaded, fall back to round-robin */
|
||||||
if (min_in_flight == max_in_flight) {
|
if (min_in_flight == max_in_flight)
|
||||||
index = (uint)atomic_inc_return(&ses->chan_seq);
|
index = (uint)start % ses->chan_count;
|
||||||
index %= ses->chan_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
server = ses->chans[index].server;
|
server = ses->chans[index].server;
|
||||||
spin_unlock(&ses->chan_lock);
|
spin_unlock(&ses->chan_lock);
|
||||||
|
|
|
||||||
|
|
@ -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__ */
|
||||||
|
|
@ -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__ */
|
||||||
|
|
@ -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__ */
|
||||||
Loading…
Reference in New Issue