From nobody Sun Oct 5 12:52:20 2025 Received: from dggsgout12.his.huawei.com (dggsgout12.his.huawei.com [45.249.212.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1B1961BEF7E; Mon, 4 Aug 2025 13:47:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754315247; cv=none; b=qF3YkLc+hBIddV4/27dPCyjXaktutddpcusWuyuTJCmwg6mt75trgNAsiyXcpe6cU94V0QojXaX9hk51pc5buZ/qpmXQbzCiEsjehlop6qzP7nwOTVvGwQ4JQPNY4VCKCYM2+9Qz00NbHE6V2Jpwt6WZSatae3KUPsp7HGTRXmM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754315247; c=relaxed/simple; bh=f4wtnMuK7prSopOjB6a/p2BQqQ+I/8XSkFa6dJ/6B98=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=joRLIZCOqEUdsTGnXaa8AcRux/PiECdr+BbMLd+aV4v47f8UL7LwWhKJBxp2vCBlKWAh/Kk6rqJpiLcgaN+D4kNUnlKRaJ3tY0u2qCZJvYa+vqS1sloUAPdiEvhsgwYXLbRti6y+binnYv50qEToeyKIe2lV+g574B4O/1XU9bs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.235]) by dggsgout12.his.huawei.com (SkyGuard) with ESMTPS id 4bwdCY4FM4zKHMnj; Mon, 4 Aug 2025 21:47:21 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id 979F61A0B93; Mon, 4 Aug 2025 21:47:20 +0800 (CST) Received: from huaweicloud.com (unknown [10.175.104.67]) by APP4 (Coremail) with SMTP id gCh0CgAHgxPjuZBoXT8zCg--.8001S5; Mon, 04 Aug 2025 21:47:20 +0800 (CST) From: Wang Zhaolong To: sfrench@samba.org, pshilov@microsoft.com Cc: linux-cifs@vger.kernel.org, samba-technical@lists.samba.org, linux-kernel@vger.kernel.org, chengzhihao1@huawei.com, wangzhaolong@huaweicloud.com, yi.zhang@huawei.com, yangerkun@huawei.com Subject: [PATCH 1/4] smb: client: rename server mid_lock to mid_queue_lock Date: Mon, 4 Aug 2025 21:40:03 +0800 Message-Id: <20250804134006.3609555-2-wangzhaolong@huaweicloud.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20250804134006.3609555-1-wangzhaolong@huaweicloud.com> References: <20250804134006.3609555-1-wangzhaolong@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: gCh0CgAHgxPjuZBoXT8zCg--.8001S5 X-Coremail-Antispam: 1UD129KBjvAXoW3ur1UtF18GF45Xw1ruw1Dtrb_yoW8Zr4xKo Z7X3s5Zr4UWryktryFyrn3tF18Xa4DKayUJrsYkr15Aasaka4jvrWUtw15JFWYv39rArsF v34xJFnYga4DJF1kn29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUY_7AC8VAFwI0_Xr0_Wr1l1xkIjI8I6I8E6xAIw20EY4v20xva j40_Wr0E3s1l1IIY67AEw4v_Jr0_Jr4l82xGYIkIc2x26280x7IE14v26r18M28IrcIa0x kI8VCY1x0267AKxVWUCVW8JwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK021l84AC jcxK6xIIjxv20xvE14v26F1j6w1UM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26r4UJVWxJr 1l84ACjcxK6I8E87Iv67AKxVW0oVCq3wA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_GcCE3s1l e2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E2Ix0cI 8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkEbVWUJVW8JwAC jcxG0xvY0x0EwIxGrwACjI8F5VA0II8E6IAqYI8I648v4I1lc7CjxVAaw2AFwI0_Jw0_GF yl42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWU JVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r1q6r43MIIYrxkI7V AKI48JMIIF0xvE2Ix0cI8IcVAFwI0_Jr0_JF4lIxAIcVC0I7IYx2IY6xkF7I0E14v26r4j 6F4UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42 IY6I8E87Iv6xkF7I0E14v26r4j6r4UJbIYCTnIWIevJa73UjIFyTuYvjfU5a0mUUUUU X-CM-SenderInfo: pzdqw6xkdrz0tqj6x35dzhxuhorxvhhfrp/ Content-Type: text/plain; charset="utf-8" This is step 1/4 of a patch series to fix mid_q_entry memory leaks caused by race conditions in callback execution. The current mid_lock name is somewhat ambiguous about what it protects. To prepare for splitting this lock into separate, more granular locks, this patch renames mid_lock to mid_queue_lock to clearly indicate its specific responsibility for protecting the pending_mid_q list and related queue operations. No functional changes are made in this patch - it only prepares the codebase for the lock splitting that follows. - mid_queue_lock for queue operations - mid_counter_lock for mid counter operations - per-mid locks for individual mid state management Signed-off-by: Wang Zhaolong --- fs/smb/client/cifs_debug.c | 8 ++++---- fs/smb/client/cifsglob.h | 4 ++-- fs/smb/client/connect.c | 20 +++++++++---------- fs/smb/client/smb1ops.c | 10 +++++----- fs/smb/client/smb2ops.c | 26 ++++++++++++------------- fs/smb/client/smb2transport.c | 4 ++-- fs/smb/client/transport.c | 36 +++++++++++++++++------------------ 7 files changed, 54 insertions(+), 54 deletions(-) diff --git a/fs/smb/client/cifs_debug.c b/fs/smb/client/cifs_debug.c index f1cea365b6f1..80d6a51b8c11 100644 --- a/fs/smb/client/cifs_debug.c +++ b/fs/smb/client/cifs_debug.c @@ -58,11 +58,11 @@ void cifs_dump_mids(struct TCP_Server_Info *server) =20 if (server =3D=3D NULL) return; =20 cifs_dbg(VFS, "Dump pending requests:\n"); - spin_lock(&server->mid_lock); + spin_lock(&server->mid_queue_lock); list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) { cifs_dbg(VFS, "State: %d Cmd: %d Pid: %d Cbdata: %p Mid %llu\n", mid_entry->mid_state, le16_to_cpu(mid_entry->command), mid_entry->pid, @@ -81,11 +81,11 @@ void cifs_dump_mids(struct TCP_Server_Info *server) cifs_dump_detail(mid_entry->resp_buf, server); cifs_dump_mem("existing buf: ", mid_entry->resp_buf, 62); } } - spin_unlock(&server->mid_lock); + spin_unlock(&server->mid_queue_lock); #endif /* CONFIG_CIFS_DEBUG2 */ } =20 #ifdef CONFIG_PROC_FS static void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon) @@ -670,20 +670,20 @@ static int cifs_debug_data_proc_show(struct seq_file = *m, void *v) if (list_empty(&chan_server->pending_mid_q)) continue; =20 seq_printf(m, "\n\tServer ConnectionId: 0x%llx", chan_server->conn_id); - spin_lock(&chan_server->mid_lock); + spin_lock(&chan_server->mid_queue_lock); list_for_each_entry(mid_entry, &chan_server->pending_mid_q, qhead) { seq_printf(m, "\n\t\tState: %d com: %d pid: %d cbdata: %p mid %llu", mid_entry->mid_state, le16_to_cpu(mid_entry->command), mid_entry->pid, mid_entry->callback_data, mid_entry->mid); } - spin_unlock(&chan_server->mid_lock); + spin_unlock(&chan_server->mid_queue_lock); } spin_unlock(&ses->chan_lock); seq_puts(m, "\n--\n"); } if (i =3D=3D 0) diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 19dd901fe8ab..ecd568793ce7 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -730,11 +730,11 @@ struct TCP_Server_Info { #ifdef CONFIG_NET_NS struct net *net; #endif wait_queue_head_t response_q; wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/ - spinlock_t mid_lock; /* protect mid queue and it's entries */ + spinlock_t mid_queue_lock; /* protect mid queue */ struct list_head pending_mid_q; bool noblocksnd; /* use blocking sendmsg */ bool noautotune; /* do not autotune send buf sizes */ bool nosharesock; bool tcp_nodelay; @@ -2005,11 +2005,11 @@ require use of the stronger protocol */ * cifs_tcp_ses_lock cifs_tcp_ses_list sesInfoAlloc * GlobalMid_Lock GlobalMaxActiveXid init_cifs * GlobalCurrentXid * GlobalTotalActiveXid * TCP_Server_Info->srv_lock (anything in struct not protected by another = lock and can change) - * TCP_Server_Info->mid_lock TCP_Server_Info->pending_mid_q cifs_get_tcp_s= ession + * TCP_Server_Info->mid_queue_lock TCP_Server_Info->pending_mid_q cifs_get= _tcp_session * ->CurrentMid * (any changes in mid_q_entry fields) * TCP_Server_Info->req_lock TCP_Server_Info->in_flight cifs_get_tcp_sessi= on * ->credits * ->echo_credits diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 5eec8957f2a9..e4b577ca48d5 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -319,19 +319,19 @@ cifs_abort_connection(struct TCP_Server_Info *server) server->lstrp =3D jiffies; =20 /* mark submitted MIDs for retry and issue callback */ INIT_LIST_HEAD(&retry_list); cifs_dbg(FYI, "%s: moving mids to private list\n", __func__); - spin_lock(&server->mid_lock); + spin_lock(&server->mid_queue_lock); list_for_each_entry_safe(mid, nmid, &server->pending_mid_q, qhead) { kref_get(&mid->refcount); if (mid->mid_state =3D=3D MID_REQUEST_SUBMITTED) mid->mid_state =3D MID_RETRY_NEEDED; list_move(&mid->qhead, &retry_list); mid->mid_flags |=3D MID_DELETED; } - spin_unlock(&server->mid_lock); + spin_unlock(&server->mid_queue_lock); cifs_server_unlock(server); =20 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__); list_for_each_entry_safe(mid, nmid, &retry_list, qhead) { list_del_init(&mid->qhead); @@ -882,17 +882,17 @@ is_smb_response(struct TCP_Server_Info *server, unsig= ned char type) * server, so reconnect would not signal connection * aborted error to mid's callbacks. Note that for this * server there should be exactly one pending mid * corresponding to SMB1/SMB2 Negotiate packet. */ - spin_lock(&server->mid_lock); + spin_lock(&server->mid_queue_lock); list_for_each_entry_safe(mid, nmid, &server->pending_mid_q, qhead) { kref_get(&mid->refcount); list_move(&mid->qhead, &dispose_list); mid->mid_flags |=3D MID_DELETED; } - spin_unlock(&server->mid_lock); + spin_unlock(&server->mid_queue_lock); =20 /* Now try to reconnect once with NetBIOS session. */ server->with_rfc1001 =3D true; rc =3D cifs_reconnect_once(server); =20 @@ -955,26 +955,26 @@ void dequeue_mid(struct mid_q_entry *mid, bool malformed) { #ifdef CONFIG_CIFS_STATS2 mid->when_received =3D jiffies; #endif - spin_lock(&mid->server->mid_lock); + spin_lock(&mid->server->mid_queue_lock); if (!malformed) mid->mid_state =3D MID_RESPONSE_RECEIVED; else mid->mid_state =3D MID_RESPONSE_MALFORMED; /* * Trying to handle/dequeue a mid after the send_recv() * function has finished processing it is a bug. */ if (mid->mid_flags & MID_DELETED) { - spin_unlock(&mid->server->mid_lock); + spin_unlock(&mid->server->mid_queue_lock); pr_warn_once("trying to dequeue a deleted mid\n"); } else { list_del_init(&mid->qhead); mid->mid_flags |=3D MID_DELETED; - spin_unlock(&mid->server->mid_lock); + spin_unlock(&mid->server->mid_queue_lock); } } =20 static unsigned int smb2_get_credits_from_hdr(char *buffer, struct TCP_Server_Info *server) @@ -1099,20 +1099,20 @@ clean_demultiplex_info(struct TCP_Server_Info *serv= er) if (!list_empty(&server->pending_mid_q)) { struct mid_q_entry *mid_entry; struct list_head *tmp, *tmp2; LIST_HEAD(dispose_list); =20 - spin_lock(&server->mid_lock); + spin_lock(&server->mid_queue_lock); list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { mid_entry =3D list_entry(tmp, struct mid_q_entry, qhead); cifs_dbg(FYI, "Clearing mid %llu\n", mid_entry->mid); kref_get(&mid_entry->refcount); mid_entry->mid_state =3D MID_SHUTDOWN; list_move(&mid_entry->qhead, &dispose_list); mid_entry->mid_flags |=3D MID_DELETED; } - spin_unlock(&server->mid_lock); + spin_unlock(&server->mid_queue_lock); =20 /* now walk dispose list and issue callbacks */ list_for_each_safe(tmp, tmp2, &dispose_list) { mid_entry =3D list_entry(tmp, struct mid_q_entry, qhead); cifs_dbg(FYI, "Callback mid %llu\n", mid_entry->mid); @@ -1820,11 +1820,11 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx, tcp_ses->reconnect_instance =3D 1; tcp_ses->lstrp =3D jiffies; tcp_ses->compression.requested =3D ctx->compress; spin_lock_init(&tcp_ses->req_lock); spin_lock_init(&tcp_ses->srv_lock); - spin_lock_init(&tcp_ses->mid_lock); + spin_lock_init(&tcp_ses->mid_queue_lock); INIT_LIST_HEAD(&tcp_ses->tcp_ses_list); INIT_LIST_HEAD(&tcp_ses->smb_ses_list); INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request); INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server); mutex_init(&tcp_ses->reconnect_mutex); diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c index e364b6515af3..a1442f697706 100644 --- a/fs/smb/client/smb1ops.c +++ b/fs/smb/client/smb1ops.c @@ -93,21 +93,21 @@ static struct mid_q_entry * cifs_find_mid(struct TCP_Server_Info *server, char *buffer) { struct smb_hdr *buf =3D (struct smb_hdr *)buffer; struct mid_q_entry *mid; =20 - spin_lock(&server->mid_lock); + spin_lock(&server->mid_queue_lock); list_for_each_entry(mid, &server->pending_mid_q, qhead) { if (compare_mid(mid->mid, buf) && mid->mid_state =3D=3D MID_REQUEST_SUBMITTED && le16_to_cpu(mid->command) =3D=3D buf->Command) { kref_get(&mid->refcount); - spin_unlock(&server->mid_lock); + spin_unlock(&server->mid_queue_lock); return mid; } } - spin_unlock(&server->mid_lock); + spin_unlock(&server->mid_queue_lock); return NULL; } =20 static void cifs_add_credits(struct TCP_Server_Info *server, @@ -167,11 +167,11 @@ cifs_get_next_mid(struct TCP_Server_Info *server) { __u64 mid =3D 0; __u16 last_mid, cur_mid; bool collision, reconnect =3D false; =20 - spin_lock(&server->mid_lock); + spin_lock(&server->mid_queue_lock); =20 /* mid is 16 bit only for CIFS/SMB */ cur_mid =3D (__u16)((server->CurrentMid) & 0xffff); /* we do not want to loop forever */ last_mid =3D cur_mid; @@ -226,11 +226,11 @@ cifs_get_next_mid(struct TCP_Server_Info *server) server->CurrentMid =3D mid; break; } cur_mid++; } - spin_unlock(&server->mid_lock); + spin_unlock(&server->mid_queue_lock); =20 if (reconnect) { cifs_signal_cifsd_for_reconnect(server, false); } =20 diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 1b4a31894f43..c714707249c7 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -372,23 +372,23 @@ smb2_adjust_credits(struct TCP_Server_Info *server, static __u64 smb2_get_next_mid(struct TCP_Server_Info *server) { __u64 mid; /* for SMB2 we need the current value */ - spin_lock(&server->mid_lock); + spin_lock(&server->mid_queue_lock); mid =3D server->CurrentMid++; - spin_unlock(&server->mid_lock); + spin_unlock(&server->mid_queue_lock); return mid; } =20 static void smb2_revert_current_mid(struct TCP_Server_Info *server, const unsigned int= val) { - spin_lock(&server->mid_lock); + spin_lock(&server->mid_queue_lock); if (server->CurrentMid >=3D val) server->CurrentMid -=3D val; - spin_unlock(&server->mid_lock); + spin_unlock(&server->mid_queue_lock); } =20 static struct mid_q_entry * __smb2_find_mid(struct TCP_Server_Info *server, char *buf, bool dequeue) { @@ -399,25 +399,25 @@ __smb2_find_mid(struct TCP_Server_Info *server, char = *buf, bool dequeue) if (shdr->ProtocolId =3D=3D SMB2_TRANSFORM_PROTO_NUM) { cifs_server_dbg(VFS, "Encrypted frame parsing not supported yet\n"); return NULL; } =20 - spin_lock(&server->mid_lock); + spin_lock(&server->mid_queue_lock); list_for_each_entry(mid, &server->pending_mid_q, qhead) { if ((mid->mid =3D=3D wire_mid) && (mid->mid_state =3D=3D MID_REQUEST_SUBMITTED) && (mid->command =3D=3D shdr->Command)) { kref_get(&mid->refcount); if (dequeue) { list_del_init(&mid->qhead); mid->mid_flags |=3D MID_DELETED; } - spin_unlock(&server->mid_lock); + spin_unlock(&server->mid_queue_lock); return mid; } } - spin_unlock(&server->mid_lock); + spin_unlock(&server->mid_queue_lock); return NULL; } =20 static struct mid_q_entry * smb2_find_mid(struct TCP_Server_Info *server, char *buf) @@ -458,13 +458,13 @@ smb2_negotiate(const unsigned int xid, struct cifs_ses *ses, struct TCP_Server_Info *server) { int rc; =20 - spin_lock(&server->mid_lock); + spin_lock(&server->mid_queue_lock); server->CurrentMid =3D 0; - spin_unlock(&server->mid_lock); + spin_unlock(&server->mid_queue_lock); rc =3D SMB2_negotiate(xid, ses, server); return rc; } =20 static inline unsigned int @@ -4807,22 +4807,22 @@ static void smb2_decrypt_offload(struct work_struct= *work) =20 mid->callback(mid); } else { spin_lock(&dw->server->srv_lock); if (dw->server->tcpStatus =3D=3D CifsNeedReconnect) { - spin_lock(&dw->server->mid_lock); + spin_lock(&dw->server->mid_queue_lock); mid->mid_state =3D MID_RETRY_NEEDED; - spin_unlock(&dw->server->mid_lock); + spin_unlock(&dw->server->mid_queue_lock); spin_unlock(&dw->server->srv_lock); mid->callback(mid); } else { - spin_lock(&dw->server->mid_lock); + spin_lock(&dw->server->mid_queue_lock); mid->mid_state =3D MID_REQUEST_SUBMITTED; mid->mid_flags &=3D ~(MID_DELETED); list_add_tail(&mid->qhead, &dw->server->pending_mid_q); - spin_unlock(&dw->server->mid_lock); + spin_unlock(&dw->server->mid_queue_lock); spin_unlock(&dw->server->srv_lock); } } release_mid(mid); } diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c index 475b36c27f65..ff9ef7fcd010 100644 --- a/fs/smb/client/smb2transport.c +++ b/fs/smb/client/smb2transport.c @@ -838,13 +838,13 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_S= erver_Info *server, spin_unlock(&ses->ses_lock); =20 *mid =3D smb2_mid_entry_alloc(shdr, server); if (*mid =3D=3D NULL) return -ENOMEM; - spin_lock(&server->mid_lock); + spin_lock(&server->mid_queue_lock); list_add_tail(&(*mid)->qhead, &server->pending_mid_q); - spin_unlock(&server->mid_lock); + spin_unlock(&server->mid_queue_lock); =20 return 0; } =20 int diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c index 191783f553ce..12dc927aa4a2 100644 --- a/fs/smb/client/transport.c +++ b/fs/smb/client/transport.c @@ -158,16 +158,16 @@ void __release_mid(struct kref *refcount) } =20 void delete_mid(struct mid_q_entry *mid) { - spin_lock(&mid->server->mid_lock); + spin_lock(&mid->server->mid_queue_lock); if (!(mid->mid_flags & MID_DELETED)) { list_del_init(&mid->qhead); mid->mid_flags |=3D MID_DELETED; } - spin_unlock(&mid->server->mid_lock); + spin_unlock(&mid->server->mid_queue_lock); =20 release_mid(mid); } =20 /* @@ -714,13 +714,13 @@ static int allocate_mid(struct cifs_ses *ses, struct = smb_hdr *in_buf, spin_unlock(&ses->ses_lock); =20 *ppmidQ =3D alloc_mid(in_buf, ses->server); if (*ppmidQ =3D=3D NULL) return -ENOMEM; - spin_lock(&ses->server->mid_lock); + spin_lock(&ses->server->mid_queue_lock); list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q); - spin_unlock(&ses->server->mid_lock); + spin_unlock(&ses->server->mid_queue_lock); return 0; } =20 static int wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ) @@ -817,13 +817,13 @@ cifs_call_async(struct TCP_Server_Info *server, struc= t smb_rqst *rqst, mid->callback_data =3D cbdata; mid->handle =3D handle; mid->mid_state =3D MID_REQUEST_SUBMITTED; =20 /* put it on the pending_mid_q */ - spin_lock(&server->mid_lock); + spin_lock(&server->mid_queue_lock); list_add_tail(&mid->qhead, &server->pending_mid_q); - spin_unlock(&server->mid_lock); + spin_unlock(&server->mid_queue_lock); =20 /* * Need to store the time in mid before calling I/O. For call_async, * I/O response may come back and free the mid entry on another thread. */ @@ -878,14 +878,14 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct = TCP_Server_Info *server) int rc =3D 0; =20 cifs_dbg(FYI, "%s: cmd=3D%d mid=3D%llu state=3D%d\n", __func__, le16_to_cpu(mid->command), mid->mid, mid->mid_state); =20 - spin_lock(&server->mid_lock); + spin_lock(&server->mid_queue_lock); switch (mid->mid_state) { case MID_RESPONSE_READY: - spin_unlock(&server->mid_lock); + spin_unlock(&server->mid_queue_lock); return rc; case MID_RETRY_NEEDED: rc =3D -EAGAIN; break; case MID_RESPONSE_MALFORMED: @@ -900,17 +900,17 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct = TCP_Server_Info *server) default: if (!(mid->mid_flags & MID_DELETED)) { list_del_init(&mid->qhead); mid->mid_flags |=3D MID_DELETED; } - spin_unlock(&server->mid_lock); + spin_unlock(&server->mid_queue_lock); cifs_server_dbg(VFS, "%s: invalid mid state mid=3D%llu state=3D%d\n", __func__, mid->mid, mid->mid_state); rc =3D -EIO; goto sync_mid_done; } - spin_unlock(&server->mid_lock); + spin_unlock(&server->mid_queue_lock); =20 sync_mid_done: release_mid(mid); return rc; } @@ -1211,19 +1211,19 @@ compound_send_recv(const unsigned int xid, struct c= ifs_ses *ses, if (rc !=3D 0) { for (; i < num_rqst; i++) { cifs_server_dbg(FYI, "Cancelling wait for mid %llu cmd: %d\n", midQ[i]->mid, le16_to_cpu(midQ[i]->command)); send_cancel(server, &rqst[i], midQ[i]); - spin_lock(&server->mid_lock); + spin_lock(&server->mid_queue_lock); midQ[i]->mid_flags |=3D MID_WAIT_CANCELLED; if (midQ[i]->mid_state =3D=3D MID_REQUEST_SUBMITTED || midQ[i]->mid_state =3D=3D MID_RESPONSE_RECEIVED) { midQ[i]->callback =3D cifs_cancelled_callback; cancelled_mid[i] =3D true; credits[i].value =3D 0; } - spin_unlock(&server->mid_lock); + spin_unlock(&server->mid_queue_lock); } } =20 for (i =3D 0; i < num_rqst; i++) { if (rc < 0) @@ -1421,20 +1421,20 @@ SendReceive(const unsigned int xid, struct cifs_ses= *ses, goto out; =20 rc =3D wait_for_response(server, midQ); if (rc !=3D 0) { send_cancel(server, &rqst, midQ); - spin_lock(&server->mid_lock); + spin_lock(&server->mid_queue_lock); if (midQ->mid_state =3D=3D MID_REQUEST_SUBMITTED || midQ->mid_state =3D=3D MID_RESPONSE_RECEIVED) { /* no longer considered to be "in-flight" */ midQ->callback =3D release_mid; - spin_unlock(&server->mid_lock); + spin_unlock(&server->mid_queue_lock); add_credits(server, &credits, 0); return rc; } - spin_unlock(&server->mid_lock); + spin_unlock(&server->mid_queue_lock); } =20 rc =3D cifs_sync_mid_result(midQ, server); if (rc !=3D 0) { add_credits(server, &credits, 0); @@ -1603,19 +1603,19 @@ SendReceiveBlockingLock(const unsigned int xid, str= uct cifs_tcon *tcon, } =20 rc =3D wait_for_response(server, midQ); if (rc) { send_cancel(server, &rqst, midQ); - spin_lock(&server->mid_lock); + spin_lock(&server->mid_queue_lock); if (midQ->mid_state =3D=3D MID_REQUEST_SUBMITTED || midQ->mid_state =3D=3D MID_RESPONSE_RECEIVED) { /* no longer considered to be "in-flight" */ midQ->callback =3D release_mid; - spin_unlock(&server->mid_lock); + spin_unlock(&server->mid_queue_lock); return rc; } - spin_unlock(&server->mid_lock); + spin_unlock(&server->mid_queue_lock); } =20 /* We got the response - restart system call. */ rstart =3D 1; spin_lock(&server->srv_lock); --=20 2.39.2 From nobody Sun Oct 5 12:52:20 2025 Received: from dggsgout11.his.huawei.com (dggsgout11.his.huawei.com [45.249.212.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 40AF426E712; Mon, 4 Aug 2025 13:47:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754315253; cv=none; b=JHlcxaOyQqhzKafSkqnWUXCUDcLAsGZqzbuDOh+lCiszLrxWGIKUT4uYu3HjOHXkllmxgMyzekkk4rXJcLp/NMtFVP7znTCnVCORI1kBVMaSpMwP71v9RqwdBFLTEaMChrLE3fyI91Y5kH6Oa0gJmBVNlefK/PB1+7x9YmQUk2s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754315253; c=relaxed/simple; bh=OHchsDxfLI6H/RcBK530VV2th9TllWlysNrU6v5xvU4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=QqGCYxtKjIDC/thQF39tu/jcXZb+eMX2PbBae8h6WS0/6LEw4GmW0T5/dCwm8519w5qjXbMLVjsnOcRfm2MQxZfAT6kyg/Ek0VWhdpIc7Mb8ggLDyUKmUQV+pH0xlG4Bht/2WEr0AR8NUZjI/GrNq7l40tVLrCcCjajbBilj/UQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.235]) by dggsgout11.his.huawei.com (SkyGuard) with ESMTPS id 4bwdCZ2l5KzYQv6Y; Mon, 4 Aug 2025 21:47:22 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id 0B3691A0B97; Mon, 4 Aug 2025 21:47:21 +0800 (CST) Received: from huaweicloud.com (unknown [10.175.104.67]) by APP4 (Coremail) with SMTP id gCh0CgAHgxPjuZBoXT8zCg--.8001S6; Mon, 04 Aug 2025 21:47:20 +0800 (CST) From: Wang Zhaolong To: sfrench@samba.org, pshilov@microsoft.com Cc: linux-cifs@vger.kernel.org, samba-technical@lists.samba.org, linux-kernel@vger.kernel.org, chengzhihao1@huawei.com, wangzhaolong@huaweicloud.com, yi.zhang@huawei.com, yangerkun@huawei.com Subject: [PATCH 2/4] smb: client: add mid_counter_lock to protect the mid counter counter Date: Mon, 4 Aug 2025 21:40:04 +0800 Message-Id: <20250804134006.3609555-3-wangzhaolong@huaweicloud.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20250804134006.3609555-1-wangzhaolong@huaweicloud.com> References: <20250804134006.3609555-1-wangzhaolong@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: gCh0CgAHgxPjuZBoXT8zCg--.8001S6 X-Coremail-Antispam: 1UD129KBjvAXoW3ury5tFW7Jw4Dtw1kCw47twb_yoW8Ar15Go Wvqw13uw4UJryUKr98trn3JF1xX348tFWUJFWjqF1Uua4Fk34UAa48Zr15tFWa93y5tr4Y v3yxJa97uas3Ja97n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUYE7AC8VAFwI0_Wr0E3s1l1xkIjI8I6I8E6xAIw20EY4v20xva j40_Wr0E3s1l1IIY67AEw4v_Jr0_Jr4l82xGYIkIc2x26280x7IE14v26r15M28IrcIa0x kI8VCY1x0267AKxVW8JVW5JwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK021l84AC jcxK6xIIjxv20xvE14v26F1j6w1UM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26r4UJVWxJr 1l84ACjcxK6I8E87Iv67AKxVW0oVCq3wA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_GcCE3s1l e2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E2Ix0cI 8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkEbVWUJVW8JwAC jcxG0xvY0x0EwIxGrwACjI8F5VA0II8E6IAqYI8I648v4I1lc7CjxVAaw2AFwI0_Jw0_GF yl42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWU JVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r1q6r43MIIYrxkI7V AKI48JMIIF0xvE2Ix0cI8IcVAFwI0_Jr0_JF4lIxAIcVC0I7IYx2IY6xkF7I0E14v26r4j 6F4UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42 IY6I8E87Iv6xkF7I0E14v26r4UJVWxJrUvcSsGvfC2KfnxnUUI43ZEXa7VUj5Ef7UUUUU= = X-CM-SenderInfo: pzdqw6xkdrz0tqj6x35dzhxuhorxvhhfrp/ Content-Type: text/plain; charset="utf-8" This is step 2/4 of a patch series to fix mid_q_entry memory leaks caused by race conditions in callback execution. Add a dedicated mid_counter_lock to protect current_mid counter, separating it from mid_queue_lock which protects pending_mid_q operations. This reduces lock contention and prepares for finer- grained locking in subsequent patches. Changes: - Add TCP_Server_Info->mid_counter_lock spinlock - Rename CurrentMid to current_mid for consistency - Use mid_counter_lock to protect current_mid access - Update locking documentation in cifsglob.h This separation allows mid allocation to proceed without blocking queue operations, improving performance under heavy load. Signed-off-by: Wang Zhaolong --- fs/smb/client/cifsglob.h | 5 +++-- fs/smb/client/connect.c | 5 +++-- fs/smb/client/smb1ops.c | 11 ++++++----- fs/smb/client/smb2ops.c | 40 +++++++++++++++++++-------------------- fs/smb/client/transport.c | 12 ++++++------ 5 files changed, 38 insertions(+), 35 deletions(-) diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index ecd568793ce7..1844afdf1e41 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -731,10 +731,11 @@ struct TCP_Server_Info { struct net *net; #endif wait_queue_head_t response_q; wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/ spinlock_t mid_queue_lock; /* protect mid queue */ + spinlock_t mid_counter_lock; struct list_head pending_mid_q; bool noblocksnd; /* use blocking sendmsg */ bool noautotune; /* do not autotune send buf sizes */ bool nosharesock; bool tcp_nodelay; @@ -768,11 +769,11 @@ struct TCP_Server_Info { unsigned int max_rw; /* maxRw specifies the maximum */ /* message size the server can send or receive for */ /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */ unsigned int capabilities; /* selective disabling of caps by smb sess */ int timeAdj; /* Adjust for difference in server time zone in sec */ - __u64 CurrentMid; /* multiplex id - rotating counter, protected b= y GlobalMid_Lock */ + __u64 current_mid; /* multiplex id - rotating counter, protected by mid_c= ounter_lock */ char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */ /* 16th byte of RFC1001 workstation name is always null */ char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; __u32 sequence_number; /* for signing, protected by srv_mutex */ __u32 reconnect_instance; /* incremented on each reconnect */ @@ -2006,12 +2007,12 @@ require use of the stronger protocol */ * GlobalMid_Lock GlobalMaxActiveXid init_cifs * GlobalCurrentXid * GlobalTotalActiveXid * TCP_Server_Info->srv_lock (anything in struct not protected by another = lock and can change) * TCP_Server_Info->mid_queue_lock TCP_Server_Info->pending_mid_q cifs_get= _tcp_session - * ->CurrentMid * (any changes in mid_q_entry fields) + * TCP_Server_Info->mid_counter_lock TCP_Server_Info->current_mid ci= fs_get_tcp_session * TCP_Server_Info->req_lock TCP_Server_Info->in_flight cifs_get_tcp_sessi= on * ->credits * ->echo_credits * ->oplock_credits * ->reconnect_instance diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index e4b577ca48d5..74ad5881ee45 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -356,11 +356,11 @@ static bool cifs_tcp_ses_needs_reconnect(struct TCP_S= erver_Info *server, int num wake_up(&server->response_q); return false; } =20 cifs_dbg(FYI, "Mark tcp session as need reconnect\n"); - trace_smb3_reconnect(server->CurrentMid, server->conn_id, + trace_smb3_reconnect(server->current_mid, server->conn_id, server->hostname); server->tcpStatus =3D CifsNeedReconnect; =20 spin_unlock(&server->srv_lock); return true; @@ -1240,11 +1240,11 @@ smb2_add_credits_from_hdr(char *buffer, struct TCP_= Server_Info *server) scredits =3D server->credits; in_flight =3D server->in_flight; spin_unlock(&server->req_lock); wake_up(&server->request_q); =20 - trace_smb3_hdr_credits(server->CurrentMid, + trace_smb3_hdr_credits(server->current_mid, server->conn_id, server->hostname, scredits, le16_to_cpu(shdr->CreditRequest), in_flight); cifs_server_dbg(FYI, "%s: added %u credits total=3D%d\n", __func__, le16_to_cpu(shdr->CreditRequest), scredits); @@ -1821,10 +1821,11 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx, tcp_ses->lstrp =3D jiffies; tcp_ses->compression.requested =3D ctx->compress; spin_lock_init(&tcp_ses->req_lock); spin_lock_init(&tcp_ses->srv_lock); spin_lock_init(&tcp_ses->mid_queue_lock); + spin_lock_init(&tcp_ses->mid_counter_lock); INIT_LIST_HEAD(&tcp_ses->tcp_ses_list); INIT_LIST_HEAD(&tcp_ses->smb_ses_list); INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request); INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server); mutex_init(&tcp_ses->reconnect_mutex); diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c index a1442f697706..13f600a3d0c4 100644 --- a/fs/smb/client/smb1ops.c +++ b/fs/smb/client/smb1ops.c @@ -167,14 +167,13 @@ cifs_get_next_mid(struct TCP_Server_Info *server) { __u64 mid =3D 0; __u16 last_mid, cur_mid; bool collision, reconnect =3D false; =20 - spin_lock(&server->mid_queue_lock); - + spin_lock(&server->mid_counter_lock); /* mid is 16 bit only for CIFS/SMB */ - cur_mid =3D (__u16)((server->CurrentMid) & 0xffff); + cur_mid =3D (__u16)((server->current_mid) & 0xffff); /* we do not want to loop forever */ last_mid =3D cur_mid; cur_mid++; /* avoid 0xFFFF MID */ if (cur_mid =3D=3D 0xffff) @@ -196,19 +195,21 @@ cifs_get_next_mid(struct TCP_Server_Info *server) collision =3D false; if (cur_mid =3D=3D 0) cur_mid++; =20 num_mids =3D 0; + spin_lock(&server->mid_queue_lock); list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) { ++num_mids; if (mid_entry->mid =3D=3D cur_mid && mid_entry->mid_state =3D=3D MID_REQUEST_SUBMITTED) { /* This mid is in use, try a different one */ collision =3D true; break; } } + spin_unlock(&server->mid_queue_lock); =20 /* * if we have more than 32k mids in the list, then something * is very wrong. Possibly a local user is trying to DoS the * box by issuing long-running calls and SIGKILL'ing them. If @@ -221,16 +222,16 @@ cifs_get_next_mid(struct TCP_Server_Info *server) if (num_mids > 32768) reconnect =3D true; =20 if (!collision) { mid =3D (__u64)cur_mid; - server->CurrentMid =3D mid; + server->current_mid =3D mid; break; } cur_mid++; } - spin_unlock(&server->mid_queue_lock); + spin_unlock(&server->mid_counter_lock); =20 if (reconnect) { cifs_signal_cifsd_for_reconnect(server, false); } =20 diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index c714707249c7..da2cb9585404 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -89,11 +89,11 @@ smb2_add_credits(struct TCP_Server_Info *server, reconnect_detected =3D true; =20 if (*val > 65000) { *val =3D 65000; /* Don't get near 64K credits, avoid srv bugs */ pr_warn_once("server overflowed SMB3 credits\n"); - trace_smb3_overflow_credits(server->CurrentMid, + trace_smb3_overflow_credits(server->current_mid, server->conn_id, server->hostname, *val, add, server->in_flight); } if (credits->in_flight_check > 1) { pr_warn_once("rreq R=3D%08x[%x] Credits not in flight\n", @@ -134,19 +134,19 @@ smb2_add_credits(struct TCP_Server_Info *server, in_flight =3D server->in_flight; spin_unlock(&server->req_lock); wake_up(&server->request_q); =20 if (reconnect_detected) { - trace_smb3_reconnect_detected(server->CurrentMid, + trace_smb3_reconnect_detected(server->current_mid, server->conn_id, server->hostname, scredits, add, in_flight); =20 cifs_dbg(FYI, "trying to put %d credits from the old server instance %d\= n", add, instance); } =20 if (reconnect_with_invalid_credits) { - trace_smb3_reconnect_with_invalid_credits(server->CurrentMid, + trace_smb3_reconnect_with_invalid_credits(server->current_mid, server->conn_id, server->hostname, scredits, add, in_flight); cifs_dbg(FYI, "Negotiate operation when server credits is non-zero. Opty= pe: %d, server credits: %d, credits added: %d\n", optype, scredits, add); } =20 @@ -174,11 +174,11 @@ smb2_add_credits(struct TCP_Server_Info *server, default: /* change_conf rebalanced credits for different types */ break; } =20 - trace_smb3_add_credits(server->CurrentMid, + trace_smb3_add_credits(server->current_mid, server->conn_id, server->hostname, scredits, add, in_flight); cifs_dbg(FYI, "%s: added %u credits total=3D%d\n", __func__, add, scredit= s); } =20 static void @@ -201,11 +201,11 @@ smb2_set_credits(struct TCP_Server_Info *server, cons= t int val) } scredits =3D server->credits; in_flight =3D server->in_flight; spin_unlock(&server->req_lock); =20 - trace_smb3_set_credits(server->CurrentMid, + trace_smb3_set_credits(server->current_mid, server->conn_id, server->hostname, scredits, val, in_flight); cifs_dbg(FYI, "%s: set %u credits\n", __func__, val); =20 /* don't log while holding the lock */ if (val =3D=3D 1) @@ -286,11 +286,11 @@ smb2_wait_mtu_credits(struct TCP_Server_Info *server,= size_t size, } scredits =3D server->credits; in_flight =3D server->in_flight; spin_unlock(&server->req_lock); =20 - trace_smb3_wait_credits(server->CurrentMid, + trace_smb3_wait_credits(server->current_mid, server->conn_id, server->hostname, scredits, -(credits->value), in_flig= ht); cifs_dbg(FYI, "%s: removed %u credits total=3D%d\n", __func__, credits->value, scredits); =20 return rc; @@ -314,11 +314,11 @@ smb2_adjust_credits(struct TCP_Server_Info *server, subreq->subreq.debug_index, credits->value, server->credits, server->in_flight, new_val - credits->value, cifs_trace_rw_credits_no_adjust_up); - trace_smb3_too_many_credits(server->CurrentMid, + trace_smb3_too_many_credits(server->current_mid, server->conn_id, server->hostname, 0, credits->value - new_val, 0); cifs_server_dbg(VFS, "R=3D%x[%x] request has less credits (%d) than requ= ired (%d)", subreq->rreq->debug_id, subreq->subreq.debug_index, credits->value, new_val); =20 @@ -336,11 +336,11 @@ smb2_adjust_credits(struct TCP_Server_Info *server, subreq->subreq.debug_index, credits->value, server->credits, server->in_flight, new_val - credits->value, cifs_trace_rw_credits_old_session); - trace_smb3_reconnect_detected(server->CurrentMid, + trace_smb3_reconnect_detected(server->current_mid, server->conn_id, server->hostname, scredits, credits->value - new_val, in_flight); cifs_server_dbg(VFS, "R=3D%x[%x] trying to return %d credits to old sess= ion\n", subreq->rreq->debug_id, subreq->subreq.debug_index, credits->value - new_val); @@ -356,11 +356,11 @@ smb2_adjust_credits(struct TCP_Server_Info *server, scredits =3D server->credits; in_flight =3D server->in_flight; spin_unlock(&server->req_lock); wake_up(&server->request_q); =20 - trace_smb3_adj_credits(server->CurrentMid, + trace_smb3_adj_credits(server->current_mid, server->conn_id, server->hostname, scredits, credits->value - new_val, in_flight); cifs_dbg(FYI, "%s: adjust added %u credits total=3D%d\n", __func__, credits->value - new_val, scredits); =20 @@ -372,23 +372,23 @@ smb2_adjust_credits(struct TCP_Server_Info *server, static __u64 smb2_get_next_mid(struct TCP_Server_Info *server) { __u64 mid; /* for SMB2 we need the current value */ - spin_lock(&server->mid_queue_lock); - mid =3D server->CurrentMid++; - spin_unlock(&server->mid_queue_lock); + spin_lock(&server->mid_counter_lock); + mid =3D server->current_mid++; + spin_unlock(&server->mid_counter_lock); return mid; } =20 static void smb2_revert_current_mid(struct TCP_Server_Info *server, const unsigned int= val) { - spin_lock(&server->mid_queue_lock); - if (server->CurrentMid >=3D val) - server->CurrentMid -=3D val; - spin_unlock(&server->mid_queue_lock); + spin_lock(&server->mid_counter_lock); + if (server->current_mid >=3D val) + server->current_mid -=3D val; + spin_unlock(&server->mid_counter_lock); } =20 static struct mid_q_entry * __smb2_find_mid(struct TCP_Server_Info *server, char *buf, bool dequeue) { @@ -458,13 +458,13 @@ smb2_negotiate(const unsigned int xid, struct cifs_ses *ses, struct TCP_Server_Info *server) { int rc; =20 - spin_lock(&server->mid_queue_lock); - server->CurrentMid =3D 0; - spin_unlock(&server->mid_queue_lock); + spin_lock(&server->mid_counter_lock); + server->current_mid =3D 0; + spin_unlock(&server->mid_counter_lock); rc =3D SMB2_negotiate(xid, ses, server); return rc; } =20 static inline unsigned int @@ -2496,11 +2496,11 @@ smb2_is_status_pending(char *buf, struct TCP_Server= _Info *server) scredits =3D server->credits; in_flight =3D server->in_flight; spin_unlock(&server->req_lock); wake_up(&server->request_q); =20 - trace_smb3_pend_credits(server->CurrentMid, + trace_smb3_pend_credits(server->current_mid, server->conn_id, server->hostname, scredits, le16_to_cpu(shdr->CreditRequest), in_flight); cifs_dbg(FYI, "%s: status pending add %u credits total=3D%d\n", __func__, le16_to_cpu(shdr->CreditRequest), scredits); } diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c index 12dc927aa4a2..8037accc3987 100644 --- a/fs/smb/client/transport.c +++ b/fs/smb/client/transport.c @@ -395,11 +395,11 @@ __smb_send_rqst(struct TCP_Server_Info *server, int n= um_rqst, * If we have only sent part of an SMB then the next SMB could * be taken as the remainder of this one. We need to kill the * socket so the server throws away the partial SMB */ cifs_signal_cifsd_for_reconnect(server, false); - trace_smb3_partial_send_reconnect(server->CurrentMid, + trace_smb3_partial_send_reconnect(server->current_mid, server->conn_id, server->hostname); } smbd_done: /* * there's hardly any use for the layers above to know the @@ -507,11 +507,11 @@ wait_for_free_credits(struct TCP_Server_Info *server,= const int num_credits, *instance =3D server->reconnect_instance; scredits =3D *credits; in_flight =3D server->in_flight; spin_unlock(&server->req_lock); =20 - trace_smb3_nblk_credits(server->CurrentMid, + trace_smb3_nblk_credits(server->current_mid, server->conn_id, server->hostname, scredits, -1, in_flight); cifs_dbg(FYI, "%s: remove %u credits total=3D%d\n", __func__, 1, scredits); =20 return 0; @@ -540,11 +540,11 @@ wait_for_free_credits(struct TCP_Server_Info *server,= const int num_credits, spin_lock(&server->req_lock); scredits =3D *credits; in_flight =3D server->in_flight; spin_unlock(&server->req_lock); =20 - trace_smb3_credit_timeout(server->CurrentMid, + trace_smb3_credit_timeout(server->current_mid, server->conn_id, server->hostname, scredits, num_credits, in_flight); cifs_server_dbg(VFS, "wait timed out after %d ms\n", timeout); return -EBUSY; @@ -583,11 +583,11 @@ wait_for_free_credits(struct TCP_Server_Info *server,= const int num_credits, scredits =3D *credits; in_flight =3D server->in_flight; spin_unlock(&server->req_lock); =20 trace_smb3_credit_timeout( - server->CurrentMid, + server->current_mid, server->conn_id, server->hostname, scredits, num_credits, in_flight); cifs_server_dbg(VFS, "wait timed out after %d ms\n", timeout); return -EBUSY; @@ -613,11 +613,11 @@ wait_for_free_credits(struct TCP_Server_Info *server,= const int num_credits, } scredits =3D *credits; in_flight =3D server->in_flight; spin_unlock(&server->req_lock); =20 - trace_smb3_waitff_credits(server->CurrentMid, + trace_smb3_waitff_credits(server->current_mid, server->conn_id, server->hostname, scredits, -(num_credits), in_flight); cifs_dbg(FYI, "%s: remove %u credits total=3D%d\n", __func__, num_credits, scredits); break; @@ -664,11 +664,11 @@ wait_for_compound_request(struct TCP_Server_Info *ser= ver, int num, * Return immediately if no requests in flight since we will be * stuck on waiting for credits. */ if (server->in_flight =3D=3D 0) { spin_unlock(&server->req_lock); - trace_smb3_insufficient_credits(server->CurrentMid, + trace_smb3_insufficient_credits(server->current_mid, server->conn_id, server->hostname, scredits, num, in_flight); cifs_dbg(FYI, "%s: %d requests in flight, needed %d total=3D%d\n", __func__, in_flight, num, scredits); return -EDEADLK; --=20 2.39.2 From nobody Sun Oct 5 12:52:20 2025 Received: from dggsgout12.his.huawei.com (dggsgout12.his.huawei.com [45.249.212.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1B2111E834E; Mon, 4 Aug 2025 13:47:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754315247; cv=none; b=ZJpBWPJOk+h3lekynCs0C5xpM4/jBui2yvpmuoHBFzrTGy/O0E4zL0JGVOK30jKgX+Ypivq/wQgzo1WSEJMf001QA/1GhP3ht7Nf3o+wqH+a/9GKxsmXMvmuD5nOEKuoaaEnNO7FrfQ+tKCRKlYusBm/k7S5RXbRmAxopkiXw0g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754315247; c=relaxed/simple; bh=imkFBcLfKj6csPi/5yH3WtYODf8JhyeTHuCgCeD5WwU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=binAbq7pc9Z1HZUyyWEbALp38Ur9pnpFV/qBQXGYbWogdvf1byisGbim0x3aY3qGBftO5WiGvg11wFtEIQ57q0isSvtPxDmGLQmWqAx2pcW5/LVqtRAU0yA2VqyqJLIBZDJ3J2Vp919O5d9na+TOI3xDLlcklPn4UP1j9cNZjf8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.216]) by dggsgout12.his.huawei.com (SkyGuard) with ESMTPS id 4bwdCZ36NGzKHMr1; Mon, 4 Aug 2025 21:47:22 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id 721781A12FB; Mon, 4 Aug 2025 21:47:21 +0800 (CST) Received: from huaweicloud.com (unknown [10.175.104.67]) by APP4 (Coremail) with SMTP id gCh0CgAHgxPjuZBoXT8zCg--.8001S7; Mon, 04 Aug 2025 21:47:21 +0800 (CST) From: Wang Zhaolong To: sfrench@samba.org, pshilov@microsoft.com Cc: linux-cifs@vger.kernel.org, samba-technical@lists.samba.org, linux-kernel@vger.kernel.org, chengzhihao1@huawei.com, wangzhaolong@huaweicloud.com, yi.zhang@huawei.com, yangerkun@huawei.com Subject: [PATCH 3/4] smb: client: smb: client: eliminate mid_flags field Date: Mon, 4 Aug 2025 21:40:05 +0800 Message-Id: <20250804134006.3609555-4-wangzhaolong@huaweicloud.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20250804134006.3609555-1-wangzhaolong@huaweicloud.com> References: <20250804134006.3609555-1-wangzhaolong@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: gCh0CgAHgxPjuZBoXT8zCg--.8001S7 X-Coremail-Antispam: 1UD129KBjvJXoW3Xr1rXFW3uFykZr18Xr4DCFg_yoWfAF1DpF WFqFW7Cr4rJa9rZ397Ja18Aw4rZwn5uFnrGrWfGry3tFZ7urn8Xrn7KryY9Fy3WFZIg3sa 9F4jy3yqv3W0qaUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBC14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_JrWl82xGYIkIc2 x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2z4x0 Y4vE2Ix0cI8IcVAFwI0_Ar0_tr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJw A2z4x0Y4vEx4A2jsIE14v26rxl6s0DM28EF7xvwVC2z280aVCY1x0267AKxVW0oVCq3wAS 0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2 IY67AKxVWUJVWUGwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0 Y48IcxkI7VAKI48JM4x0x7Aq67IIx4CEVc8vx2IErcIFxwCY1x0262kKe7AKxVWUtVW8Zw CF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j 6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw0_GFylIxkGc2Ij64 vIr41lIxAIcVC0I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr0_ Cr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4j6F4UMIIF0x vEx4A2jsIEc7CjxVAFwI0_Gr1j6F4UJbIYCTnIWIevJa73UjIFyTuYvjfUO_MaUUUUU X-CM-SenderInfo: pzdqw6xkdrz0tqj6x35dzhxuhorxvhhfrp/ Content-Type: text/plain; charset="utf-8" This is step 3/4 of a patch series to fix mid_q_entry memory leaks caused by race conditions in callback execution. Replace the mid_flags bitmask with dedicated boolean fields to simplify locking logic and improve code readability: - Replace MID_DELETED with bool deleted_from_q - Replace MID_WAIT_CANCELLED with bool wait_cancelled - Remove mid_flags field entirely The new boolean fields have clearer semantics: - deleted_from_q: whether mid has been removed from pending_mid_q - wait_cancelled: whether request was cancelled during wait This change reduces memory usage (from 4-byte bitmask to 2 boolean flags) and eliminates confusion about which lock protects which flag bits, preparing for per-mid locking in the next patch. Signed-off-by: Wang Zhaolong --- fs/smb/client/cifsglob.h | 9 +++------ fs/smb/client/connect.c | 10 +++++----- fs/smb/client/smb2ops.c | 4 ++-- fs/smb/client/transport.c | 12 ++++++------ 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 1844afdf1e41..536dff5b4a9c 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -1728,13 +1728,14 @@ struct mid_q_entry { 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 mid_flags; __le16 command; /* smb command code */ unsigned int optype; /* operation type */ + 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 */ }; @@ -1892,14 +1893,10 @@ static inline bool is_replayable_error(int error) #define MID_RESPONSE_MALFORMED 0x10 #define MID_SHUTDOWN 0x20 #define MID_RESPONSE_READY 0x40 /* ready for other process handle the rs= p */ #define MID_RC 0x80 /* mid_rc contains custom rc */ =20 -/* Flags */ -#define MID_WAIT_CANCELLED 1 /* Cancelled while waiting for response */ -#define MID_DELETED 2 /* Mid has been dequeued/deleted */ - /* Types of response buffer returned from SendReceive2 */ #define CIFS_NO_BUFFER 0 /* Response buffer not returned */ #define CIFS_SMALL_BUFFER 1 #define CIFS_LARGE_BUFFER 2 #define CIFS_IOVEC 4 /* array of response buffers */ @@ -2007,11 +2004,11 @@ require use of the stronger protocol */ * GlobalMid_Lock GlobalMaxActiveXid init_cifs * GlobalCurrentXid * GlobalTotalActiveXid * TCP_Server_Info->srv_lock (anything in struct not protected by another = lock and can change) * TCP_Server_Info->mid_queue_lock TCP_Server_Info->pending_mid_q cifs_get= _tcp_session - * (any changes in mid_q_entry fields) + * mid_q_entry->deleted_from_q * TCP_Server_Info->mid_counter_lock TCP_Server_Info->current_mid ci= fs_get_tcp_session * TCP_Server_Info->req_lock TCP_Server_Info->in_flight cifs_get_tcp_sessi= on * ->credits * ->echo_credits * ->oplock_credits diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 74ad5881ee45..587845a2452d 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -325,11 +325,11 @@ cifs_abort_connection(struct TCP_Server_Info *server) list_for_each_entry_safe(mid, nmid, &server->pending_mid_q, qhead) { kref_get(&mid->refcount); if (mid->mid_state =3D=3D MID_REQUEST_SUBMITTED) mid->mid_state =3D MID_RETRY_NEEDED; list_move(&mid->qhead, &retry_list); - mid->mid_flags |=3D MID_DELETED; + mid->deleted_from_q =3D true; } spin_unlock(&server->mid_queue_lock); cifs_server_unlock(server); =20 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__); @@ -886,11 +886,11 @@ is_smb_response(struct TCP_Server_Info *server, unsig= ned char type) */ spin_lock(&server->mid_queue_lock); list_for_each_entry_safe(mid, nmid, &server->pending_mid_q, qhead) { kref_get(&mid->refcount); list_move(&mid->qhead, &dispose_list); - mid->mid_flags |=3D MID_DELETED; + mid->deleted_from_q =3D true; } spin_unlock(&server->mid_queue_lock); =20 /* Now try to reconnect once with NetBIOS session. */ server->with_rfc1001 =3D true; @@ -964,16 +964,16 @@ dequeue_mid(struct mid_q_entry *mid, bool malformed) mid->mid_state =3D MID_RESPONSE_MALFORMED; /* * Trying to handle/dequeue a mid after the send_recv() * function has finished processing it is a bug. */ - if (mid->mid_flags & MID_DELETED) { + if (mid->deleted_from_q =3D=3D true) { spin_unlock(&mid->server->mid_queue_lock); pr_warn_once("trying to dequeue a deleted mid\n"); } else { list_del_init(&mid->qhead); - mid->mid_flags |=3D MID_DELETED; + mid->deleted_from_q =3D true; spin_unlock(&mid->server->mid_queue_lock); } } =20 static unsigned int @@ -1106,11 +1106,11 @@ clean_demultiplex_info(struct TCP_Server_Info *serv= er) mid_entry =3D list_entry(tmp, struct mid_q_entry, qhead); cifs_dbg(FYI, "Clearing mid %llu\n", mid_entry->mid); kref_get(&mid_entry->refcount); mid_entry->mid_state =3D MID_SHUTDOWN; list_move(&mid_entry->qhead, &dispose_list); - mid_entry->mid_flags |=3D MID_DELETED; + mid_entry->deleted_from_q =3D true; } spin_unlock(&server->mid_queue_lock); =20 /* now walk dispose list and issue callbacks */ list_for_each_safe(tmp, tmp2, &dispose_list) { diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index da2cb9585404..2643d86a5b5f 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -407,11 +407,11 @@ __smb2_find_mid(struct TCP_Server_Info *server, char = *buf, bool dequeue) (mid->mid_state =3D=3D MID_REQUEST_SUBMITTED) && (mid->command =3D=3D shdr->Command)) { kref_get(&mid->refcount); if (dequeue) { list_del_init(&mid->qhead); - mid->mid_flags |=3D MID_DELETED; + mid->deleted_from_q =3D true; } spin_unlock(&server->mid_queue_lock); return mid; } } @@ -4815,11 +4815,11 @@ static void smb2_decrypt_offload(struct work_struct= *work) spin_unlock(&dw->server->srv_lock); mid->callback(mid); } else { spin_lock(&dw->server->mid_queue_lock); mid->mid_state =3D MID_REQUEST_SUBMITTED; - mid->mid_flags &=3D ~(MID_DELETED); + mid->deleted_from_q =3D false; list_add_tail(&mid->qhead, &dw->server->pending_mid_q); spin_unlock(&dw->server->mid_queue_lock); spin_unlock(&dw->server->srv_lock); } diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c index 8037accc3987..ca9358c24ceb 100644 --- a/fs/smb/client/transport.c +++ b/fs/smb/client/transport.c @@ -87,11 +87,11 @@ void __release_mid(struct kref *refcount) unsigned long now; unsigned long roundtrip_time; #endif struct TCP_Server_Info *server =3D midEntry->server; =20 - if (midEntry->resp_buf && (midEntry->mid_flags & MID_WAIT_CANCELLED) && + if (midEntry->resp_buf && (midEntry->wait_cancelled) && (midEntry->mid_state =3D=3D MID_RESPONSE_RECEIVED || midEntry->mid_state =3D=3D MID_RESPONSE_READY) && server->ops->handle_cancelled_mid) server->ops->handle_cancelled_mid(midEntry, server); =20 @@ -159,13 +159,13 @@ void __release_mid(struct kref *refcount) =20 void delete_mid(struct mid_q_entry *mid) { spin_lock(&mid->server->mid_queue_lock); - if (!(mid->mid_flags & MID_DELETED)) { + if (mid->deleted_from_q =3D=3D false) { list_del_init(&mid->qhead); - mid->mid_flags |=3D MID_DELETED; + mid->deleted_from_q =3D true; } spin_unlock(&mid->server->mid_queue_lock); =20 release_mid(mid); } @@ -896,13 +896,13 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct = TCP_Server_Info *server) break; case MID_RC: rc =3D mid->mid_rc; break; default: - if (!(mid->mid_flags & MID_DELETED)) { + if (mid->deleted_from_q =3D=3D false) { list_del_init(&mid->qhead); - mid->mid_flags |=3D MID_DELETED; + mid->deleted_from_q =3D true; } spin_unlock(&server->mid_queue_lock); cifs_server_dbg(VFS, "%s: invalid mid state mid=3D%llu state=3D%d\n", __func__, mid->mid, mid->mid_state); rc =3D -EIO; @@ -1212,11 +1212,11 @@ compound_send_recv(const unsigned int xid, struct c= ifs_ses *ses, for (; i < num_rqst; i++) { cifs_server_dbg(FYI, "Cancelling wait for mid %llu cmd: %d\n", midQ[i]->mid, le16_to_cpu(midQ[i]->command)); send_cancel(server, &rqst[i], midQ[i]); spin_lock(&server->mid_queue_lock); - midQ[i]->mid_flags |=3D MID_WAIT_CANCELLED; + midQ[i]->wait_cancelled =3D true; if (midQ[i]->mid_state =3D=3D MID_REQUEST_SUBMITTED || midQ[i]->mid_state =3D=3D MID_RESPONSE_RECEIVED) { midQ[i]->callback =3D cifs_cancelled_callback; cancelled_mid[i] =3D true; credits[i].value =3D 0; --=20 2.39.2 From nobody Sun Oct 5 12:52:20 2025 Received: from dggsgout12.his.huawei.com (dggsgout12.his.huawei.com [45.249.212.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1B2F21F2C45; Mon, 4 Aug 2025 13:47:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754315247; cv=none; b=jFy5QmuaJTU5HXsqMrnIAG6sqAMdSQusFQOftUk5MhFBaECk9aZPyyKn15h+nGf/OJp4A5W11aWX/Ouvvp9eQLfA5TwXTAArWmVHazYXqpQ+UGAJhZjZl9PYhPblW/4t6GpLnYPNSSWcIjWhq3r/l0XzNTiQuYE90KKFxN07GQs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754315247; c=relaxed/simple; bh=sU1WSI6K0LVwwD59jB2LP5tJAS+FcxiDHZr8Oh6mGPU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=S5L6lQ06Z1A39GiSVwsnVrfBdkChowJ0Nyd6UrYrY+AnHWBQnv5th3qeOkRP2mz5sgoZkFPyGjVsKDKw/TPU8wTbAozhqla4wKB+bRi7d3DRSOlnkENW45R2fzllXUfFh+8LR+cc7LjCZsX8//B5uUJUzeCvAE0VMFcvk/5ShGk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.93.142]) by dggsgout12.his.huawei.com (SkyGuard) with ESMTPS id 4bwdCZ6NhZzKHMwF; Mon, 4 Aug 2025 21:47:22 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id E136C1A0359; Mon, 4 Aug 2025 21:47:21 +0800 (CST) Received: from huaweicloud.com (unknown [10.175.104.67]) by APP4 (Coremail) with SMTP id gCh0CgAHgxPjuZBoXT8zCg--.8001S8; Mon, 04 Aug 2025 21:47:21 +0800 (CST) From: Wang Zhaolong To: sfrench@samba.org, pshilov@microsoft.com Cc: linux-cifs@vger.kernel.org, samba-technical@lists.samba.org, linux-kernel@vger.kernel.org, chengzhihao1@huawei.com, wangzhaolong@huaweicloud.com, yi.zhang@huawei.com, yangerkun@huawei.com Subject: [PATCH 4/4] smb: client: fix mid_q_entry memleak leak with per-mid locking Date: Mon, 4 Aug 2025 21:40:06 +0800 Message-Id: <20250804134006.3609555-5-wangzhaolong@huaweicloud.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20250804134006.3609555-1-wangzhaolong@huaweicloud.com> References: <20250804134006.3609555-1-wangzhaolong@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: gCh0CgAHgxPjuZBoXT8zCg--.8001S8 X-Coremail-Antispam: 1UD129KBjvAXoW3uw4DZrWfCF43GF45ZrykuFg_yoW8CryDuo Z7X3s5Zr4UWr92yFy0yFnxtFZ7XFyqgay7Zrs5Cr45Z3ZayFWjqryUtw45Jay5Zr48AwsI v3yxJFnYqa9rJrn5n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUOU7AC8VAFwI0_Wr0E3s1l1xkIjI8I6I8E6xAIw20EY4v20xva j40_Wr0E3s1l1IIY67AEw4v_Jr0_Jr4l82xGYIkIc2x26280x7IE14v26r126s0DM28Irc Ia0xkI8VCY1x0267AKxVW5JVCq3wA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK021l 84ACjcxK6xIIjxv20xvE14v26F1j6w1UM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26r4UJV WxJr1l84ACjcxK6I8E87Iv67AKxVW0oVCq3wA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_GcCE 3s1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E2I x0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkEbVWUJVW8 JwACjcxG0xvY0x0EwIxGrwACjI8F5VA0II8E6IAqYI8I648v4I1lc7CjxVAaw2AFwI0_Jw 0_GFyl42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AK xVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r1q6r43MIIYrx kI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_Jr0_JF4lIxAIcVC0I7IYx2IY6xkF7I0E14v2 6r4j6F4UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWxJw CI42IY6I8E87Iv6xkF7I0E14v26r4UJVWxJrUvcSsGvfC2KfnxnUUI43ZEXa7VUbPC7UUU UUU== X-CM-SenderInfo: pzdqw6xkdrz0tqj6x35dzhxuhorxvhhfrp/ Content-Type: text/plain; charset="utf-8" This is step 4/4 of a patch series to fix mid_q_entry memory leaks caused by race conditions in callback execution. In compound_send_recv(), when wait_for_response() is interrupted by signals, the code attempts to cancel pending requests by changing their callbacks to cifs_cancelled_callback. However, there's a race condition between signal interruption and network response processing that causes both mid_q_entry and server buffer leaks: ``` User foreground process cifsd cifs_readdir open_cached_dir cifs_send_recv compound_send_recv smb2_setup_request smb2_mid_entry_alloc smb2_get_mid_entry smb2_mid_entry_alloc mempool_alloc // alloc mid kref_init(&temp->refcount); // refcount =3D 1 mid[0]->callback =3D cifs_compound_callback; mid[1]->callback =3D cifs_compound_last_callback; smb_send_rqst rc =3D wait_for_response wait_event_state TASK_KILLABLE cifs_demultiplex_thread allocate_buffers server->bigbuf =3D cifs_buf_get() standard_receive3 ->find_mid() smb2_find_mid __smb2_find_mid kref_get(&mid->refcount) // +1 cifs_handle_standard handle_mid /* bigbuf will also leak */ mid->resp_buf =3D server->bigbuf server->bigbuf =3D NULL; dequeue_mid /* in for loop */ mids[0]->callback cifs_compound_callback /* Signal interrupts wait: rc =3D -ERESTARTSYS */ /* if (... || midQ[i]->mid_state =3D=3D MID_RESPONSE_RECEIVED) *? midQ[0]->callback =3D cifs_cancelled_callback; cancelled_mid[i] =3D true; /* The change comes too late */ mid->mid_state =3D MID_RESPONSE_READY release_mid // -1 /* cancelled_mid[i] =3D=3D true causes mid won't be released in compound_send_recv cleanup */ /* cifs_cancelled_callback won't executed to release mid */ ``` The callback assignment (mid->callback =3D cifs_cancelled_callback) and callback execution (mid->callback(mid)) are not atomic, allowing the network thread to execute the old callback even after cancellation. Solution: Add per-mid locking to ensure atomic callback execution: - Add spinlock_t mid_lock to struct mid_q_entry - Protect mid_state, callback, and related fields with mid_lock - Add mid_execute_callback() wrapper for safe callback execution - Use mid_lock in compound_send_recv() cancellation logic Key changes: - Initialize mid_lock in alloc_mid() and smb2_mid_entry_alloc() - Replace direct mid->callback() calls with mid_execute_callback() - Protect all mid state changes with appropriate locks - Update locking documentation This ensures that either the original callback or the cancellation callback executes atomically, preventing reference count leaks when requests are interrupted by signals. Link: https://bugzilla.kernel.org/show_bug.cgi?id=3D220404 Fixes: ee258d79159a ("CIFS: Move credit processing to mid callbacks for SMB= 3") Signed-off-by: Wang Zhaolong --- fs/smb/client/cifs_debug.c | 4 ++++ fs/smb/client/cifsglob.h | 5 +++++ fs/smb/client/connect.c | 22 ++++++++++++++++++---- fs/smb/client/smb1ops.c | 6 ++++++ fs/smb/client/smb2ops.c | 15 +++++++++------ fs/smb/client/smb2transport.c | 1 + fs/smb/client/transport.c | 29 ++++++++++++++++++----------- 7 files changed, 61 insertions(+), 21 deletions(-) diff --git a/fs/smb/client/cifs_debug.c b/fs/smb/client/cifs_debug.c index 80d6a51b8c11..4708afc9106c 100644 --- a/fs/smb/client/cifs_debug.c +++ b/fs/smb/client/cifs_debug.c @@ -60,10 +60,11 @@ void cifs_dump_mids(struct TCP_Server_Info *server) return; =20 cifs_dbg(VFS, "Dump pending requests:\n"); spin_lock(&server->mid_queue_lock); list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) { + spin_lock(&mid_entry->mid_lock); cifs_dbg(VFS, "State: %d Cmd: %d Pid: %d Cbdata: %p Mid %llu\n", mid_entry->mid_state, le16_to_cpu(mid_entry->command), mid_entry->pid, mid_entry->callback_data, @@ -80,10 +81,11 @@ void cifs_dump_mids(struct TCP_Server_Info *server) if (mid_entry->resp_buf) { cifs_dump_detail(mid_entry->resp_buf, server); cifs_dump_mem("existing buf: ", mid_entry->resp_buf, 62); } + spin_unlock(&mid_entry->mid_lock); } spin_unlock(&server->mid_queue_lock); #endif /* CONFIG_CIFS_DEBUG2 */ } =20 @@ -672,16 +674,18 @@ static int cifs_debug_data_proc_show(struct seq_file = *m, void *v) =20 seq_printf(m, "\n\tServer ConnectionId: 0x%llx", chan_server->conn_id); spin_lock(&chan_server->mid_queue_lock); list_for_each_entry(mid_entry, &chan_server->pending_mid_q, qhead) { + spin_lock(&mid_entry->mid_lock); seq_printf(m, "\n\t\tState: %d com: %d pid: %d cbdata: %p mid %llu", mid_entry->mid_state, le16_to_cpu(mid_entry->command), mid_entry->pid, mid_entry->callback_data, mid_entry->mid); + spin_unlock(&mid_entry->mid_lock); } spin_unlock(&chan_server->mid_queue_lock); } spin_unlock(&ses->chan_lock); seq_puts(m, "\n--\n"); diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 536dff5b4a9c..430163a878d9 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -1357,10 +1357,11 @@ struct tcon_link { struct cifs_tcon *tl_tcon; }; =20 extern struct tcon_link *cifs_sb_tlink(struct cifs_sb_info *cifs_sb); extern void smb3_free_compound_rqst(int num_rqst, struct smb_rqst *rqst); +extern inline void mid_execute_callback(struct mid_q_entry *mid); =20 static inline struct cifs_tcon * tlink_tcon(struct tcon_link *tlink) { return tlink->tl_tcon; @@ -1730,10 +1731,11 @@ struct mid_q_entry { 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 */ __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 */ @@ -2034,10 +2036,13 @@ require use of the stronger protocol */ * init_cached_dir * cifsFileInfo->fh_mutex cifsFileInfo cifs_new_fileinfo * cifsFileInfo->file_info_lock cifsFileInfo->count cifs_new_fileinfo * ->invalidHandle initiate_cifs_search * ->oplock_break_cancelled + * mid_q_entry->mid_lock mid_q_entry->mid_state alloc_mid + * mid_q_entry->callback smb2_mid_entry_alloc + * (Ensure that mid->callback is executed atomically) *************************************************************************= ***/ =20 #ifdef DECLARE_GLOBALS_HERE #define GLOBAL_EXTERN #else diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 587845a2452d..2d85554b8041 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -288,10 +288,18 @@ cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Serv= er_Info *server, } } spin_unlock(&cifs_tcp_ses_lock); } =20 +inline void mid_execute_callback(struct mid_q_entry *mid) +{ + spin_lock(&mid->mid_lock); + if (mid->callback) + mid->callback(mid); + spin_unlock(&mid->mid_lock); +} + static void cifs_abort_connection(struct TCP_Server_Info *server) { struct mid_q_entry *mid, *nmid; struct list_head retry_list; @@ -322,22 +330,24 @@ cifs_abort_connection(struct TCP_Server_Info *server) INIT_LIST_HEAD(&retry_list); cifs_dbg(FYI, "%s: moving mids to private list\n", __func__); spin_lock(&server->mid_queue_lock); list_for_each_entry_safe(mid, nmid, &server->pending_mid_q, qhead) { kref_get(&mid->refcount); + spin_lock(&mid->mid_lock); if (mid->mid_state =3D=3D MID_REQUEST_SUBMITTED) mid->mid_state =3D MID_RETRY_NEEDED; + spin_unlock(&mid->mid_lock); list_move(&mid->qhead, &retry_list); mid->deleted_from_q =3D true; } spin_unlock(&server->mid_queue_lock); cifs_server_unlock(server); =20 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__); list_for_each_entry_safe(mid, nmid, &retry_list, qhead) { list_del_init(&mid->qhead); - mid->callback(mid); + mid_execute_callback(mid); release_mid(mid); } =20 if (cifs_rdma_enabled(server)) { cifs_server_lock(server); @@ -917,11 +927,11 @@ is_smb_response(struct TCP_Server_Info *server, unsig= ned char type) */ list_for_each_entry_safe(mid, nmid, &dispose_list, qhead) { list_del_init(&mid->qhead); mid->mid_rc =3D mid_rc; mid->mid_state =3D MID_RC; - mid->callback(mid); + mid_execute_callback(mid); release_mid(mid); } =20 /* * If reconnect failed then wait two seconds. In most @@ -956,14 +966,16 @@ dequeue_mid(struct mid_q_entry *mid, bool malformed) { #ifdef CONFIG_CIFS_STATS2 mid->when_received =3D jiffies; #endif spin_lock(&mid->server->mid_queue_lock); + spin_lock(&mid->mid_lock); if (!malformed) mid->mid_state =3D MID_RESPONSE_RECEIVED; else mid->mid_state =3D MID_RESPONSE_MALFORMED; + spin_unlock(&mid->mid_lock); /* * Trying to handle/dequeue a mid after the send_recv() * function has finished processing it is a bug. */ if (mid->deleted_from_q =3D=3D true) { @@ -1104,22 +1116,24 @@ clean_demultiplex_info(struct TCP_Server_Info *serv= er) spin_lock(&server->mid_queue_lock); list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { mid_entry =3D list_entry(tmp, struct mid_q_entry, qhead); cifs_dbg(FYI, "Clearing mid %llu\n", mid_entry->mid); kref_get(&mid_entry->refcount); + spin_lock(&mid_entry->mid_lock); mid_entry->mid_state =3D MID_SHUTDOWN; + spin_unlock(&mid_entry->mid_lock); list_move(&mid_entry->qhead, &dispose_list); mid_entry->deleted_from_q =3D true; } spin_unlock(&server->mid_queue_lock); =20 /* now walk dispose list and issue callbacks */ list_for_each_safe(tmp, tmp2, &dispose_list) { mid_entry =3D list_entry(tmp, struct mid_q_entry, qhead); cifs_dbg(FYI, "Callback mid %llu\n", mid_entry->mid); list_del_init(&mid_entry->qhead); - mid_entry->callback(mid_entry); + mid_execute_callback(mid_entry); release_mid(mid_entry); } /* 1/8th of sec is more than enough time for them to exit */ msleep(125); } @@ -1392,11 +1406,11 @@ cifs_demultiplex_thread(void *p) "Share deleted. Reconnect needed"); } } =20 if (!mids[i]->multiRsp || mids[i]->multiEnd) - mids[i]->callback(mids[i]); + mid_execute_callback(mids[i]); =20 release_mid(mids[i]); } else if (server->ops->is_oplock_break && server->ops->is_oplock_break(bufs[i], server)) { diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c index 13f600a3d0c4..6a6b09cfcefa 100644 --- a/fs/smb/client/smb1ops.c +++ b/fs/smb/client/smb1ops.c @@ -95,17 +95,20 @@ cifs_find_mid(struct TCP_Server_Info *server, char *buf= fer) struct smb_hdr *buf =3D (struct smb_hdr *)buffer; struct mid_q_entry *mid; =20 spin_lock(&server->mid_queue_lock); list_for_each_entry(mid, &server->pending_mid_q, qhead) { + spin_lock(&mid->mid_lock); if (compare_mid(mid->mid, buf) && mid->mid_state =3D=3D MID_REQUEST_SUBMITTED && le16_to_cpu(mid->command) =3D=3D buf->Command) { + spin_unlock(&mid->mid_lock); kref_get(&mid->refcount); spin_unlock(&server->mid_queue_lock); return mid; } + spin_unlock(&mid->mid_lock); } spin_unlock(&server->mid_queue_lock); return NULL; } =20 @@ -198,16 +201,19 @@ cifs_get_next_mid(struct TCP_Server_Info *server) =20 num_mids =3D 0; spin_lock(&server->mid_queue_lock); list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) { ++num_mids; + spin_lock(&mid_entry->mid_lock); if (mid_entry->mid =3D=3D cur_mid && mid_entry->mid_state =3D=3D MID_REQUEST_SUBMITTED) { + spin_unlock(&mid_entry->mid_lock); /* This mid is in use, try a different one */ collision =3D true; break; } + spin_unlock(&mid_entry->mid_lock); } spin_unlock(&server->mid_queue_lock); =20 /* * if we have more than 32k mids in the list, then something diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 2643d86a5b5f..14c572e04894 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -4803,27 +4803,30 @@ static void smb2_decrypt_offload(struct work_struct= *work) #endif if (dw->server->ops->is_network_name_deleted) dw->server->ops->is_network_name_deleted(dw->buf, dw->server); =20 - mid->callback(mid); + mid_execute_callback(mid); } else { spin_lock(&dw->server->srv_lock); if (dw->server->tcpStatus =3D=3D CifsNeedReconnect) { - spin_lock(&dw->server->mid_queue_lock); - mid->mid_state =3D MID_RETRY_NEEDED; - spin_unlock(&dw->server->mid_queue_lock); spin_unlock(&dw->server->srv_lock); - mid->callback(mid); + spin_lock(&mid->mid_lock); + mid->mid_state =3D MID_RETRY_NEEDED; + if (mid->callback) + mid->callback(mid); + spin_unlock(&mid->mid_lock); } else { + spin_unlock(&dw->server->srv_lock); spin_lock(&dw->server->mid_queue_lock); + spin_lock(&mid->mid_lock); mid->mid_state =3D MID_REQUEST_SUBMITTED; + spin_unlock(&mid->mid_lock); mid->deleted_from_q =3D false; list_add_tail(&mid->qhead, &dw->server->pending_mid_q); spin_unlock(&dw->server->mid_queue_lock); - spin_unlock(&dw->server->srv_lock); } } release_mid(mid); } =20 diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c index ff9ef7fcd010..bc0e92eb2b64 100644 --- a/fs/smb/client/smb2transport.c +++ b/fs/smb/client/smb2transport.c @@ -769,10 +769,11 @@ smb2_mid_entry_alloc(const struct smb2_hdr *shdr, } =20 temp =3D mempool_alloc(cifs_mid_poolp, GFP_NOFS); memset(temp, 0, sizeof(struct mid_q_entry)); kref_init(&temp->refcount); + spin_lock_init(&temp->mid_lock); temp->mid =3D le64_to_cpu(shdr->MessageId); temp->credits =3D credits > 0 ? credits : 1; temp->pid =3D current->pid; temp->command =3D shdr->Command; /* Always LE */ temp->when_alloc =3D jiffies; diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c index ca9358c24ceb..8bbcecf2225d 100644 --- a/fs/smb/client/transport.c +++ b/fs/smb/client/transport.c @@ -52,10 +52,11 @@ alloc_mid(const struct smb_hdr *smb_buffer, struct TCP_= Server_Info *server) } =20 temp =3D mempool_alloc(cifs_mid_poolp, GFP_NOFS); memset(temp, 0, sizeof(struct mid_q_entry)); kref_init(&temp->refcount); + spin_lock_init(&temp->mid_lock); temp->mid =3D get_mid(smb_buffer); temp->pid =3D current->pid; temp->command =3D cpu_to_le16(smb_buffer->Command); cifs_dbg(FYI, "For smb_command %d\n", smb_buffer->Command); /* easier to use jiffies */ @@ -875,17 +876,17 @@ SendReceiveNoRsp(const unsigned int xid, struct cifs_= ses *ses, static int cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *serv= er) { int rc =3D 0; =20 + spin_lock(&mid->mid_lock); cifs_dbg(FYI, "%s: cmd=3D%d mid=3D%llu state=3D%d\n", __func__, le16_to_cpu(mid->command), mid->mid, mid->mid_state); =20 - spin_lock(&server->mid_queue_lock); switch (mid->mid_state) { case MID_RESPONSE_READY: - spin_unlock(&server->mid_queue_lock); + spin_unlock(&mid->mid_lock); return rc; case MID_RETRY_NEEDED: rc =3D -EAGAIN; break; case MID_RESPONSE_MALFORMED: @@ -896,21 +897,25 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct = TCP_Server_Info *server) break; case MID_RC: rc =3D mid->mid_rc; break; default: + cifs_server_dbg(VFS, "%s: invalid mid state mid=3D%llu state=3D%d\n", + __func__, mid->mid, mid->mid_state); + spin_unlock(&mid->mid_lock); + + spin_lock(&server->mid_queue_lock); if (mid->deleted_from_q =3D=3D false) { list_del_init(&mid->qhead); mid->deleted_from_q =3D true; } spin_unlock(&server->mid_queue_lock); - cifs_server_dbg(VFS, "%s: invalid mid state mid=3D%llu state=3D%d\n", - __func__, mid->mid, mid->mid_state); + rc =3D -EIO; goto sync_mid_done; } - spin_unlock(&server->mid_queue_lock); + spin_unlock(&mid->mid_lock); =20 sync_mid_done: release_mid(mid); return rc; } @@ -1212,17 +1217,19 @@ compound_send_recv(const unsigned int xid, struct c= ifs_ses *ses, for (; i < num_rqst; i++) { cifs_server_dbg(FYI, "Cancelling wait for mid %llu cmd: %d\n", midQ[i]->mid, le16_to_cpu(midQ[i]->command)); send_cancel(server, &rqst[i], midQ[i]); spin_lock(&server->mid_queue_lock); + spin_lock(&midQ[i]->mid_lock); midQ[i]->wait_cancelled =3D true; if (midQ[i]->mid_state =3D=3D MID_REQUEST_SUBMITTED || midQ[i]->mid_state =3D=3D MID_RESPONSE_RECEIVED) { midQ[i]->callback =3D cifs_cancelled_callback; cancelled_mid[i] =3D true; credits[i].value =3D 0; } + spin_unlock(&midQ[i]->mid_lock); spin_unlock(&server->mid_queue_lock); } } =20 for (i =3D 0; i < num_rqst; i++) { @@ -1421,20 +1428,20 @@ SendReceive(const unsigned int xid, struct cifs_ses= *ses, goto out; =20 rc =3D wait_for_response(server, midQ); if (rc !=3D 0) { send_cancel(server, &rqst, midQ); - spin_lock(&server->mid_queue_lock); + spin_lock(&midQ->mid_lock); if (midQ->mid_state =3D=3D MID_REQUEST_SUBMITTED || midQ->mid_state =3D=3D MID_RESPONSE_RECEIVED) { /* no longer considered to be "in-flight" */ midQ->callback =3D release_mid; - spin_unlock(&server->mid_queue_lock); + spin_unlock(&midQ->mid_lock); add_credits(server, &credits, 0); return rc; } - spin_unlock(&server->mid_queue_lock); + spin_unlock(&midQ->mid_lock); } =20 rc =3D cifs_sync_mid_result(midQ, server); if (rc !=3D 0) { add_credits(server, &credits, 0); @@ -1603,19 +1610,19 @@ SendReceiveBlockingLock(const unsigned int xid, str= uct cifs_tcon *tcon, } =20 rc =3D wait_for_response(server, midQ); if (rc) { send_cancel(server, &rqst, midQ); - spin_lock(&server->mid_queue_lock); + spin_lock(&midQ->mid_lock); if (midQ->mid_state =3D=3D MID_REQUEST_SUBMITTED || midQ->mid_state =3D=3D MID_RESPONSE_RECEIVED) { /* no longer considered to be "in-flight" */ midQ->callback =3D release_mid; - spin_unlock(&server->mid_queue_lock); + spin_unlock(&midQ->mid_lock); return rc; } - spin_unlock(&server->mid_queue_lock); + spin_unlock(&midQ->mid_lock); } =20 /* We got the response - restart system call. */ rstart =3D 1; spin_lock(&server->srv_lock); --=20 2.39.2