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 09/36] cifs: Institute message managing struct
Date: Tue, 19 May 2026 11:21:27 +0100 [thread overview]
Message-ID: <20260519102158.592165-10-dhowells@redhat.com> (raw)
In-Reply-To: <20260519102158.592165-1-dhowells@redhat.com>
Turn the smb_message struct into a message handling struct to aid in
building an SMB message, queuing them and holding the resources and
buffers. It has absorbed the mid_q_struct and now other fields are added.
The idea is that the smb_message struct will be allocated and filled in
much higher up (typically in the PDU encoding code) and passed down to the
transport.
In particular, the following fields:
(*) ->next: This is used to link together messages into compounds and then
walk through the message list.
(*) ->credits: The credit requirements for the message.
(*) ->request: Pointer to the smb_hdr struct for the request.
(*) ->command_trace: An ID of the command type for use in tracing.
(*) ->total_len: The total length of the request message, not including
rfc1002 or transform headers.
(*) ->response: Pointer to the smb_hdr struct for the response.
(*) ->rqst, ->resp_buf_type, ->resp_iov: The old request info stuff.
Functions are provided to get and put refs upon the struct and also to drop
all the refs on a compound string of structs.
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 | 104 ++++++++++++++++++++++++----------
fs/smb/client/cifsproto.h | 11 ++--
fs/smb/client/connect.c | 6 +-
fs/smb/client/smb1ops.c | 2 +-
fs/smb/client/smb1transport.c | 2 +-
fs/smb/client/smb2ops.c | 2 +-
fs/smb/client/smb2transport.c | 4 +-
fs/smb/client/transport.c | 42 +++++++++++++-
8 files changed, 127 insertions(+), 46 deletions(-)
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index a5e12a2eefdd..0f876feb0dbf 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -1701,40 +1701,82 @@ typedef void (*mid_callback_t)(struct TCP_Server_Info *srv, struct smb_message *
typedef int (*mid_handle_t)(struct TCP_Server_Info *server,
struct smb_message *smb);
-/* one of these for every pending CIFS request to the server */
+/*
+ * Definition of an SMB request message to be transmitted. These may be
+ * chained together and will automatically be turned into compound messages if
+ * they are.
+ *
+ * +-----------------------+
+ * | NetBIOS/padding |
+ * +-----------------------+ <--- smb->request + pre_offset
+ * | (Transform header) |
+ * +-----------------------+ <--- smb->request
+ * | SMB2 Header | } }
+ * +-----------------------+ } header_size }
+ * | Req/Rsp struct | } }
+ * +-----------------------+ <--- smb->request + ext_offset } protocol_size
+ * | | }
+ * | Extra protocol data | }
+ * | | }
+ * +-----------------------+ <--- smb->request + smb->data_offset
+ * | |
+ * | Data Payload | data_size
+ * | |
+ * +-----------------------+
+ *
+ *
+ * If the data is to be RDMA'd, it will be kept separate from the protocol.
+ */
struct smb_message {
- struct list_head qhead; /* mids waiting on reply from this server */
- refcount_t refcount;
- __u64 mid; /* multiplex id */
- __u16 credits; /* number of credits consumed by this mid */
- __u16 credits_received; /* number of credits from the response */
- __u32 pid; /* process id */
- __u32 sequence_number; /* for CIFS signing */
- unsigned int sr_flags; /* Flags passed to send_recv() */
- unsigned long when_alloc; /* when mid was created */
+ struct smb_message *next; /* Next message in compound */
+ struct cifs_credits credits; /* Credit requirements for this message */
+ void *request; /* Pointer to request message body */
+ refcount_t ref;
+ bool sensitive; /* Request contains sensitive data */
+ bool cancelled; /* T if cancelled */
+ unsigned int sr_flags; /* Flags passed to send_recv() */
+
+ /* Queue state */
+ struct list_head qhead; /* mids waiting on reply from this server */
+ __u64 mid; /* multiplex id */
+ __u16 credits_consumed; /* number of credits consumed by this op */
+ __u16 credits_received; /* number of credits from the response */
+ __u32 pid; /* process id */
+ __u32 sequence_number; /* for CIFS signing */
+ unsigned long when_alloc; /* when mid was created */
#ifdef CONFIG_CIFS_STATS2
- unsigned long when_sent; /* time when smb send finished */
- unsigned long when_received; /* when demux complete (taken off wire) */
+ unsigned long when_sent; /* time when smb send finished */
+ unsigned long when_received; /* when demux complete (taken off wire) */
#endif
- mid_receive_t receive; /* call receive callback */
- mid_callback_t callback; /* call completion callback */
- mid_handle_t handle; /* call handle mid callback */
- void *callback_data; /* general purpose pointer for callback */
- struct task_struct *creator;
- void *resp_buf; /* pointer to received SMB header */
- unsigned int resp_buf_size;
- u32 response_pdu_len;
- int mid_state; /* wish this were enum but can not pass to wait_event */
- int mid_rc; /* rc for MID_RC */
- __le16 command; /* smb command code */
- unsigned int optype; /* operation type */
- spinlock_t mid_lock;
- bool wait_cancelled:1; /* Cancelled while waiting for response */
- bool deleted_from_q:1; /* Whether Mid has been dequeued frem pending_mid_q */
- bool large_buf:1; /* if valid response, is pointer to large buf */
- bool multiRsp:1; /* multiple trans2 responses for one request */
- bool multiEnd:1; /* both received */
- bool decrypted:1; /* decrypted entry */
+ mid_receive_t receive; /* call receive callback */
+ mid_callback_t callback; /* call completion callback */
+ mid_handle_t handle; /* call handle mid callback */
+ void *callback_data; /* general purpose pointer for callback */
+ struct task_struct *creator;
+ void *resp_buf; /* pointer to received SMB header */
+ unsigned int resp_buf_size;
+ int mid_state; /* wish this were enum but can not pass to wait_event */
+ int mid_rc; /* rc for MID_RC */
+ unsigned int optype; /* operation type */
+ spinlock_t mid_lock;
+ bool wait_cancelled:1; /* Cancelled while waiting for response */
+ bool deleted_from_q:1; /* Mid has been dequeued from pending_mid_q */
+ bool large_buf:1; /* if valid response, is pointer to large buf */
+ bool multiRsp:1; /* multiple trans2 responses for one request */
+ bool multiEnd:1; /* both received */
+ bool decrypted:1; /* decrypted entry */
+
+ /* Request details */
+ u8 command_trace; /* enum smb_command_trace - Command trace ID */
+ __le16 command; /* smb command code */
+ s16 pre_offset; /* Offset of pre-headers from ->body (negative) */
+ unsigned int total_len; /* Total length of from hdr_offset onwards */
+ /* Response */
+ u32 response_pdu_len; /* Size of response PDU */
+ /* Compat with old code */
+ struct smb_rqst rqst;
+ int *resp_buf_type;
+ struct kvec *resp_iov;
};
struct close_cancelled_open {
diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
index f88ae04af85d..9c60fffcf53d 100644
--- a/fs/smb/client/cifsproto.h
+++ b/fs/smb/client/cifsproto.h
@@ -81,6 +81,10 @@ char *cifs_build_path_to_root(struct smb3_fs_context *ctx,
struct cifs_tcon *tcon, int add_treename);
char *cifs_build_devname(char *nodename, const char *prepath);
void delete_mid(struct TCP_Server_Info *server, struct smb_message *smb);
+struct smb_message *smb_message_alloc(enum smb_command_trace cmd, gfp_t gfp);
+void smb_get_message(struct smb_message *smb);
+void smb_put_message(struct smb_message *smb);
+void smb_put_messages(struct smb_message *smb);
void __release_mid(struct TCP_Server_Info *server, struct smb_message *smb);
void cifs_wake_up_task(struct TCP_Server_Info *server,
struct smb_message *smb);
@@ -470,14 +474,9 @@ static inline bool dfs_src_pathname_equal(const char *s1, const char *s2)
return true;
}
-static inline void smb_get_mid(struct smb_message *smb)
-{
- refcount_inc(&smb->refcount);
-}
-
static inline void release_mid(struct TCP_Server_Info *server, struct smb_message *smb)
{
- if (refcount_dec_and_test(&smb->refcount))
+ if (refcount_dec_and_test(&smb->ref))
__release_mid(server, smb);
}
diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
index 97de3ae68d7a..3d7e279ba149 100644
--- a/fs/smb/client/connect.c
+++ b/fs/smb/client/connect.c
@@ -327,7 +327,7 @@ cifs_abort_connection(struct TCP_Server_Info *server)
cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
spin_lock(&server->mid_queue_lock);
list_for_each_entry_safe(smb, nsmb, &server->pending_mid_q, qhead) {
- smb_get_mid(smb);
+ smb_get_message(smb);
if (smb->mid_state == MID_REQUEST_SUBMITTED)
smb->mid_state = MID_RETRY_NEEDED;
list_move(&smb->qhead, &retry_list);
@@ -884,7 +884,7 @@ is_smb_response(struct TCP_Server_Info *server, unsigned char type)
*/
spin_lock(&server->mid_queue_lock);
list_for_each_entry_safe(smb, nsmb, &server->pending_mid_q, qhead) {
- smb_get_mid(smb);
+ smb_get_message(smb);
list_move(&smb->qhead, &dispose_list);
smb->deleted_from_q = true;
}
@@ -1103,7 +1103,7 @@ clean_demultiplex_info(struct TCP_Server_Info *server)
list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
smb = list_entry(tmp, struct smb_message, qhead);
cifs_dbg(FYI, "Clearing mid %llu\n", smb->mid);
- smb_get_mid(smb);
+ smb_get_message(smb);
smb->mid_state = MID_SHUTDOWN;
list_move(&smb->qhead, &dispose_list);
smb->deleted_from_q = true;
diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
index c1c16f6346fb..df74975374ee 100644
--- a/fs/smb/client/smb1ops.c
+++ b/fs/smb/client/smb1ops.c
@@ -254,7 +254,7 @@ cifs_find_mid(struct TCP_Server_Info *server, char *buffer)
if (compare_mid(smb->mid, buf) &&
smb->mid_state == MID_REQUEST_SUBMITTED &&
le16_to_cpu(smb->command) == buf->Command) {
- smb_get_mid(smb);
+ smb_get_message(smb);
spin_unlock(&server->mid_queue_lock);
return smb;
}
diff --git a/fs/smb/client/smb1transport.c b/fs/smb/client/smb1transport.c
index c2d211a62577..f38fe262c7ea 100644
--- a/fs/smb/client/smb1transport.c
+++ b/fs/smb/client/smb1transport.c
@@ -45,7 +45,7 @@ alloc_mid(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
smb = mempool_alloc(&smb_message_pool, GFP_NOFS);
memset(smb, 0, sizeof(struct smb_message));
- refcount_set(&smb->refcount, 1);
+ refcount_set(&smb->ref, 1);
spin_lock_init(&smb->mid_lock);
smb->mid = get_mid(smb_buffer);
smb->pid = current->pid;
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index 236eb560bdff..f39074d0e4a0 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -416,7 +416,7 @@ __smb2_find_mid(struct TCP_Server_Info *server, char *buf, bool dequeue)
if ((smb->mid == wire_mid) &&
(smb->mid_state == MID_REQUEST_SUBMITTED) &&
(smb->command == shdr->Command)) {
- smb_get_mid(smb);
+ smb_get_message(smb);
if (dequeue) {
list_del_init(&smb->qhead);
smb->deleted_from_q = true;
diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c
index a28b66ead690..f5b676802ce7 100644
--- a/fs/smb/client/smb2transport.c
+++ b/fs/smb/client/smb2transport.c
@@ -619,10 +619,10 @@ smb2_mid_entry_alloc(const struct smb2_hdr *shdr,
smb = mempool_alloc(&smb_message_pool, GFP_NOFS);
memset(smb, 0, sizeof(*smb));
- refcount_set(&smb->refcount, 1);
+ refcount_set(&smb->ref, 1);
spin_lock_init(&smb->mid_lock);
smb->mid = le64_to_cpu(shdr->MessageId);
- smb->credits = credits > 0 ? credits : 1;
+ smb->credits_consumed = credits > 0 ? credits : 1;
smb->pid = current->pid;
smb->command = shdr->Command; /* Always LE */
smb->when_alloc = jiffies;
diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c
index 622f63779de0..3ea52cf4a64b 100644
--- a/fs/smb/client/transport.c
+++ b/fs/smb/client/transport.c
@@ -30,6 +30,46 @@
#include "smbdirect.h"
#include "compress.h"
+struct smb_message *smb_message_alloc(enum smb_command_trace cmd, gfp_t gfp)
+{
+ struct smb_message *smb;
+
+ smb = mempool_alloc(&smb_message_pool, gfp);
+ if (smb) {
+ memset(smb, 0, sizeof(*smb));
+ refcount_set(&smb->ref, 1);
+ smb->command_trace = cmd;
+ }
+ return smb;
+}
+
+void smb_get_message(struct smb_message *smb)
+{
+ refcount_inc(&smb->ref);
+}
+
+/*
+ * Drop a ref on a message. This does not touch the chained messages.
+ */
+void smb_put_message(struct smb_message *smb)
+{
+ if (refcount_dec_and_test(&smb->ref))
+ mempool_free(smb, &smb_message_pool);
+}
+
+/*
+ * Dispose of a chain of compound messages.
+ */
+void smb_put_messages(struct smb_message *smb)
+{
+ struct smb_message *next;
+
+ for (; smb; smb = next) {
+ next = smb->next;
+ smb_put_message(smb);
+ }
+}
+
void
cifs_wake_up_task(struct TCP_Server_Info *server, struct smb_message *smb)
{
@@ -722,7 +762,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst,
rc = smb_send_rqst(server, 1, rqst, flags);
if (rc < 0) {
- revert_current_mid(server, smb->credits);
+ revert_current_mid(server, smb->credits_consumed);
server->sequence_number -= 2;
delete_mid(server, smb);
}
next prev parent reply other threads:[~2026-05-19 10:22 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 ` David Howells [this message]
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 ` [RFC PATCH 31/36] cifs: Convert SMB2 Read request David Howells
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-10-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