1 From 1944f6ab4967db7ad8d4db527dceae8c77de76e9 Mon Sep 17 00:00:00 2001
2 From: Stefan Metzmacher <metze@samba.org>
3 Date: Wed, 25 Jun 2025 10:16:38 +0200
4 Subject: smb: client: let smbd_post_send_iter() respect the peers max_send_size and transmit all data
6 From: Stefan Metzmacher <metze@samba.org>
8 commit 1944f6ab4967db7ad8d4db527dceae8c77de76e9 upstream.
10 We should not send smbdirect_data_transfer messages larger than
11 the negotiated max_send_size, typically 1364 bytes, which means
12 24 bytes of the smbdirect_data_transfer header + 1340 payload bytes.
14 This happened when doing an SMB2 write with more than 1340 bytes
15 (which is done inline as it's below rdma_readwrite_threshold).
17 It means the peer resets the connection.
19 When testing between cifs.ko and ksmbd.ko something like this
24 CIFS: VFS: RDMA transport re-established
25 siw: got TERMINATE. layer 1, type 2, code 2
26 siw: got TERMINATE. layer 1, type 2, code 2
27 siw: got TERMINATE. layer 1, type 2, code 2
28 siw: got TERMINATE. layer 1, type 2, code 2
29 siw: got TERMINATE. layer 1, type 2, code 2
30 siw: got TERMINATE. layer 1, type 2, code 2
31 siw: got TERMINATE. layer 1, type 2, code 2
32 siw: got TERMINATE. layer 1, type 2, code 2
33 siw: got TERMINATE. layer 1, type 2, code 2
34 CIFS: VFS: \\carina Send error in SessSetup = -11
35 smb2_reconnect: 12 callbacks suppressed
36 CIFS: VFS: reconnect tcon failed rc = -11
37 CIFS: VFS: reconnect tcon failed rc = -11
38 CIFS: VFS: reconnect tcon failed rc = -11
39 CIFS: VFS: SMB: Zero rsize calculated, using minimum value 65536
43 CIFS: VFS: RDMA transport re-established
44 siw: got TERMINATE. layer 1, type 2, code 2
45 CIFS: VFS: smbd_recv:1894 disconnected
46 siw: got TERMINATE. layer 1, type 2, code 2
48 The ksmbd dmesg is showing things like:
50 smb_direct: Recv error. status='local length error (1)' opcode=128
51 smb_direct: disconnected
52 smb_direct: Recv error. status='local length error (1)' opcode=128
53 ksmbd: smb_direct: disconnected
54 ksmbd: sock_read failed: -107
56 As smbd_post_send_iter() limits the transmitted number of bytes
57 we need loop over it in order to transmit the whole iter.
59 Reviewed-by: David Howells <dhowells@redhat.com>
60 Tested-by: David Howells <dhowells@redhat.com>
61 Tested-by: Meetakshi Setiya <msetiya@microsoft.com>
62 Cc: Tom Talpey <tom@talpey.com>
63 Cc: linux-cifs@vger.kernel.org
64 Cc: <stable+noautosel@kernel.org> # sp->max_send_size should be info->max_send_size in backports
65 Fixes: 3d78fe73fa12 ("cifs: Build the RDMA SGE list directly from an iterator")
66 Signed-off-by: Stefan Metzmacher <metze@samba.org>
67 Signed-off-by: Steve French <stfrench@microsoft.com>
68 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
70 fs/smb/client/smbdirect.c | 31 +++++++++++++++++++++++++++----
71 1 file changed, 27 insertions(+), 4 deletions(-)
73 --- a/fs/smb/client/smbdirect.c
74 +++ b/fs/smb/client/smbdirect.c
75 @@ -907,8 +907,10 @@ wait_send_queue:
76 .local_dma_lkey = sc->ib.pd->local_dma_lkey,
77 .direction = DMA_TO_DEVICE,
79 + size_t payload_len = umin(*_remaining_data_length,
80 + sp->max_send_size - sizeof(*packet));
82 - rc = smb_extract_iter_to_rdma(iter, *_remaining_data_length,
83 + rc = smb_extract_iter_to_rdma(iter, payload_len,
87 @@ -1013,6 +1015,27 @@ static int smbd_post_send_empty(struct s
88 return smbd_post_send_iter(info, NULL, &remaining_data_length);
91 +static int smbd_post_send_full_iter(struct smbd_connection *info,
92 + struct iov_iter *iter,
93 + int *_remaining_data_length)
98 + * smbd_post_send_iter() respects the
99 + * negotiated max_send_size, so we need to
100 + * loop until the full iter is posted
103 + while (iov_iter_count(iter) > 0) {
104 + rc = smbd_post_send_iter(info, iter, _remaining_data_length);
113 * Post a receive request to the transport
114 * The remote peer can only send data when a receive request is posted
115 @@ -1962,14 +1985,14 @@ int smbd_send(struct TCP_Server_Info *se
116 klen += rqst->rq_iov[i].iov_len;
117 iov_iter_kvec(&iter, ITER_SOURCE, rqst->rq_iov, rqst->rq_nvec, klen);
119 - rc = smbd_post_send_iter(info, &iter, &remaining_data_length);
120 + rc = smbd_post_send_full_iter(info, &iter, &remaining_data_length);
124 if (iov_iter_count(&rqst->rq_iter) > 0) {
125 /* And then the data pages if there are any */
126 - rc = smbd_post_send_iter(info, &rqst->rq_iter,
127 - &remaining_data_length);
128 + rc = smbd_post_send_full_iter(info, &rqst->rq_iter,
129 + &remaining_data_length);