[PATCH v4 1/5] ceph: use READ_ONCE/WRITE_ONCE for oldest_tid

From: Xiubo Li via B4 Relay

Date: Wed Aug 12 2026 - 03:17:34 EST


From: Xiubo Li <xiubo.li@xxxxxxxxx>

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
the client already has, or trim its completed-requests table
slightly earlier or later than optimal, both of which the protocol
handles correctly. The field is monotonic and does not need lock
serialization to stay correct.

Switch all accesses to READ_ONCE() and WRITE_ONCE() to prevent
the compiler from tearing or inventing loads, documenting that
these lockless accesses are intentional. This removes the last
reason the MDS request-send path had to be serialized under
mdsc->mutex.

Signed-off-by: Xiubo Li <xiubo.li@xxxxxxxxx>
---
fs/ceph/mds_client.c | 20 +++++++-------------
1 file changed, 7 insertions(+), 13 deletions(-)

diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index f365e434e35d..2c51edd0e9cd 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1240,8 +1240,8 @@ static void __register_request(struct ceph_mds_client *mdsc,
if (!req->r_mnt_idmap)
req->r_mnt_idmap = &nop_mnt_idmap;

- if (mdsc->oldest_tid == 0 && req->r_op != CEPH_MDS_OP_SETFILELOCK)
- mdsc->oldest_tid = req->r_tid;
+ if (READ_ONCE(mdsc->oldest_tid) == 0 && req->r_op != CEPH_MDS_OP_SETFILELOCK)
+ WRITE_ONCE(mdsc->oldest_tid, req->r_tid);

if (dir) {
struct ceph_inode_info *ci = ceph_inode(dir);
@@ -1262,14 +1262,14 @@ static void __unregister_request(struct ceph_mds_client *mdsc,
/* Never leave an unregistered request on an unsafe list! */
list_del_init(&req->r_unsafe_item);

- if (req->r_tid == mdsc->oldest_tid) {
+ if (req->r_tid == READ_ONCE(mdsc->oldest_tid)) {
struct rb_node *p = rb_next(&req->r_node);
- mdsc->oldest_tid = 0;
+ WRITE_ONCE(mdsc->oldest_tid, 0);
while (p) {
struct ceph_mds_request *next_req =
rb_entry(p, struct ceph_mds_request, r_node);
if (next_req->r_op != CEPH_MDS_OP_SETFILELOCK) {
- mdsc->oldest_tid = next_req->r_tid;
+ WRITE_ONCE(mdsc->oldest_tid, next_req->r_tid);
break;
}
p = rb_next(p);
@@ -1698,7 +1698,7 @@ create_session_full_msg(struct ceph_mds_client *mdsc, int op, u64 seq)
ceph_encode_32(&p, 0);

/* version == 7, oldest_client_tid */
- ceph_encode_64(&p, mdsc->oldest_tid);
+ ceph_encode_64(&p, READ_ONCE(mdsc->oldest_tid));

msg->front.iov_len = p - msg->front.iov_base;
msg->hdr.front_len = cpu_to_le32(msg->front.iov_len);
@@ -2764,7 +2764,7 @@ static struct ceph_mds_request *__get_oldest_req(struct ceph_mds_client *mdsc)

static inline u64 __get_oldest_tid(struct ceph_mds_client *mdsc)
{
- return mdsc->oldest_tid;
+ return READ_ONCE(mdsc->oldest_tid);
}

#if IS_ENABLED(CONFIG_FS_ENCRYPTION)
@@ -3443,9 +3443,6 @@ static void complete_request(struct ceph_mds_client *mdsc,
complete_all(&req->r_completion);
}

-/*
- * called under mdsc->mutex
- */
static int __prepare_send_request(struct ceph_mds_session *session,
struct ceph_mds_request *req,
bool drop_cap_releases)
@@ -3560,9 +3557,6 @@ static int __prepare_send_request(struct ceph_mds_session *session,
return 0;
}

-/*
- * called under mdsc->mutex
- */
static int __send_request(struct ceph_mds_session *session,
struct ceph_mds_request *req,
bool drop_cap_releases)

--
2.53.0