From: David Howells <dhowells@redhat.com>
To: Steve French <sfrench@samba.org>
Cc: David Howells <dhowells@redhat.com>,
Paulo Alcantara <pc@manguebit.org>,
Shyam Prasad N <sprasad@microsoft.com>,
Tom Talpey <tom@talpey.com>, Stefan Metzmacher <metze@samba.org>,
Mina Almasry <almasrymina@google.com>,
linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org,
netfs@lists.linux.dev, linux-fsdevel@vger.kernel.org
Subject: [RFC PATCH 31/36] cifs: Convert SMB2 Read request
Date: Tue, 19 May 2026 11:21:49 +0100 [thread overview]
Message-ID: <20260519102158.592165-32-dhowells@redhat.com> (raw)
In-Reply-To: <20260519102158.592165-1-dhowells@redhat.com>
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Steve French <sfrench@samba.org>
cc: Paulo Alcantara <pc@manguebit.org>
cc: Shyam Prasad N <sprasad@microsoft.com>
cc: Tom Talpey <tom@talpey.com>
cc: linux-cifs@vger.kernel.org
cc: netfs@lists.linux.dev
cc: linux-fsdevel@vger.kernel.org
---
fs/smb/client/cifsglob.h | 1 -
fs/smb/client/smb2pdu.c | 232 +++++++++++++++++++--------------------
2 files changed, 113 insertions(+), 120 deletions(-)
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index 9aa9eb72ec6b..ed7311637d81 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -1455,7 +1455,6 @@ struct cifs_io_subrequest {
bool replay;
unsigned int retries; /* number of retries so far */
unsigned int cur_sleep; /* time to sleep before replay */
- struct kvec iov[2];
struct TCP_Server_Info *server;
#ifdef CONFIG_CIFS_SMB_DIRECT
struct smbdirect_mr_io *mr;
diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
index f0b39c77f8ae..b2140cb1662e 100644
--- a/fs/smb/client/smb2pdu.c
+++ b/fs/smb/client/smb2pdu.c
@@ -4757,48 +4757,62 @@ static inline bool smb3_use_rdma_offload(struct cifs_io_parms *io_parms)
* To form a chain of read requests, any read requests after the first should
* have the end_of_chain boolean set to true.
*/
-static int
-smb2_new_read_req(void **buf, unsigned int *total_len,
- struct cifs_io_parms *io_parms, struct cifs_io_subrequest *rdata,
- unsigned int remaining_bytes, int request_type)
+static struct smb_message *
+smb2_new_read_req(struct cifs_io_parms *io_parms, struct cifs_io_subrequest *rdata,
+ unsigned int remaining_bytes, int request_type)
{
- int rc = -EACCES;
- struct smb2_read_req *req = NULL;
- struct smb2_hdr *shdr;
struct TCP_Server_Info *server = io_parms->server;
+ struct smb2_read_req *req;
+ struct smb_message *smb;
+ struct smb2_hdr *shdr;
+ size_t proto_len = sizeof(*req) + 1;
- rc = smb2_plain_req_init(SMB2_READ, io_parms->tcon, server,
- (void **) &req, total_len);
- if (rc)
- return rc;
+ if (!server)
+ return ERR_PTR(-ECONNABORTED);
- if (server == NULL)
- return -ECONNABORTED;
+#ifdef CONFIG_CIFS_SMB_DIRECT
+ bool rdma_offload = rdata && smb3_use_rdma_offload(io_parms);
+
+ if (rdma_offload)
+ proto_len += sizeof(struct smbdirect_buffer_descriptor_v1);
+#endif
+ smb = smb2_create_request(SMB2_READ, server, io_parms->tcon,
+ sizeof(*req), proto_len, 0,
+ SMB2_REQ_DYNAMIC);
+ if (!smb)
+ return ERR_PTR(-ENOMEM);
+ req = smb->request;
shdr = &req->hdr;
- shdr->Id.SyncId.ProcessId = cpu_to_le32(io_parms->pid);
- req->PersistentFileId = io_parms->persistent_fid;
- req->VolatileFileId = io_parms->volatile_fid;
- req->ReadChannelInfoOffset = 0; /* reserved */
- req->ReadChannelInfoLength = 0; /* reserved */
- req->Channel = 0; /* reserved */
- req->MinimumCount = 0;
- req->Length = cpu_to_le32(io_parms->length);
- req->Offset = cpu_to_le64(io_parms->offset);
+ if (rdata) {
+ smb->subreq = rdata;
+ smb->credits = rdata->credits;
+ }
- trace_smb3_read_enter(rdata ? rdata->rreq->debug_id : 0,
- rdata ? rdata->subreq.debug_index : 0,
+ shdr->Id.SyncId.ProcessId = cpu_to_le32(io_parms->pid);
+ req->PersistentFileId = io_parms->persistent_fid;
+ req->VolatileFileId = io_parms->volatile_fid;
+ req->ReadChannelInfoOffset = 0; /* reserved */
+ req->ReadChannelInfoLength = 0; /* reserved */
+ req->Channel = 0; /* reserved */
+ req->MinimumCount = 0;
+ req->Length = cpu_to_le32(io_parms->length);
+ req->Offset = cpu_to_le64(io_parms->offset);
+
+ trace_smb3_read_enter(smb->credits.rreq_debug_id,
+ smb->credits.rreq_debug_index,
rdata ? rdata->xid : 0,
io_parms->persistent_fid,
io_parms->tcon->tid, io_parms->tcon->ses->Suid,
io_parms->offset, io_parms->length);
+
#ifdef CONFIG_CIFS_SMB_DIRECT
/*
* If we want to do a RDMA write, fill in and append
* smbdirect_buffer_descriptor_v1 to the end of read request
*/
- if (rdata && smb3_use_rdma_offload(io_parms)) {
+ if (rdma_offload) {
struct smbdirect_buffer_descriptor_v1 *v1;
struct iov_iter iter;
bool need_invalidate = server->dialect == SMB30_PROT_ID;
@@ -4808,8 +4822,10 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
rdata->subreq.content.offset, rdata->subreq.len);
rdata->mr = smbd_register_mr(server->smbd_conn, &iter,
true, need_invalidate);
- if (!rdata->mr)
- return -EAGAIN;
+ if (!rdata->mr) {
+ smb_put_messages(smb);
+ return ERR_PTR(-EAGAIN);
+ }
req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE;
if (need_invalidate)
@@ -4820,36 +4836,28 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
cpu_to_le16(sizeof(struct smbdirect_buffer_descriptor_v1));
v1 = (struct smbdirect_buffer_descriptor_v1 *) &req->Buffer[0];
smbd_mr_fill_buffer_descriptor(rdata->mr, v1);
-
- *total_len += sizeof(*v1);
}
#endif
- if (request_type & CHAINED_REQUEST) {
- if (!(request_type & END_OF_CHAIN)) {
- /* next 8-byte aligned request */
- *total_len = ALIGN8(*total_len);
- shdr->NextCommand = cpu_to_le32(*total_len);
- } else /* END_OF_CHAIN */
- shdr->NextCommand = 0;
- if (request_type & RELATED_REQUEST) {
- shdr->Flags |= SMB2_FLAGS_RELATED_OPERATIONS;
- /*
- * Related requests use info from previous read request
- * in chain.
- */
- shdr->SessionId = cpu_to_le64(0xFFFFFFFFFFFFFFFF);
- shdr->Id.SyncId.TreeId = cpu_to_le32(0xFFFFFFFF);
- req->PersistentFileId = (u64)-1;
- req->VolatileFileId = (u64)-1;
- }
+
+ if ((request_type & CHAINED_REQUEST) &&
+ (request_type & RELATED_REQUEST)) {
+ shdr->Flags |= SMB2_FLAGS_RELATED_OPERATIONS;
+ /*
+ * Related requests use info from previous read request in
+ * chain.
+ */
+ shdr->SessionId = cpu_to_le64(0xFFFFFFFFFFFFFFFF);
+ shdr->Id.SyncId.TreeId = cpu_to_le32(0xFFFFFFFF);
+ req->PersistentFileId = (u64)-1;
+ req->VolatileFileId = (u64)-1;
}
+
if (remaining_bytes > io_parms->length)
req->RemainingBytes = cpu_to_le32(remaining_bytes);
else
req->RemainingBytes = 0;
- *buf = req;
- return rc;
+ return smb;
}
static void
@@ -5004,13 +5012,12 @@ smb2_async_readv(struct cifs_io_subrequest *rdata)
{
struct netfs_io_subrequest *subreq = &rdata->subreq;
struct TCP_Server_Info *server;
+ struct smb2_read_req *req;
struct smb_message *smb;
- struct smb2_hdr *shdr;
struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink);
- unsigned int total_len;
- void *buf;
+ struct smb2_hdr *shdr;
int credit_request;
- int rc, flags = 0;
+ int rc;
cifs_dbg(FYI, "%s: offset=%llu bytes=%zu\n",
__func__, subreq->start, subreq->len);
@@ -5029,30 +5036,19 @@ smb2_async_readv(struct cifs_io_subrequest *rdata)
.pid = rdata->req->pid,
};
- smb = smb_message_alloc(smb2_command_trace_read, GFP_NOFS);
- if (!smb) {
- rc = -ENOMEM;
- goto out;
- }
-
- rc = smb2_new_read_req(&buf, &total_len, &io_parms, rdata, 0, 0);
- if (rc) {
- mempool_free(smb, &smb_message_pool);
+ smb = smb2_new_read_req(&io_parms, rdata, 0, 0);
+ if (IS_ERR(smb)) {
+ rc = PTR_ERR(smb);
goto out;
}
+ req = smb->request;
+ shdr = &req->hdr;
if (smb3_encryption_required(io_parms.tcon))
- flags |= CIFS_TRANSFORM_REQ;
+ smb->sr_flags |= CIFS_TRANSFORM_REQ;
- rdata->iov[0].iov_base = buf;
- rdata->iov[0].iov_len = total_len;
rdata->result = 0;
- smb->rqst.rq_iov = rdata->iov;
- smb->rqst.rq_nvec = 1;
- smb->command = SMB2_READ;
- smb->request = buf;
- smb->total_len = total_len;
smb->callback = smb2_readv_callback;
smb->subreq = rdata;
smb->copy_to_bufs = true;
@@ -5061,19 +5057,19 @@ smb2_async_readv(struct cifs_io_subrequest *rdata)
rdata->subreq.content.bvecq, rdata->subreq.content.slot,
rdata->subreq.content.offset, rdata->subreq.len);
- shdr = (struct smb2_hdr *)smb->request;
-
if (rdata->replay) {
/* Back-off before retry */
if (rdata->cur_sleep)
msleep(rdata->cur_sleep);
- smb2_set_replay(server, &smb->rqst);
+ smb2_set_replay_smb(server, smb);
}
if (rdata->credits.value > 0) {
- shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(io_parms.length,
- SMB2_MAX_BUFFER_SIZE));
- credit_request = le16_to_cpu(shdr->CreditCharge) + 8;
+ unsigned int credit_charge =
+ DIV_ROUND_UP(io_parms.length, SMB2_MAX_BUFFER_SIZE);
+
+ shdr->CreditCharge = cpu_to_le16(credit_charge);
+ credit_request = credit_charge + 8;
if (server->credits >= server->max_credits)
shdr->CreditRequest = cpu_to_le16(0);
else
@@ -5085,10 +5081,14 @@ smb2_async_readv(struct cifs_io_subrequest *rdata)
if (rc)
goto async_readv_out;
- flags |= CIFS_HAS_CREDITS;
+ smb->credits.value = rdata->credits.value;
+ smb->sr_flags |= CIFS_HAS_CREDITS;
}
- rc = cifs_call_async(server, smb, flags, &rdata->credits);
+ iov_iter_bvec_queue(&smb->req_iter, ITER_SOURCE, &smb->bvecq, 0, 0,
+ smb->data_offset);
+
+ rc = cifs_call_async(server, smb, smb->sr_flags, &rdata->credits);
if (rc) {
cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE);
trace_smb3_read_err(rdata->rreq->debug_id,
@@ -5101,8 +5101,7 @@ smb2_async_readv(struct cifs_io_subrequest *rdata)
}
async_readv_out:
- cifs_small_buf_release(buf);
-
+ smb_put_messages(smb);
out:
/* if the send error is retryable, let netfs know about it */
if (is_replayable_error(rc) &&
@@ -5113,7 +5112,6 @@ smb2_async_readv(struct cifs_io_subrequest *rdata)
__set_bit(NETFS_SREQ_NEED_RETRY, &rdata->subreq.flags);
}
- smb_put_messages(smb);
return rc;
}
@@ -5121,63 +5119,56 @@ int
SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
unsigned int *nbytes, char **buf, int *buf_type)
{
- struct smb_rqst rqst;
- int resp_buftype, rc;
- struct smb2_read_req *req = NULL;
struct smb2_read_rsp *rsp = NULL;
- struct kvec iov[1];
- struct kvec rsp_iov;
- unsigned int total_len;
- int flags = CIFS_LOG_ERROR;
+ struct smb_message *smb;
struct cifs_ses *ses = io_parms->tcon->ses;
+ int rc;
if (!io_parms->server)
io_parms->server = cifs_pick_channel(io_parms->tcon->ses);
*nbytes = 0;
- rc = smb2_new_read_req((void **)&req, &total_len, io_parms, NULL, 0, 0);
- if (rc)
- return rc;
+ smb = smb2_new_read_req(io_parms, NULL, 0, 0);
+ if (IS_ERR(smb))
+ return PTR_ERR(smb);
+ smb->sr_flags = CIFS_LOG_ERROR;
if (smb3_encryption_required(io_parms->tcon))
- flags |= CIFS_TRANSFORM_REQ;
+ smb->sr_flags |= CIFS_TRANSFORM_REQ;
- iov[0].iov_base = (char *)req;
- iov[0].iov_len = total_len;
+ iov_iter_bvec_queue(&smb->req_iter, ITER_SOURCE, &smb->bvecq, 0, 0,
+ smb->data_offset);
- memset(&rqst, 0, sizeof(struct smb_rqst));
- rqst.rq_iov = iov;
- rqst.rq_nvec = 1;
+ rc = smb_send_recv_messages(xid, ses, io_parms->server, smb, smb->sr_flags);
+ smb_clear_request(smb);
- rc = cifs_send_recv(xid, ses, io_parms->server,
- &rqst, &resp_buftype, flags, &rsp_iov);
- rsp = (struct smb2_read_rsp *)rsp_iov.iov_base;
+ rsp = (struct smb2_read_rsp *)smb->response;
if (rc) {
if (rc != -ENODATA) {
cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE);
cifs_dbg(VFS, "Send error in read = %d\n", rc);
trace_smb3_read_err(0, 0, xid,
- req->PersistentFileId,
+ io_parms->persistent_fid,
io_parms->tcon->tid, ses->Suid,
io_parms->offset, io_parms->length,
rc);
- } else
+ } else {
trace_smb3_read_done(0, 0, xid,
- req->PersistentFileId, io_parms->tcon->tid,
+ io_parms->persistent_fid,
+ io_parms->tcon->tid,
ses->Suid, io_parms->offset, 0);
- free_rsp_buf(resp_buftype, rsp_iov.iov_base);
- cifs_small_buf_release(req);
- return rc == -ENODATA ? 0 : rc;
- } else
- trace_smb3_read_done(0, 0, xid,
- req->PersistentFileId,
- io_parms->tcon->tid, ses->Suid,
- io_parms->offset, io_parms->length);
+ rc = 0;
+ }
+ goto out;
+ }
- cifs_small_buf_release(req);
+ trace_smb3_read_done(0, 0, xid,
+ io_parms->persistent_fid,
+ io_parms->tcon->tid, ses->Suid,
+ io_parms->offset, io_parms->length);
- *nbytes = le32_to_cpu(rsp->DataLength);
+ *nbytes = smb->resp_data_len;
if ((*nbytes > CIFS_MAX_MSGSIZE) ||
(*nbytes > io_parms->length)) {
cifs_dbg(FYI, "bad length %d for count %d\n",
@@ -5188,15 +5179,18 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
}
if (*buf) {
- memcpy(*buf, (char *)rsp + rsp->DataOffset, *nbytes);
- free_rsp_buf(resp_buftype, rsp_iov.iov_base);
- } else if (resp_buftype != CIFS_NO_BUFFER) {
- *buf = rsp_iov.iov_base;
- if (resp_buftype == CIFS_SMALL_BUFFER)
+ memcpy(*buf, (char *)rsp + smb->resp_data_offset, *nbytes);
+ } else if (smb->response) {
+ *buf = smb->response;
+ smb->response = NULL;
+ if (!smb->large_buf)
*buf_type = CIFS_SMALL_BUFFER;
- else if (resp_buftype == CIFS_LARGE_BUFFER)
+ else
*buf_type = CIFS_LARGE_BUFFER;
}
+
+out:
+ smb_put_messages(smb);
return rc;
}
next prev parent reply other threads:[~2026-05-19 10:24 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20260519102158.592165-1-dhowells@redhat.com>
2026-05-19 10:21 ` [RFC PATCH 01/36] net: Perform special handling for a splice from a bvecq David Howells
2026-05-19 10:21 ` [RFC PATCH 02/36] netfs: Add a facility to splice TCP receive buffers into " David Howells
2026-05-19 10:21 ` [RFC PATCH 03/36] netfs: Add some TCP receive queue helpers David Howells
2026-05-19 10:21 ` [RFC PATCH 04/36] cifs, nls: Provide unicode size determination func David Howells
2026-05-19 10:21 ` [RFC PATCH 05/36] cifs: Introduce an ALIGN8() macro David Howells
2026-05-19 10:21 ` [RFC PATCH 06/36] cifs: Rename mid_q_entry to smb_message David Howells
2026-05-19 10:21 ` [RFC PATCH 07/36] cifs: Add "Has dynamic part" flag form SMB2/3 StructureSize LSB David Howells
2026-05-19 10:21 ` [RFC PATCH 09/36] cifs: Institute message managing struct David Howells
2026-05-19 10:21 ` [RFC PATCH 10/36] cifs: Split crypt_message() into encrypt and decrypt variants David Howells
2026-05-19 10:21 ` [RFC PATCH 11/36] cifs: Add new AEAD alloc and setup routines that draw from an iterator David Howells
2026-05-19 10:21 ` [RFC PATCH 12/36] cifs: [WIP] Rewrite base Rx to put data off the socket into a bvecq David Howells
2026-05-19 10:21 ` [RFC PATCH 13/36] cifs: Remove validate_t2() David Howells
2026-05-19 10:21 ` [RFC PATCH 14/36] cifs: Remove cifs_io_subrequest::got_bytes David Howells
2026-05-19 10:21 ` [RFC PATCH 15/36] cifs: Pass smb_message to cifs_verify_signature() David Howells
2026-05-19 10:21 ` [RFC PATCH 16/36] cifs: Rewrite base TCP transmission David Howells
2026-05-19 10:36 ` Stefan Metzmacher
2026-05-19 10:21 ` [RFC PATCH 17/36] cifs: Don't use corking David Howells
2026-05-19 10:21 ` [RFC PATCH 20/36] cifs: Pass smb_message structs down into the transport layer David Howells
2026-05-19 10:21 ` [RFC PATCH 21/36] cifs: Add a tracepoint to trace the smb_message refcount David Howells
2026-05-19 10:21 ` [RFC PATCH 22/36] cifs: Trace smb1/2_copy_to_prepped_buffers() David Howells
2026-05-19 10:21 ` [RFC PATCH 23/36] cifs: Clean up mid->callback_data and kill off mid->creator David Howells
2026-05-19 10:21 ` [RFC PATCH 24/36] cifs: Add netmem allocation functions David Howells
2026-05-19 10:21 ` [RFC PATCH 25/36] cifs: Add more pieces to smb_message David Howells
2026-05-19 10:21 ` [RFC PATCH 26/36] cifs: Convert SMB2 Negotiate Protocol request David Howells
2026-05-19 10:21 ` [RFC PATCH 27/36] cifs: Convert SMB2 Session Setup request David Howells
2026-05-19 10:21 ` [RFC PATCH 28/36] cifs: Convert SMB2 Logoff request David Howells
2026-05-19 10:21 ` [RFC PATCH 29/36] cifs: Convert SMB2 Tree Connect request David Howells
2026-05-19 10:21 ` [RFC PATCH 30/36] cifs: Convert SMB2 Tree Disconnect request David Howells
2026-05-19 10:21 ` David Howells [this message]
2026-05-19 10:21 ` [RFC PATCH 32/36] cifs: Convert SMB2 Write request David Howells
2026-05-19 10:21 ` [RFC PATCH 33/36] cifs: [WIP] Don't copy new-style smb_messages to a set of pages David Howells
2026-05-19 10:21 ` [RFC PATCH 34/36] cifs: [WIP] Rearrange Create request subfuncs David Howells
2026-05-19 10:21 ` [RFC PATCH 35/36] cifs: [WIP] Convert SMB2 Posix Mkdir request David Howells
2026-05-19 10:21 ` [RFC PATCH 36/36] cifs: [WIP] Convert SMB2 Open request David Howells
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260519102158.592165-32-dhowells@redhat.com \
--to=dhowells@redhat.com \
--cc=almasrymina@google.com \
--cc=linux-cifs@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=metze@samba.org \
--cc=netfs@lists.linux.dev \
--cc=pc@manguebit.org \
--cc=sfrench@samba.org \
--cc=sprasad@microsoft.com \
--cc=tom@talpey.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox