[PATCH 7/9] smb/client: remember async ids from SMB2 pending responses

ChenXiaoSong <[email protected]>
Newsgroups org.kernel.vger.linux-cifs
Message-ID <[email protected]>
From: ChenXiaoSong <[email protected]>

SMB2 servers may turn a request into an asynchronous command by replying
with STATUS_PENDING and SMB2_FLAGS_ASYNC_COMMAND. A later SMB2_CANCEL must
target the async id from that pending response rather than only the
original message id fields.

Store that async id in the mid entry when processing STATUS_PENDING so
the cancel path can build the correct header.

Signed-off-by: ChenXiaoSong <[email protected]>
---
 fs/smb/client/cifsglob.h |  2 ++
 fs/smb/client/smb2ops.c  | 12 ++++++++++++
 2 files changed, 14 insertions(+)

diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index 1250518997fb..ea1c5eb2356a 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -1713,6 +1713,7 @@ struct mid_q_entry {
 	struct list_head qhead;	/* mids waiting on reply from this server */
 	refcount_t refcount;
 	__u64 mid;		/* multiplex id */
+	__u64 async_id;		/* async id if server returned STATUS_PENDING */
 	__u16 credits;		/* number of credits consumed by this mid */
 	__u16 credits_received;	/* number of credits from the response */
 	__u32 pid;		/* process id */
@@ -1742,6 +1743,7 @@ struct mid_q_entry {
 	bool multiRsp:1;	/* multiple trans2 responses for one request  */
 	bool multiEnd:1;	/* both received */
 	bool decrypted:1;	/* decrypted entry */
+	bool async_cmd:1;	/* server returned an async id for this request */
 };
 
 struct close_cancelled_open {
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index 9c2455b5fb03..40f1ae0e9735 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -2684,11 +2684,23 @@ static bool
 smb2_is_status_pending(char *buf, struct TCP_Server_Info *server)
 {
 	struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
+	struct mid_q_entry *mid;
 	int scredits, in_flight;
 
 	if (shdr->Status != STATUS_PENDING)
 		return false;
 
+	if (shdr->Flags & SMB2_FLAGS_ASYNC_COMMAND) {
+		mid = __smb2_find_mid(server, buf, false);
+		if (mid) {
+			spin_lock(&mid->mid_lock);
+			mid->async_cmd = true;
+			mid->async_id = le64_to_cpu(shdr->Id.AsyncId);
+			spin_unlock(&mid->mid_lock);
+			release_mid(server, mid);
+		}
+	}
+
 	if (shdr->CreditRequest) {
 		spin_lock(&server->req_lock);
 		server->credits += le16_to_cpu(shdr->CreditRequest);
-- 
2.54.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.