Re: [PATCH 2/5] ceph: replace the request_tree rbtree with an xarray keyed by r_tid.

Xiubo Li <[email protected]> Wed, 15 Jul 2026 10:21:31 +0800
Newsgroups org.kernel.vger.ceph-devel,org.kernel.vger.linux-kernel
Message-ID <CAOJNxR+cyR-BJx_39MDnTH_AOLckxLgSPDezAswpbpHeWVjjwg@mail.gmail.com>
Hi Slava,

On Wed, 15 Jul 2026 at 02:35, Viacheslav Dubeyko <[email protected]> wrote:
>
> On Mon, 2026-07-13 at 17:46 +0800, Xiubo Li via B4 Relay wrote:
> > From: Xiubo Li <[email protected]>
> >
[......]
> > --- 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);
> >  }
> >
> > -DEFINE_RB_FUNCS(request, struct ceph_mds_request, r_tid, r_node)
> >
> >  /*
> >   * 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;
> >
> > -     req = lookup_request(&mdsc->request_tree, tid);
> > +     req = xa_load(&mdsc->request_tree, tid);
> >       if (req)
> >               ceph_mdsc_get_request(req);
> >
> > @@ -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);
>
> Should we check the return value of xa_store()? What about this?
>
>         err = xa_err(xa_store(&mdsc->request_tree, req->r_tid, req,
> GFP_NOFS));
>         if (err) {
>                 ceph_mdsc_put_request(req);
>                 return err;
>         }
>

Good Catch. Let me fix it.

> >
> >       req->r_cred = get_current_cred();
> >       if (!req->r_mnt_idmap)
> > @@ -1259,20 +1258,20 @@ static void __unregister_request(struct
> > ceph_mds_client *mdsc,
> >       list_del_init(&req->r_unsafe_item);
> >

[......]

> > @@ -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 */
>
> Transaction IDs are u64; xarray indices are unsigned long. req->r_tid,
> mdsc->last_tid, and want_tid/last_tid in the drain paths are all u64,
> but xa_store(), xa_load(), xa_erase(), and xa_find()'s max parameter
> all take unsigned long. CEPH_FS in fs/ceph/Kconfig only depends on INET
> — it's not gated on 64BIT — so this driver still builds for 32-bit
> targets, where unsigned long truncates r_tid to 32 bits. Are we safe
> here?
>

Yeah, you are right. We have two options to fix it. Just add
"depends on 64BIT" in Kconfig or fall back to the rbtree code on
32-bit with an #if BITS_PER_LONG == 64 guard, similar to what we
already do for s_delegated_inos. I went with the #if guard in v2
because it keeps the driver buildable on 32-bit without introducing
a regression — the rbtree handles u64 keys correctly there. The
downside is a few extra #if/#else/#endif blocks, but they are
mostly confined to the iteration headers; the loop bodies are
shared. Only flush_mdlog_and_wait_mdsc_unsafe_requests() needs a
full alternate implementation because the two control flows are
fundamentally different.

What do you prefer?

Thanks
Xiubo Li