Commit 017d1701 authored by Stefan Metzmacher's avatar Stefan Metzmacher Committed by Steve French

smb/client: fix rdma usage in smb2_async_writev()

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"
(d08089f6).

Cc: stable@vger.kernel.org
Fixes: d08089f6 ("cifs: Change the I/O paths to use an iterator rather than a page list")
Reviewed-by: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarStefan Metzmacher <metze@samba.org>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent b608e2c3
...@@ -4913,6 +4913,13 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) ...@@ -4913,6 +4913,13 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
if (rc) if (rc)
goto out; 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)) if (smb3_encryption_required(tcon))
flags |= CIFS_TRANSFORM_REQ; flags |= CIFS_TRANSFORM_REQ;
...@@ -4924,6 +4931,7 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) ...@@ -4924,6 +4931,7 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
req->WriteChannelInfoOffset = 0; req->WriteChannelInfoOffset = 0;
req->WriteChannelInfoLength = 0; req->WriteChannelInfoLength = 0;
req->Channel = SMB2_CHANNEL_NONE; req->Channel = SMB2_CHANNEL_NONE;
req->Length = cpu_to_le32(io_parms->length);
req->Offset = cpu_to_le64(io_parms->offset); req->Offset = cpu_to_le64(io_parms->offset);
req->DataOffset = cpu_to_le16( req->DataOffset = cpu_to_le16(
offsetof(struct smb2_write_req, Buffer)); offsetof(struct smb2_write_req, Buffer));
...@@ -4943,7 +4951,6 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) ...@@ -4943,7 +4951,6 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
*/ */
if (smb3_use_rdma_offload(io_parms)) { if (smb3_use_rdma_offload(io_parms)) {
struct smbd_buffer_descriptor_v1 *v1; 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; 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,
...@@ -4952,9 +4959,10 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) ...@@ -4952,9 +4959,10 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
rc = -EAGAIN; rc = -EAGAIN;
goto async_writev_out; goto async_writev_out;
} }
/* For RDMA read, I/O size is in RemainingBytes not in Length */
req->RemainingBytes = req->Length;
req->Length = 0; req->Length = 0;
req->DataOffset = 0; req->DataOffset = 0;
req->RemainingBytes = cpu_to_le32(data_size);
req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE; req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE;
if (need_invalidate) if (need_invalidate)
req->Channel = SMB2_CHANNEL_RDMA_V1; req->Channel = SMB2_CHANNEL_RDMA_V1;
...@@ -4966,30 +4974,22 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) ...@@ -4966,30 +4974,22 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
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);
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 #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)) if (test_bit(NETFS_SREQ_RETRYING, &wdata->subreq.flags))
smb2_set_replay(server, &rqst); 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 cifs_dbg(FYI, "async write at %llu %u bytes iter=%zx\n",
/* For RDMA read, I/O size is in RemainingBytes not in Length */ io_parms->offset, io_parms->length, iov_iter_count(&wdata->subreq.io_iter));
if (!wdata->mr)
req->Length = cpu_to_le32(io_parms->length);
#else
req->Length = cpu_to_le32(io_parms->length);
#endif
if (wdata->credits.value > 0) { if (wdata->credits.value > 0) {
shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->subreq.len, shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->subreq.len,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment