From nobody Sat Jul 25 22:03:24 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 496AF3502A8; Mon, 13 Jul 2026 09:47:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783936021; cv=none; b=m95zK/8o8GQ8pUwSc82yBIi89n37Oc2ZNGO2bV38GxE+zXdfyzbsD9NxkjVY/1AbdKApTnQO/W6lJQ1M2C6LKDLCHFTWaZudZtHJmXjDG9OISkqBu6HFERkD1UNCBHQOBXzpsbdzd881sQdvwsTmhMe1CaIH4tzAS6b1Sj2xmdg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783936021; c=relaxed/simple; bh=usXMJycNUqlqgmLibcqdwKEGzxpM8o0oSreTSQUb9aA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=HMME34+twzWHOY12SrH8iJk267qG5E8sUDYtiHfBZHHY2kWv6dQJRtdFi2tOMGSH+53BfvOxiYd5GQ8Pg7Kf58OGZqROW9OUCr0bgrDST3BrGmcCrm7pYO1jI4IeUzdK+Rmo6Kou0RXdUU/4edWhyblU6zpwpiJCOwcUeyJ15vs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=el2LSPKN; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="el2LSPKN" Received: by smtp.kernel.org (Postfix) with ESMTPS id 0471CC2BCF5; Mon, 13 Jul 2026 09:47:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1783936021; bh=usXMJycNUqlqgmLibcqdwKEGzxpM8o0oSreTSQUb9aA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=el2LSPKNzHjg6LhU5aUFX3YaWjTISFWIoFAgX+XzTbVXH1goRizZn2+3NUyVHiOo7 nPthrZHr8LqVoijlVjhc2z/v3FImD9uBapTK+CCticnmJQ1vV2JLz+8i4GsilGqS7Q 5O6N/8qMh32651lhJOEXANfstH6Xd2Dbcgs9xYiSKmyabddoA+lgEejaQhpaKaC7d0 jFsJQxKbvEKKfPVFImiC3Bo9MFBLnJV71ep4aUajOtVXPFbdoaSgcpy0x0TZ6qIDVv 1zXk+diMsy0aCm+v0xe0Rp0rVNgTycn2Ne5a9ODjkSxI9/B4K8W/Mj2OyBe7fihvru 5HFtmhjq8UGlQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id DA535C44501; Mon, 13 Jul 2026 09:47:00 +0000 (UTC) From: Xiubo Li via B4 Relay Date: Mon, 13 Jul 2026 17:46:07 +0800 Subject: [PATCH 1/5] ceph: convert oldest_tid to atomic64_t Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260713-ceph-mdsc-mutex-optimization-v1-1-9ae5ac135c34@clyso.com> References: <20260713-ceph-mdsc-mutex-optimization-v1-0-9ae5ac135c34@clyso.com> In-Reply-To: <20260713-ceph-mdsc-mutex-optimization-v1-0-9ae5ac135c34@clyso.com> To: Ilya Dryomov , Alex Markuze , Viacheslav Dubeyko Cc: ceph-devel@vger.kernel.org, linux-kernel@vger.kernel.org, Xiubo Li X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1783936018; l=4251; i=xiubo.li@clyso.com; s=20260625; h=from:subject:message-id; bh=Ln313jfnyI9iEkGY4T3NBIW+U7Vyr9d7sWpnTOxEXz8=; b=w6QCuGrFzG0BRds+mcufPiJRiYJhpuLjtvuXJWBV46ojnHI33Q2D5nXDGvhXFW3tJToswXE+2 LmxifXAJPC4AitJzrl7xVoGrruSkOA69bo+5IfpLSGlLQFij6kxGFHY X-Developer-Key: i=xiubo.li@clyso.com; a=ed25519; pk=V3NGr0AgAopiUhaLY51ipBkLN5LlcLhjOEfLEq1RoZ8= X-Endpoint-Received: by B4 Relay for xiubo.li@clyso.com/20260625 with auth_id=840 X-Original-From: Xiubo Li Reply-To: xiubo.li@clyso.com From: Xiubo Li The oldest_client_tid sent in the MDS request header is advisory: a stale value is harmless -- at worst the MDS may resend a reply we already have, or skip one we still need (which will just be retried). With the plain u64 read, however, the compiler is free to split or cache the load, which is undefined behaviour when the write side runs under mdsc->mutex on a different CPU. Convert mdsc->oldest_tid from u64 to atomic64_t so that reads are guaranteed to be single-copy atomic on all architectures. This removes the one remaining reason __prepare_send_request() and __send_request() needed to be called under mdsc->mutex, so drop those comments as well. All write sites (__register_request, __unregister_request) still run under mdsc->mutex, so use atomic64_set() for clarity. Signed-off-by: Xiubo Li Reviewed-by: Viacheslav Dubeyko --- fs/ceph/mds_client.c | 21 ++++++++------------- fs/ceph/mds_client.h | 2 +- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 9f84ef2ac6e4..98d0a5baff70 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -1235,8 +1235,9 @@ static void __register_request(struct ceph_mds_client= *mdsc, if (!req->r_mnt_idmap) req->r_mnt_idmap =3D &nop_mnt_idmap; =20 - if (mdsc->oldest_tid =3D=3D 0 && req->r_op !=3D CEPH_MDS_OP_SETFILELOCK) - mdsc->oldest_tid =3D req->r_tid; + if (atomic64_read(&mdsc->oldest_tid) =3D=3D 0 && + req->r_op !=3D CEPH_MDS_OP_SETFILELOCK) + atomic64_set(&mdsc->oldest_tid, req->r_tid); =20 if (dir) { struct ceph_inode_info *ci =3D ceph_inode(dir); @@ -1257,14 +1258,14 @@ static void __unregister_request(struct ceph_mds_cl= ient *mdsc, /* Never leave an unregistered request on an unsafe list! */ list_del_init(&req->r_unsafe_item); =20 - if (req->r_tid =3D=3D mdsc->oldest_tid) { + if (req->r_tid =3D=3D atomic64_read(&mdsc->oldest_tid)) { struct rb_node *p =3D rb_next(&req->r_node); - mdsc->oldest_tid =3D 0; + atomic64_set(&mdsc->oldest_tid, 0); while (p) { struct ceph_mds_request *next_req =3D rb_entry(p, struct ceph_mds_request, r_node); if (next_req->r_op !=3D CEPH_MDS_OP_SETFILELOCK) { - mdsc->oldest_tid =3D next_req->r_tid; + atomic64_set(&mdsc->oldest_tid, next_req->r_tid); break; } p =3D rb_next(p); @@ -1693,7 +1694,7 @@ create_session_full_msg(struct ceph_mds_client *mdsc,= int op, u64 seq) ceph_encode_32(&p, 0); =20 /* version =3D=3D 7, oldest_client_tid */ - ceph_encode_64(&p, mdsc->oldest_tid); + ceph_encode_64(&p, atomic64_read(&mdsc->oldest_tid)); =20 msg->front.iov_len =3D p - msg->front.iov_base; msg->hdr.front_len =3D cpu_to_le32(msg->front.iov_len); @@ -2759,7 +2760,7 @@ static struct ceph_mds_request *__get_oldest_req(stru= ct ceph_mds_client *mdsc) =20 static inline u64 __get_oldest_tid(struct ceph_mds_client *mdsc) { - return mdsc->oldest_tid; + return atomic64_read(&mdsc->oldest_tid); } =20 #if IS_ENABLED(CONFIG_FS_ENCRYPTION) @@ -3438,9 +3439,6 @@ static void complete_request(struct ceph_mds_client *= mdsc, complete_all(&req->r_completion); } =20 -/* - * called under mdsc->mutex - */ static int __prepare_send_request(struct ceph_mds_session *session, struct ceph_mds_request *req, bool drop_cap_releases) @@ -3555,9 +3553,6 @@ static int __prepare_send_request(struct ceph_mds_ses= sion *session, return 0; } =20 -/* - * called under mdsc->mutex - */ static int __send_request(struct ceph_mds_session *session, struct ceph_mds_request *req, bool drop_cap_releases) diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index 731d6ad04956..3b614b5df18c 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -532,7 +532,7 @@ struct ceph_mds_client { spinlock_t snap_empty_lock; /* protect snap_empty */ =20 u64 last_tid; /* most recent mds request */ - u64 oldest_tid; /* oldest incomplete mds request, + atomic64_t oldest_tid; /* oldest incomplete mds request, excluding setfilelock requests */ struct rb_root request_tree; /* pending mds requests */ struct delayed_work delayed_work; /* delayed work */ --=20 2.53.0 From nobody Sat Jul 25 22:03:24 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 498B537701C; Mon, 13 Jul 2026 09:47:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783936021; cv=none; b=FUatCeIjL8Xkogt93wytQUNEOTH9bBxUlpb4bpsUtYHouEPLxwQyHf8ZEyVGwYf3UTkYNiFDMGDBPQ5qa/HtKQ+5Bt+6EnWm9nWf9iiW9Zy8Aq52Xai9HK8JRfSa23ayHw7PZ2k2XhyOsrTz1gB35hDQg2epnQOukmcHTLKu+Zg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783936021; c=relaxed/simple; bh=FuMGn2tEaqzUS+HTxRIrIkvT20dTJFvzkrMoXHuFGV0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hZI/TMbCg495I7jsr6fXCLRRA6ohh7TIM6eanbPYyvXfjcnLmTvHQrBMJgbOsBmGZOI5VIRc0t72FxLe+4LvT5cWrooj/c4qwBR80ANVwO3GuJUp4dP+G22mkKjdVFNaHUSfIPuuKBPDhmb1ZYHnlcRoLZEfZL0t7EYn0ayEBes= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XrAaP2dn; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="XrAaP2dn" Received: by smtp.kernel.org (Postfix) with ESMTPS id 0F232C2BCF4; Mon, 13 Jul 2026 09:47:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1783936021; bh=FuMGn2tEaqzUS+HTxRIrIkvT20dTJFvzkrMoXHuFGV0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=XrAaP2dn8dyfJAZALdut9Nr8xWRVqOGopuHZCgYwQzmyFB4To+ye0yjlNc3SwMblx xwAVkae7cKXK0IPTR1Uz242nvpBnoO2RPrKC6+7WZb/w66fXUkfsTZwGzrUEGFOKuf tT8aWV3EjUng26rRqPSqBuljCDrKRP5MKu/4m0cEfRExb3WQ93u73jtw1nOZ3h4xfR eD3Xtnmjk41Esj7DTs5/pf3e466hhfIRkIrQoWpYsi9kW9NPbKtzVDsLD/vgw/Ntqz Hn5+hu6FQivKZdRDPaDEoreT5h+BCOFU1jI19uT31oCKNznulc5itcYQNeAvA9aFbG br0Y6LynWEE9w== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id E8764C44507; Mon, 13 Jul 2026 09:47:00 +0000 (UTC) From: Xiubo Li via B4 Relay Date: Mon, 13 Jul 2026 17:46:08 +0800 Subject: [PATCH 2/5] ceph: replace the request_tree rbtree with an xarray keyed by r_tid. Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260713-ceph-mdsc-mutex-optimization-v1-2-9ae5ac135c34@clyso.com> References: <20260713-ceph-mdsc-mutex-optimization-v1-0-9ae5ac135c34@clyso.com> In-Reply-To: <20260713-ceph-mdsc-mutex-optimization-v1-0-9ae5ac135c34@clyso.com> To: Ilya Dryomov , Alex Markuze , Viacheslav Dubeyko Cc: ceph-devel@vger.kernel.org, linux-kernel@vger.kernel.org, Xiubo Li X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1783936018; l=11026; i=xiubo.li@clyso.com; s=20260625; h=from:subject:message-id; bh=E29whNYNjCrjTbCZtl25dlUASbbTF+MPIVTIDSccGrg=; b=MAr2v7AyfqWcIKZzMBPymFyNap8LCIyVFryZEeYf0X4uUUtVykIWz4/U6Iz1jSrTWVkMeKmhk 0sRDqsSCCg+AS/2qhgA8+xA7v7uS8qja3QqfbrhrrDcydaYaUmsnXPT X-Developer-Key: i=xiubo.li@clyso.com; a=ed25519; pk=V3NGr0AgAopiUhaLY51ipBkLN5LlcLhjOEfLEq1RoZ8= X-Endpoint-Received: by B4 Relay for xiubo.li@clyso.com/20260625 with auth_id=840 X-Original-From: Xiubo Li Reply-To: xiubo.li@clyso.com From: Xiubo Li The xarray gives O(1) lookups by tid (vs O(log N) rbtree) and uses internal RCU-based locking, eliminating mdsc->mutex as a precondition for tree access and paving the way for lockless xa_load() in the future. Iteration is also cleaner: xa_for_each() and xa_find() replace the open-coded rb_first()/rb_next() walks. Signed-off-by: Xiubo Li --- fs/ceph/debugfs.c | 6 +-- fs/ceph/mds_client.c | 109 ++++++++++++++++++++++-------------------------= ---- fs/ceph/mds_client.h | 3 +- 3 files changed, 50 insertions(+), 68 deletions(-) diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c index 18eb5da03411..491ead3fe1c6 100644 --- a/fs/ceph/debugfs.c +++ b/fs/ceph/debugfs.c @@ -87,12 +87,12 @@ static int mdsc_show(struct seq_file *s, void *p) struct ceph_fs_client *fsc =3D s->private; struct ceph_mds_client *mdsc =3D fsc->mdsc; struct ceph_mds_request *req; - struct rb_node *rp; + unsigned long idx; char *path; =20 mutex_lock(&mdsc->mutex); - for (rp =3D rb_first(&mdsc->request_tree); rp; rp =3D rb_next(rp)) { - req =3D rb_entry(rp, struct ceph_mds_request, r_node); + idx =3D 0; + xa_for_each(&mdsc->request_tree, idx, req) { =20 if (req->r_request && req->r_session) seq_printf(s, "%lld\tmds%d\t", req->r_tid, diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 98d0a5baff70..909f909b64ed 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -1183,7 +1183,6 @@ void ceph_mdsc_release_request(struct kref *kref) kmem_cache_free(ceph_mds_request_cachep, req); } =20 -DEFINE_RB_FUNCS(request, struct ceph_mds_request, r_tid, r_node) =20 /* * lookup session, bump ref if found. @@ -1195,7 +1194,7 @@ lookup_get_request(struct ceph_mds_client *mdsc, u64 = tid) { struct ceph_mds_request *req; =20 - req =3D lookup_request(&mdsc->request_tree, tid); + req =3D xa_load(&mdsc->request_tree, tid); if (req) ceph_mdsc_get_request(req); =20 @@ -1229,7 +1228,7 @@ static void __register_request(struct ceph_mds_client= *mdsc, } doutc(cl, "%p tid %lld\n", req, req->r_tid); ceph_mdsc_get_request(req); - insert_request(&mdsc->request_tree, req); + xa_store(&mdsc->request_tree, req->r_tid, req, GFP_NOFS); =20 req->r_cred =3D get_current_cred(); if (!req->r_mnt_idmap) @@ -1259,20 +1258,20 @@ static void __unregister_request(struct ceph_mds_cl= ient *mdsc, list_del_init(&req->r_unsafe_item); =20 if (req->r_tid =3D=3D atomic64_read(&mdsc->oldest_tid)) { - struct rb_node *p =3D rb_next(&req->r_node); + unsigned long tidx =3D req->r_tid + 1; + struct ceph_mds_request *next_req; + atomic64_set(&mdsc->oldest_tid, 0); - while (p) { - struct ceph_mds_request *next_req =3D - rb_entry(p, struct ceph_mds_request, r_node); + xa_for_each_start(&mdsc->request_tree, tidx, next_req, tidx) { if (next_req->r_op !=3D CEPH_MDS_OP_SETFILELOCK) { - atomic64_set(&mdsc->oldest_tid, next_req->r_tid); + atomic64_set(&mdsc->oldest_tid, + next_req->r_tid); break; } - p =3D rb_next(p); } } =20 - erase_request(&mdsc->request_tree, req); + xa_erase(&mdsc->request_tree, req->r_tid); =20 if (req->r_unsafe_dir) { struct ceph_inode_info *ci =3D ceph_inode(req->r_unsafe_dir); @@ -1829,7 +1828,7 @@ static void cleanup_session_requests(struct ceph_mds_= client *mdsc, { struct ceph_client *cl =3D mdsc->fsc->client; struct ceph_mds_request *req; - struct rb_node *p; + unsigned long idx; =20 doutc(cl, "mds%d\n", session->s_mds); mutex_lock(&mdsc->mutex); @@ -1845,10 +1844,8 @@ static void cleanup_session_requests(struct ceph_mds= _client *mdsc, __unregister_request(mdsc, req); } /* zero r_attempts, so kick_requests() will re-send requests */ - p =3D rb_first(&mdsc->request_tree); - while (p) { - req =3D rb_entry(p, struct ceph_mds_request, r_node); - p =3D rb_next(p); + idx =3D 0; + xa_for_each(&mdsc->request_tree, idx, req) { if (req->r_session && req->r_session->s_mds =3D=3D session->s_mds) req->r_attempts =3D 0; @@ -2732,7 +2729,6 @@ ceph_mdsc_create_request(struct ceph_mds_client *mdsc= , int op, int mode) req->r_fmode =3D -1; req->r_feature_needed =3D -1; kref_init(&req->r_kref); - RB_CLEAR_NODE(&req->r_node); INIT_LIST_HEAD(&req->r_wait); init_completion(&req->r_completion); init_completion(&req->r_safe_completion); @@ -2752,10 +2748,9 @@ ceph_mdsc_create_request(struct ceph_mds_client *mds= c, int op, int mode) */ static struct ceph_mds_request *__get_oldest_req(struct ceph_mds_client *m= dsc) { - if (RB_EMPTY_ROOT(&mdsc->request_tree)) - return NULL; - return rb_entry(rb_first(&mdsc->request_tree), - struct ceph_mds_request, r_node); + unsigned long idx =3D 0; + + return xa_find(&mdsc->request_tree, &idx, ULONG_MAX, XA_PRESENT); } =20 static inline u64 __get_oldest_tid(struct ceph_mds_client *mdsc) @@ -3816,12 +3811,11 @@ static void kick_requests(struct ceph_mds_client *m= dsc, int mds) { struct ceph_client *cl =3D mdsc->fsc->client; struct ceph_mds_request *req; - struct rb_node *p =3D rb_first(&mdsc->request_tree); + unsigned long idx; =20 doutc(cl, "kick_requests mds%d\n", mds); - while (p) { - req =3D rb_entry(p, struct ceph_mds_request, r_node); - p =3D rb_next(p); + idx =3D 0; + xa_for_each(&mdsc->request_tree, idx, req) { if (test_bit(CEPH_MDS_R_GOT_UNSAFE, &req->r_req_flags)) continue; if (req->r_attempts > 0) @@ -4654,7 +4648,7 @@ static void replay_unsafe_requests(struct ceph_mds_cl= ient *mdsc, struct ceph_mds_session *session) { struct ceph_mds_request *req, *nreq; - struct rb_node *p; + unsigned long idx; =20 doutc(mdsc->fsc->client, "mds%d\n", session->s_mds); =20 @@ -4666,10 +4660,8 @@ static void replay_unsafe_requests(struct ceph_mds_c= lient *mdsc, * also re-send old requests when MDS enters reconnect stage. So that MDS * can process completed request in clientreplay stage. */ - p =3D rb_first(&mdsc->request_tree); - while (p) { - req =3D rb_entry(p, struct ceph_mds_request, r_node); - p =3D rb_next(p); + idx =3D 0; + xa_for_each(&mdsc->request_tree, idx, req) { if (test_bit(CEPH_MDS_R_GOT_UNSAFE, &req->r_req_flags)) continue; if (req->r_attempts =3D=3D 0) @@ -5514,7 +5506,7 @@ static void ceph_mdsc_reset_workfn(struct work_struct= *work) */ { struct ceph_mds_request *req; - struct rb_node *rn; + unsigned long idx; u64 last_tid; =20 mutex_lock(&mdsc->mutex); @@ -5522,14 +5514,12 @@ static void ceph_mdsc_reset_workfn(struct work_stru= ct *work) mutex_unlock(&mdsc->mutex); =20 mutex_lock(&mdsc->mutex); - rn =3D rb_first(&mdsc->request_tree); - while (rn) { - req =3D rb_entry(rn, struct ceph_mds_request, r_node); - if (req->r_tid > last_tid) - break; + idx =3D 0; + while ((req =3D xa_find(&mdsc->request_tree, &idx, last_tid, + XA_PRESENT))) { if (req->r_op =3D=3D CEPH_MDS_OP_SETFILELOCK || !(req->r_op & CEPH_MDS_OP_WRITE)) { - rn =3D rb_next(rn); + idx++; continue; } ceph_mdsc_get_request(req); @@ -5542,7 +5532,7 @@ static void ceph_mdsc_reset_workfn(struct work_struct= *work) ceph_mdsc_put_request(req); if (time_after(jiffies, drain_deadline)) break; - rn =3D rb_first(&mdsc->request_tree); + idx =3D 0; /* restart: tree may have changed */ } mutex_unlock(&mdsc->mutex); =20 @@ -6268,7 +6258,7 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc) mdsc->snap_realms =3D RB_ROOT; INIT_LIST_HEAD(&mdsc->snap_empty); spin_lock_init(&mdsc->snap_empty_lock); - mdsc->request_tree =3D RB_ROOT; + xa_init(&mdsc->request_tree); INIT_DELAYED_WORK(&mdsc->delayed_work, delayed_work); mdsc->last_renew_caps =3D jiffies; INIT_LIST_HEAD(&mdsc->cap_delay_list); @@ -6590,34 +6580,33 @@ static void flush_mdlog_and_wait_mdsc_unsafe_reques= ts(struct ceph_mds_client *md u64 want_tid) { struct ceph_client *cl =3D mdsc->fsc->client; - struct ceph_mds_request *req =3D NULL, *nextreq; + struct ceph_mds_request *req; struct ceph_mds_session *last_session =3D NULL; - struct rb_node *n; + unsigned long idx; =20 mutex_lock(&mdsc->mutex); doutc(cl, "want %lld\n", want_tid); -restart: - req =3D __get_oldest_req(mdsc); - while (req && req->r_tid <=3D want_tid) { - /* find next request */ - n =3D rb_next(&req->r_node); - if (n) - nextreq =3D rb_entry(n, struct ceph_mds_request, r_node); - else - nextreq =3D NULL; - if (req->r_op !=3D CEPH_MDS_OP_SETFILELOCK && - (req->r_op & CEPH_MDS_OP_WRITE)) { + idx =3D 0; + while ((req =3D xa_find(&mdsc->request_tree, &idx, want_tid, + XA_PRESENT))) { + u64 next_tid =3D req->r_tid + 1; + + if (req->r_op =3D=3D CEPH_MDS_OP_SETFILELOCK || + !(req->r_op & CEPH_MDS_OP_WRITE)) { + idx =3D next_tid; + continue; + } + + { struct ceph_mds_session *s =3D req->r_session; =20 if (!s) { - req =3D nextreq; + idx =3D next_tid; continue; } =20 /* write op */ ceph_mdsc_get_request(req); - if (nextreq) - ceph_mdsc_get_request(nextreq); s =3D ceph_get_mds_session(s); mutex_unlock(&mdsc->mutex); =20 @@ -6635,16 +6624,9 @@ static void flush_mdlog_and_wait_mdsc_unsafe_request= s(struct ceph_mds_client *md =20 mutex_lock(&mdsc->mutex); ceph_mdsc_put_request(req); - if (!nextreq) - break; /* next dne before, so we're done! */ - if (RB_EMPTY_NODE(&nextreq->r_node)) { - /* next request was removed from tree */ - ceph_mdsc_put_request(nextreq); - goto restart; - } - ceph_mdsc_put_request(nextreq); /* won't go away */ + /* restart from the next tid; tree may have changed */ + idx =3D next_tid; } - req =3D nextreq; } mutex_unlock(&mdsc->mutex); ceph_put_mds_session(last_session); @@ -6803,6 +6785,7 @@ static void ceph_mdsc_stop(struct ceph_mds_client *md= sc) if (mdsc->mdsmap) ceph_mdsmap_destroy(mdsc->mdsmap); kfree(mdsc->sessions); + xa_destroy(&mdsc->request_tree); ceph_caps_finalize(mdsc); =20 if (mdsc->s_cap_auths) { diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index 3b614b5df18c..00ca993ed583 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -329,7 +329,6 @@ typedef int (*ceph_mds_request_wait_callback_t) (struct= ceph_mds_client *mdsc, */ struct ceph_mds_request { u64 r_tid; /* transaction id */ - struct rb_node r_node; struct ceph_mds_client *r_mdsc; =20 struct kref r_kref; @@ -534,7 +533,7 @@ struct ceph_mds_client { u64 last_tid; /* most recent mds request */ atomic64_t oldest_tid; /* oldest incomplete mds request, excluding setfilelock requests */ - struct rb_root request_tree; /* pending mds requests */ + struct xarray request_tree; /* pending mds requests */ struct delayed_work delayed_work; /* delayed work */ unsigned long last_renew_caps; /* last time we renewed our caps */ struct list_head cap_delay_list; /* caps with delayed release */ --=20 2.53.0 From nobody Sat Jul 25 22:03:24 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 49821376BE0; Mon, 13 Jul 2026 09:47:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783936021; cv=none; b=ikP7GTaxqqYPYSakbUYfFRvYdjAzSLIQ1OjVaRlHvl6rF30jaUzWjw9nUU4fUKK6ZRvdkGfkCMorasZNpd5Mtk5klf3o+tUZcj5t9Dbot19NSINWSztpRNAf8aIZXHPJDhXBPAtB7AAW7vFWdToIdEhibFnOj3VdrQg7IEqHBCM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783936021; c=relaxed/simple; bh=e9iMPlkuziCv8yWN07h/xt2GTIksRXCyEIzNgVSqYw4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hozeXYspgxjgGjJpedMRmamkaGNk0+NILOhrwn17e98GbDnNHFWbBQZeF7NNJ6cSn7DLnbwrxgRC2yWQf/aZRIh962MOjw/CeyfNpCQsWZ8JbVM9yxIn+j75eRpVjvR1ByHvt18zRE52RJnqYT2Z61hhQLkee+HbJbhw0lGLq1c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=J8o1sWTC; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="J8o1sWTC" Received: by smtp.kernel.org (Postfix) with ESMTPS id 1BE88C2BCF7; Mon, 13 Jul 2026 09:47:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1783936021; bh=e9iMPlkuziCv8yWN07h/xt2GTIksRXCyEIzNgVSqYw4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=J8o1sWTCvSztkFQfm9/zlGW9YPBg/9NISf24IEMlZrv9cjRRHqC6Qwmo2hUPck/yI 0945ICMwp48I59TaTPttd6HsiLPoJoaok5d/VFtuJOAzNe4evYCwB8Q8SM5kIE3ak5 IcBoFcJn0bfOy2BQgVqtpMXUCOaHbmPJlKGle74cgyCT75KVZ8pp+5QxfkkQ3509oC p7TGiAAG86FW2EKItNUG9dEl5yFUoy0i2gHhnGPkKLXm4bWZFRvtdO3AeN5Qlkc504 b9SMb597B+Y50UvWADi7SdvJNa+gQ0ox4muLccGS1qiUO01SEcPZvl2U0NXHcMmQJ7 gjdv9ikj6ZTug== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 01E44C44506; Mon, 13 Jul 2026 09:47:01 +0000 (UTC) From: Xiubo Li via B4 Relay Date: Mon, 13 Jul 2026 17:46:09 +0800 Subject: [PATCH 3/5] ceph: add wait_list_lock for wait-list serialization Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260713-ceph-mdsc-mutex-optimization-v1-3-9ae5ac135c34@clyso.com> References: <20260713-ceph-mdsc-mutex-optimization-v1-0-9ae5ac135c34@clyso.com> In-Reply-To: <20260713-ceph-mdsc-mutex-optimization-v1-0-9ae5ac135c34@clyso.com> To: Ilya Dryomov , Alex Markuze , Viacheslav Dubeyko Cc: ceph-devel@vger.kernel.org, linux-kernel@vger.kernel.org, Xiubo Li X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1783936018; l=4380; i=xiubo.li@clyso.com; s=20260625; h=from:subject:message-id; bh=J7oEObT3LMGtmwTthR3MugHZb7zCkSg8x13b9qZBoVw=; b=pkey4ZKEKkXCwSUEK7FuG5kl8MBucKSAkoT/5SoxxCLNDpm1uI5bvPGe4zon4bCLzeiGOygLh fnSovYeLfGbAyf0yf7+H6Ducq0CFW//KTgPS2zKFJ1HC2pweHSTfi8/ X-Developer-Key: i=xiubo.li@clyso.com; a=ed25519; pk=V3NGr0AgAopiUhaLY51ipBkLN5LlcLhjOEfLEq1RoZ8= X-Endpoint-Received: by B4 Relay for xiubo.li@clyso.com/20260625 with auth_id=840 X-Original-From: Xiubo Li Reply-To: xiubo.li@clyso.com From: Xiubo Li Add a dedicated spinlock to protect the waiting_for_map and s_waiting lists, which are currently serialized by mdsc->mutex. This is a preparatory step for removing mdsc->mutex from the kick_requests() path: xa_for_each() is internally locked and the per-request filter checks are lockless, so only list_del_init() needs external protection. Signed-off-by: Xiubo Li Reviewed-by: Viacheslav Dubeyko --- fs/ceph/mds_client.c | 18 +++++++++++++++++- fs/ceph/mds_client.h | 3 +++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 909f909b64ed..6f9049148721 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -3609,7 +3609,9 @@ static void __do_request(struct ceph_mds_client *mdsc, doutc(cl, "no mdsmap, waiting for map\n"); trace_ceph_mdsc_suspend_request(mdsc, session, req, ceph_mdsc_suspend_reason_no_mdsmap); + spin_lock(&mdsc->wait_list_lock); list_add(&req->r_wait, &mdsc->waiting_for_map); + spin_unlock(&mdsc->wait_list_lock); return; } if (!(mdsc->fsc->mount_options->flags & @@ -3632,7 +3634,9 @@ static void __do_request(struct ceph_mds_client *mdsc, doutc(cl, "no mds or not active, waiting for map\n"); trace_ceph_mdsc_suspend_request(mdsc, session, req, ceph_mdsc_suspend_reason_no_active_mds); + spin_lock(&mdsc->wait_list_lock); list_add(&req->r_wait, &mdsc->waiting_for_map); + spin_unlock(&mdsc->wait_list_lock); return; } =20 @@ -3680,9 +3684,12 @@ static void __do_request(struct ceph_mds_client *mds= c, if (ceph_test_mount_opt(mdsc->fsc, CLEANRECOVER)) { trace_ceph_mdsc_suspend_request(mdsc, session, req, ceph_mdsc_suspend_reason_rejected); + spin_lock(&mdsc->wait_list_lock); list_add(&req->r_wait, &mdsc->waiting_for_map); - } else + spin_unlock(&mdsc->wait_list_lock); + } else { err =3D -EACCES; + } goto out_session; } =20 @@ -3697,7 +3704,9 @@ static void __do_request(struct ceph_mds_client *mdsc, } trace_ceph_mdsc_suspend_request(mdsc, session, req, ceph_mdsc_suspend_reason_session); + spin_lock(&mdsc->wait_list_lock); list_add(&req->r_wait, &session->s_waiting); + spin_unlock(&mdsc->wait_list_lock); goto out_session; } =20 @@ -3790,7 +3799,9 @@ static void __wake_requests(struct ceph_mds_client *m= dsc, struct ceph_mds_request *req; LIST_HEAD(tmp_list); =20 + spin_lock(&mdsc->wait_list_lock); list_splice_init(head, &tmp_list); + spin_unlock(&mdsc->wait_list_lock); =20 while (!list_empty(&tmp_list)) { req =3D list_entry(tmp_list.next, @@ -3823,7 +3834,9 @@ static void kick_requests(struct ceph_mds_client *mds= c, int mds) if (req->r_session && req->r_session->s_mds =3D=3D mds) { doutc(cl, " kicking tid %llu\n", req->r_tid); + spin_lock(&mdsc->wait_list_lock); list_del_init(&req->r_wait); + spin_unlock(&mdsc->wait_list_lock); trace_ceph_mdsc_resume_request(mdsc, req); __do_request(mdsc, req); } @@ -6258,6 +6271,7 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc) mdsc->snap_realms =3D RB_ROOT; INIT_LIST_HEAD(&mdsc->snap_empty); spin_lock_init(&mdsc->snap_empty_lock); + spin_lock_init(&mdsc->wait_list_lock); xa_init(&mdsc->request_tree); INIT_DELAYED_WORK(&mdsc->delayed_work, delayed_work); mdsc->last_renew_caps =3D jiffies; @@ -6340,7 +6354,9 @@ static void wait_requests(struct ceph_mds_client *mds= c) mutex_lock(&mdsc->mutex); while ((req =3D __get_oldest_req(mdsc))) { doutc(cl, "timed out on tid %llu\n", req->r_tid); + spin_lock(&mdsc->wait_list_lock); list_del_init(&req->r_wait); + spin_unlock(&mdsc->wait_list_lock); __unregister_request(mdsc, req); } } diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index 00ca993ed583..cd5dacfb42bd 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -529,6 +529,9 @@ struct ceph_mds_client { struct list_head snap_empty; int num_snap_realms; spinlock_t snap_empty_lock; /* protect snap_empty */ + spinlock_t wait_list_lock; /* protect waiting_for_map + * and s_waiting lists + */ =20 u64 last_tid; /* most recent mds request */ atomic64_t oldest_tid; /* oldest incomplete mds request, --=20 2.53.0 From nobody Sat Jul 25 22:03:24 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 49601346784; Mon, 13 Jul 2026 09:47:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783936021; cv=none; b=YirUsGJoLUhySTAWkJOMFNgof7njQ8zs5nI3CvzMRC6N4g0ce9kMnv4ciu9BBPSSDFUse79yfRNANFcqytmhwWEhqpMu1is79bZEGPYzEDxV6P1nkS6zKz8XoVxGq96lrQANX7G2/s0Rv1Ty68AIww71TbFqY8hzyp8303gjF+A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783936021; c=relaxed/simple; bh=UDIyCUfXFHWqj6IVJqjgM0HgwmJgQvyP5NXQ49VuHvs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=umz+rJqJKXVOUfcangPayXFl86aZbbQV5OAdi7veL9SObXDi0mZuLTjICk712vIdTtcW3/zevVKJyE6GcZrIq4CQbJ3rD4BEgEayq3mmcdNqOeSdVU5k5+qMIW9YWbSIa/0L7XGmfNIDHWvZgrO6LXE9Zezx4qeG+z4qOoHhTcY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=j/hs/5j0; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="j/hs/5j0" Received: by smtp.kernel.org (Postfix) with ESMTPS id 21105C2BCFA; Mon, 13 Jul 2026 09:47:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1783936021; bh=UDIyCUfXFHWqj6IVJqjgM0HgwmJgQvyP5NXQ49VuHvs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=j/hs/5j0I0CzeM2FXD1E5sDmJ+zuAi5psnsEl4d9LyNvmDGvmwBj3kxqnifDmeAh2 pOYAimftIepDnvKzRPExEDXO2BUxq+0MPX1G5b4IdMYs3qOG+9hQK3f1cnFdPvuiCe Rpg/7BnxMy6mHjbm7Tl6kTedXQKFlLDZdX0v+Y/cgPr0+uFtT8kcBAOn5UxtknJcur di4DYVVRCNSDFivgfRM1+4znhhoFGKbk9GBXzbzmUFVgAVtMhAOQG4YcK7D1WT8qnu uarnQg8dpAVNvNwrIDJX8Cm833IjnlYw0kkySMqlO6SEkdtiUi5exw1V2oHW/AnIAm 651uGfmzW9IKA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1047CC44508; Mon, 13 Jul 2026 09:47:01 +0000 (UTC) From: Xiubo Li via B4 Relay Date: Mon, 13 Jul 2026 17:46:10 +0800 Subject: [PATCH 4/5] ceph: move mdsc->mutex into __do_request() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260713-ceph-mdsc-mutex-optimization-v1-4-9ae5ac135c34@clyso.com> References: <20260713-ceph-mdsc-mutex-optimization-v1-0-9ae5ac135c34@clyso.com> In-Reply-To: <20260713-ceph-mdsc-mutex-optimization-v1-0-9ae5ac135c34@clyso.com> To: Ilya Dryomov , Alex Markuze , Viacheslav Dubeyko Cc: ceph-devel@vger.kernel.org, linux-kernel@vger.kernel.org, Xiubo Li X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1783936018; l=8374; i=xiubo.li@clyso.com; s=20260625; h=from:subject:message-id; bh=Vu2lxq/ZLSzuATsXBorCwXr4GVDVi48b6ZbdEBHxwoA=; b=96kxuKn/PVQ1sqbdtWBrjPKYlnCbrSLLcfdpHc2YkTKav+2ouQfDnpPAv3n45CyouPQUKDqP4 ZsRM7mQe/nNBwsml6IZzaTii8r1P/+EA0b+6T8jgHyzXlPgify6GpDK X-Developer-Key: i=xiubo.li@clyso.com; a=ed25519; pk=V3NGr0AgAopiUhaLY51ipBkLN5LlcLhjOEfLEq1RoZ8= X-Endpoint-Received: by B4 Relay for xiubo.li@clyso.com/20260625 with auth_id=840 X-Original-From: Xiubo Li Reply-To: xiubo.li@clyso.com From: Xiubo Li __do_request() now acquires mdsc->mutex on entry and unlocks at every exit point, so callers no longer need to hold it. As a result kick_requests() is now completely free of mdsc->mutex: xa_for_each() is internally locked, list_del_init() is guarded by wait_list_lock, and __do_request() manages its own serialization. Remove the no-longer-needed mutex_lock/unlock around __do_request() in ceph_mdsc_submit_request() and handle_forward(). The do_request() wrapper introduced in the previous commit is no longer necessary and is dropped. Signed-off-by: Xiubo Li --- fs/ceph/mds_client.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 6f9049148721..ef54d19ace2a 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -3577,9 +3577,12 @@ static void __do_request(struct ceph_mds_client *mds= c, int err =3D 0; bool random; =20 + mutex_lock(&mdsc->mutex); + if (req->r_err || test_bit(CEPH_MDS_R_GOT_RESULT, &req->r_req_flags)) { if (test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags)) __unregister_request(mdsc, req); + mutex_unlock(&mdsc->mutex); return; } =20 @@ -3612,6 +3615,7 @@ static void __do_request(struct ceph_mds_client *mdsc, spin_lock(&mdsc->wait_list_lock); list_add(&req->r_wait, &mdsc->waiting_for_map); spin_unlock(&mdsc->wait_list_lock); + mutex_unlock(&mdsc->mutex); return; } if (!(mdsc->fsc->mount_options->flags & @@ -3637,6 +3641,7 @@ static void __do_request(struct ceph_mds_client *mdsc, spin_lock(&mdsc->wait_list_lock); list_add(&req->r_wait, &mdsc->waiting_for_map); spin_unlock(&mdsc->wait_list_lock); + mutex_unlock(&mdsc->mutex); return; } =20 @@ -3710,6 +3715,8 @@ static void __do_request(struct ceph_mds_client *mdsc, goto out_session; } =20 + mutex_unlock(&mdsc->mutex); + /* send request */ req->r_resend_mds =3D -1; /* forget any previous mds hint */ =20 @@ -3740,6 +3747,7 @@ static void __do_request(struct ceph_mds_client *mdsc, err =3D wait_on_bit(&di->flags, CEPH_DENTRY_ASYNC_CREATE_BIT, TASK_KILLABLE); if (err) { + mutex_lock(&mdsc->mutex); mutex_lock(&req->r_fill_mutex); set_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags); mutex_unlock(&req->r_fill_mutex); @@ -3777,6 +3785,8 @@ static void __do_request(struct ceph_mds_client *mdsc, =20 err =3D __send_request(session, req, false); =20 + mutex_lock(&mdsc->mutex); + out_session: ceph_put_mds_session(session); finish: @@ -3786,6 +3796,7 @@ static void __do_request(struct ceph_mds_client *mdsc, complete_request(mdsc, req); __unregister_request(mdsc, req); } + mutex_unlock(&mdsc->mutex); return; } =20 @@ -3900,10 +3911,11 @@ int ceph_mdsc_submit_request(struct ceph_mds_client= *mdsc, struct inode *dir, doutc(cl, "submit_request on %p for inode %p\n", req, dir); mutex_lock(&mdsc->mutex); __register_request(mdsc, req, dir); + mutex_unlock(&mdsc->mutex); + trace_ceph_mdsc_submit_request(mdsc, req); __do_request(mdsc, req); err =3D req->r_err; - mutex_unlock(&mdsc->mutex); return err; } =20 @@ -4276,13 +4288,14 @@ static void handle_forward(struct ceph_mds_client *= mdsc, req->r_num_fwd =3D fwd_seq; req->r_resend_mds =3D next_mds; put_request_session(req); - __do_request(mdsc, req); } mutex_unlock(&mdsc->mutex); =20 /* kick calling process */ if (aborted) complete_request(mdsc, req); + else if (!test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags)) + __do_request(mdsc, req); ceph_mdsc_put_request(req); return; =20 @@ -4606,11 +4619,9 @@ static void handle_session(struct ceph_mds_session *= session, =20 mutex_unlock(&session->s_mutex); if (wake) { - mutex_lock(&mdsc->mutex); __wake_requests(mdsc, &session->s_waiting); if (wake =3D=3D 2) kick_requests(mdsc, mds); - mutex_unlock(&mdsc->mutex); } if (op =3D=3D CEPH_SESSION_CLOSE) ceph_put_mds_session(session); @@ -5245,9 +5256,7 @@ static int send_mds_reconnect(struct ceph_mds_client = *mdsc, =20 mutex_unlock(&session->s_mutex); =20 - mutex_lock(&mdsc->mutex); __wake_requests(mdsc, &session->s_waiting); - mutex_unlock(&mdsc->mutex); =20 up_read(&mdsc->snap_rwsem); ceph_pagelist_release(recon_state.pagelist); @@ -5672,8 +5681,8 @@ static void ceph_mdsc_reset_workfn(struct work_struct= *work) } sessions[i]->s_state =3D CEPH_MDS_SESSION_CLOSED; __unregister_session(mdsc, sessions[i]); - __wake_requests(mdsc, &sessions[i]->s_waiting); mutex_unlock(&mdsc->mutex); + __wake_requests(mdsc, &sessions[i]->s_waiting); =20 mutex_lock(&sessions[i]->s_mutex); cleanup_session_requests(mdsc, sessions[i]); @@ -5684,9 +5693,7 @@ static void ceph_mdsc_reset_workfn(struct work_struct= *work) =20 ceph_put_mds_session(sessions[i]); =20 - mutex_lock(&mdsc->mutex); kick_requests(mdsc, mds); - mutex_unlock(&mdsc->mutex); =20 torn_down++; pr_info_client(cl, "mds%d session reset complete\n", mds); @@ -5802,8 +5809,8 @@ static void check_new_map(struct ceph_mds_client *mds= c, /* force close session for stopped mds */ ceph_get_mds_session(s); __unregister_session(mdsc, s); - __wake_requests(mdsc, &s->s_waiting); mutex_unlock(&mdsc->mutex); + __wake_requests(mdsc, &s->s_waiting); =20 mutex_lock(&s->s_mutex); cleanup_session_requests(mdsc, s); @@ -5812,8 +5819,8 @@ static void check_new_map(struct ceph_mds_client *mds= c, =20 ceph_put_mds_session(s); =20 - mutex_lock(&mdsc->mutex); kick_requests(mdsc, i); + mutex_lock(&mdsc->mutex); continue; } =20 @@ -5857,8 +5864,8 @@ static void check_new_map(struct ceph_mds_client *mds= c, oldstate !=3D CEPH_MDS_STATE_STARTING) pr_info_client(cl, "mds%d recovery completed\n", s->s_mds); - kick_requests(mdsc, i); mutex_unlock(&mdsc->mutex); + kick_requests(mdsc, i); mutex_lock(&s->s_mutex); mutex_lock(&mdsc->mutex); ceph_kick_flushing_caps(mdsc, s); @@ -6766,8 +6773,8 @@ void ceph_mdsc_force_umount(struct ceph_mds_client *m= dsc) =20 if (session->s_state =3D=3D CEPH_MDS_SESSION_REJECTED) __unregister_session(mdsc, session); - __wake_requests(mdsc, &session->s_waiting); mutex_unlock(&mdsc->mutex); + __wake_requests(mdsc, &session->s_waiting); =20 mutex_lock(&session->s_mutex); __close_session(mdsc, session); @@ -6778,11 +6785,11 @@ void ceph_mdsc_force_umount(struct ceph_mds_client = *mdsc) mutex_unlock(&session->s_mutex); ceph_put_mds_session(session); =20 - mutex_lock(&mdsc->mutex); kick_requests(mdsc, mds); + mutex_lock(&mdsc->mutex); } - __wake_requests(mdsc, &mdsc->waiting_for_map); mutex_unlock(&mdsc->mutex); + __wake_requests(mdsc, &mdsc->waiting_for_map); } =20 static void ceph_mdsc_stop(struct ceph_mds_client *mdsc) @@ -6924,8 +6931,8 @@ void ceph_mdsc_handle_fsmap(struct ceph_mds_client *m= dsc, struct ceph_msg *msg) err_out: mutex_lock(&mdsc->mutex); mdsc->mdsmap_err =3D err; - __wake_requests(mdsc, &mdsc->waiting_for_map); mutex_unlock(&mdsc->mutex); + __wake_requests(mdsc, &mdsc->waiting_for_map); } =20 /* @@ -6976,11 +6983,11 @@ void ceph_mdsc_handle_mdsmap(struct ceph_mds_client= *mdsc, struct ceph_msg *msg) mdsc->fsc->max_file_size =3D min((loff_t)mdsc->mdsmap->m_max_file_size, MAX_LFS_FILESIZE); =20 + mutex_unlock(&mdsc->mutex); __wake_requests(mdsc, &mdsc->waiting_for_map); ceph_monc_got_map(&mdsc->fsc->client->monc, CEPH_SUB_MDSMAP, mdsc->mdsmap->m_epoch); =20 - mutex_unlock(&mdsc->mutex); schedule_delayed(mdsc, 0); return; =20 @@ -7078,8 +7085,8 @@ static void mds_peer_reset(struct ceph_connection *co= n) ceph_get_mds_session(s); s->s_state =3D CEPH_MDS_SESSION_CLOSED; __unregister_session(mdsc, s); - __wake_requests(mdsc, &s->s_waiting); mutex_unlock(&mdsc->mutex); + __wake_requests(mdsc, &s->s_waiting); =20 mutex_lock(&s->s_mutex); cleanup_session_requests(mdsc, s); @@ -7088,9 +7095,7 @@ static void mds_peer_reset(struct ceph_connection *co= n) =20 wake_up_all(&mdsc->session_close_wq); =20 - mutex_lock(&mdsc->mutex); kick_requests(mdsc, s->s_mds); - mutex_unlock(&mdsc->mutex); =20 ceph_put_mds_session(s); break; --=20 2.53.0 From nobody Sat Jul 25 22:03:24 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 6ECD83DD508; Mon, 13 Jul 2026 09:47:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783936021; cv=none; b=OCjCi/i4/wZsqLESoKBOXP33a8TBg9PlbZJalbEdtlbU6HDSkYUc7rYNw8CohsqgjfrS8PSyvTaI9vup/uPiaayrQjtwFuFq2EklGB/RQiGaO672djCjbmQfIfKVJLb5Fg+t0QwApJCnroKNCRLtqaHztqVPSVUaDN2Ai+v8O9w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783936021; c=relaxed/simple; bh=OrhbLzSQoljdA3xsrT3Ppv78ks1IkOXDcY62zeCoVdc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=A2QwjSPCYorj/Fm7606fsO3v9WAkfwJOBf1PYNA52sWJNdFnmbMKwOODKT62i9sbLJGhaEbldN6+3krhX28K82EIQrigkNvNXqyYK6pRj4+benP59xEoXi4iWWwEb/oQafQkJOj0GVdkJM4rHQNhp4NZLm/SqyqHHpeX9TnGDeg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GlpYF9mu; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GlpYF9mu" Received: by smtp.kernel.org (Postfix) with ESMTPS id 2DB94C2BCFB; Mon, 13 Jul 2026 09:47:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1783936021; bh=OrhbLzSQoljdA3xsrT3Ppv78ks1IkOXDcY62zeCoVdc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=GlpYF9muMftQRlqrFKC/SGx3YGWbODL//OY+iP+JDBok6EPVsAMPyv/bs6Yp4uFjk kceJ1NnTwz+/We6ZY94aKQ+KoF6Y/YOjrXHr0GXaxqcwDpj2usULWwSs/9PSwM/YBJ SrJp8tQ0ZpkQ4VAWlG5WbZzaQyWXE/oYH9KfpKKQuNlwDgX50WvDuvVVl8HLO+cbYP KEsxRt0oMsuE0jYnjUcUAybiy8DSOT1mwex1nqLuPYSd5WEfdYCLmJ1P46Xo2YnMPc okJhW95H75nOy1Ulf3ioZ3RFGhEL/vO+cGKFMpiogw3PBVONZHr2z+kZR+sfZviDo2 aW775w9aQP54A== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1DF42C43458; Mon, 13 Jul 2026 09:47:01 +0000 (UTC) From: Xiubo Li via B4 Relay Date: Mon, 13 Jul 2026 17:46:11 +0800 Subject: [PATCH 5/5] ceph: narrow mdsc->mutex scope in replay_unsafe_requests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260713-ceph-mdsc-mutex-optimization-v1-5-9ae5ac135c34@clyso.com> References: <20260713-ceph-mdsc-mutex-optimization-v1-0-9ae5ac135c34@clyso.com> In-Reply-To: <20260713-ceph-mdsc-mutex-optimization-v1-0-9ae5ac135c34@clyso.com> To: Ilya Dryomov , Alex Markuze , Viacheslav Dubeyko Cc: ceph-devel@vger.kernel.org, linux-kernel@vger.kernel.org, Xiubo Li X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1783936018; l=1786; i=xiubo.li@clyso.com; s=20260625; h=from:subject:message-id; bh=Sl0B6kcMz6zymOkZ4jEEs/Wx0+iGbBxBQZu85Is5ZhM=; b=eB7ysIYOWFeALC2JWW2za+3YIQIvxnyN7J24eSXDLed8j+2xYBOGtjjT0pUbRqjT14oqmBoZn IVZwxMEuHRUApPT1pqHUVclVKxwNbNJPg9rqcA+QT1Z/mILKfNh5CJq X-Developer-Key: i=xiubo.li@clyso.com; a=ed25519; pk=V3NGr0AgAopiUhaLY51ipBkLN5LlcLhjOEfLEq1RoZ8= X-Endpoint-Received: by B4 Relay for xiubo.li@clyso.com/20260625 with auth_id=840 X-Original-From: Xiubo Li Reply-To: xiubo.li@clyso.com From: Xiubo Li __send_request() is lockless so holding mdsc->mutex across the replay loop only serializes the list iteration itself. Collect the unsafe list entries under the mutex, then replay them without it. The old-request tree walk uses xa_for_each() which is internally locked. Signed-off-by: Xiubo Li --- fs/ceph/mds_client.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index ef54d19ace2a..6c5a8c651d3e 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -4673,12 +4673,25 @@ static void replay_unsafe_requests(struct ceph_mds_= client *mdsc, { struct ceph_mds_request *req, *nreq; unsigned long idx; + LIST_HEAD(replay_list); =20 doutc(mdsc->fsc->client, "mds%d\n", session->s_mds); =20 + /* collect unsafe requests under the mutex */ mutex_lock(&mdsc->mutex); - list_for_each_entry_safe(req, nreq, &session->s_unsafe, r_unsafe_item) + list_for_each_entry_safe(req, nreq, &session->s_unsafe, + r_unsafe_item) { + ceph_mdsc_get_request(req); + list_move(&req->r_unsafe_item, &replay_list); + } + mutex_unlock(&mdsc->mutex); + + /* replay unsafe requests =E2=80=94 __send_request is lockless */ + list_for_each_entry_safe(req, nreq, &replay_list, r_unsafe_item) { __send_request(session, req, true); + list_del_init(&req->r_unsafe_item); + ceph_mdsc_put_request(req); + } =20 /* * also re-send old requests when MDS enters reconnect stage. So that MDS @@ -4699,7 +4712,6 @@ static void replay_unsafe_requests(struct ceph_mds_cl= ient *mdsc, =20 __send_request(session, req, true); } - mutex_unlock(&mdsc->mutex); } =20 static int send_reconnect_partial(struct ceph_reconnect_state *recon_state) --=20 2.53.0