]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
smb/client: fix rdma usage in smb2_async_writev()
authorStefan Metzmacher <metze@samba.org>
Wed, 21 Aug 2024 14:31:39 +0000 (16:31 +0200)
committerSteve French <stfrench@microsoft.com>
Sun, 25 Aug 2024 14:06:25 +0000 (09:06 -0500)
rqst.rq_iter needs to be truncated otherwise we'll
also send the bytes into the stream socket...

This is the logic behind rqst.rq_npages = 0, which was removed in
"cifs: Change the I/O paths to use an iterator rather than a page list"
(d08089f649a0cfb2099c8551ac47eef0cc23fdf2).

Cc: stable@vger.kernel.org
Fixes: d08089f649a0 ("cifs: Change the I/O paths to use an iterator rather than a page list")
Reviewed-by: David Howells <dhowells@redhat.com>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/client/smb2pdu.c

index 63a2541d4a052434d80f82c6f0c96563b00a63e8..2d7e6c42cf182b9d5b5c4f5b8f5bac7914cce14c 100644 (file)
@@ -4913,6 +4913,13 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
        if (rc)
                goto out;
 
+       rqst.rq_iov = iov;
+       rqst.rq_iter = wdata->subreq.io_iter;
+
+       rqst.rq_iov[0].iov_len = total_len - 1;
+       rqst.rq_iov[0].iov_base = (char *)req;
+       rqst.rq_nvec += 1;
+
        if (smb3_encryption_required(tcon))
                flags |= CIFS_TRANSFORM_REQ;
 
@@ -4924,6 +4931,7 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
        req->WriteChannelInfoOffset = 0;
        req->WriteChannelInfoLength = 0;
        req->Channel = SMB2_CHANNEL_NONE;
+       req->Length = cpu_to_le32(io_parms->length);
        req->Offset = cpu_to_le64(io_parms->offset);
        req->DataOffset = cpu_to_le16(
                                offsetof(struct smb2_write_req, Buffer));
@@ -4943,7 +4951,6 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
         */
        if (smb3_use_rdma_offload(io_parms)) {
                struct smbd_buffer_descriptor_v1 *v1;
-               size_t data_size = iov_iter_count(&wdata->subreq.io_iter);
                bool need_invalidate = server->dialect == SMB30_PROT_ID;
 
                wdata->mr = smbd_register_mr(server->smbd_conn, &wdata->subreq.io_iter,
@@ -4952,9 +4959,10 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
                        rc = -EAGAIN;
                        goto async_writev_out;
                }
+               /* For RDMA read, I/O size is in RemainingBytes not in Length */
+               req->RemainingBytes = req->Length;
                req->Length = 0;
                req->DataOffset = 0;
-               req->RemainingBytes = cpu_to_le32(data_size);
                req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE;
                if (need_invalidate)
                        req->Channel = SMB2_CHANNEL_RDMA_V1;
@@ -4966,30 +4974,22 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
                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);
+
+               rqst.rq_iov[0].iov_len += sizeof(*v1);
+
+               /*
+                * We keep wdata->subreq.io_iter,
+                * but we have to truncate rqst.rq_iter
+                */
+               iov_iter_truncate(&rqst.rq_iter, 0);
        }
 #endif
-       iov[0].iov_len = total_len - 1;
-       iov[0].iov_base = (char *)req;
 
-       rqst.rq_iov = iov;
-       rqst.rq_nvec = 1;
-       rqst.rq_iter = wdata->subreq.io_iter;
        if (test_bit(NETFS_SREQ_RETRYING, &wdata->subreq.flags))
                smb2_set_replay(server, &rqst);
-#ifdef CONFIG_CIFS_SMB_DIRECT
-       if (wdata->mr)
-               iov[0].iov_len += sizeof(struct smbd_buffer_descriptor_v1);
-#endif
-       cifs_dbg(FYI, "async write at %llu %u bytes iter=%zx\n",
-                io_parms->offset, io_parms->length, iov_iter_count(&rqst.rq_iter));
 
-#ifdef CONFIG_CIFS_SMB_DIRECT
-       /* For RDMA read, I/O size is in RemainingBytes not in Length */
-       if (!wdata->mr)
-               req->Length = cpu_to_le32(io_parms->length);
-#else
-       req->Length = cpu_to_le32(io_parms->length);
-#endif
+       cifs_dbg(FYI, "async write at %llu %u bytes iter=%zx\n",
+                io_parms->offset, io_parms->length, iov_iter_count(&wdata->subreq.io_iter));
 
        if (wdata->credits.value > 0) {
                shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->subreq.len,