From: Aditya Prakash Srivastava <aditya.ansh182@gmail.com>
To: Gao Xiang <xiang@kernel.org>, Chao Yu <chao@kernel.org>
Cc: Yue Hu <zbestahu@gmail.com>,
Jeffle Xu <jefflexu@linux.alibaba.com>,
Sandeep Dhavale <dhavale@google.com>,
Hongbo Li <lihongbo22@huawei.com>,
Chunhai Guo <guochunhai@vivo.com>,
linux-erofs@lists.ozlabs.org, linux-kernel@vger.kernel.org,
Aditya Prakash Srivastava <aditya.ansh182@gmail.com>
Subject: [PATCH] erofs: modernize device IDR to XArray
Date: Wed, 15 Jul 2026 03:35:07 +0000 [thread overview]
Message-ID: <20260715033507.1666-1-aditya.ansh182@gmail.com> (raw)
Currently, EROFS maintains a list of extra devices using a legacy IDR
structure (`sbi->devs->tree`). Modernize this to use a standard, more
efficient XArray instead.
This migration simplifies device management, removes legacy boilerplate,
and aligns EROFS device tracking with modern Linux kernel storage subsystem
conventions:
1. Convert `sbi->devs->tree` from a legacy IDR to an XArray initialized
with `XA_FLAGS_ALLOC` flags.
2. Use `xa_alloc()` to safely register devices under `xa_limit_32b` limits.
3. Use `xa_load()` for direct, fast lookups.
4. Replace custom IDR traversal wrappers with modern `xa_for_each()`
iterators.
5. Replace custom IDR releasing callback helpers with a clean
`xa_for_each()` loop and clean up the tree with `xa_destroy()`.
Signed-off-by: Aditya Prakash Srivastava <aditya.ansh182@gmail.com>
---
fs/erofs/data.c | 6 +++---
fs/erofs/internal.h | 2 +-
fs/erofs/super.c | 43 +++++++++++++++++++++++--------------------
3 files changed, 27 insertions(+), 24 deletions(-)
diff --git a/fs/erofs/data.c b/fs/erofs/data.c
index 9aa48c8d67d1..34a1a7d71559 100644
--- a/fs/erofs/data.c
+++ b/fs/erofs/data.c
@@ -211,13 +211,13 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
struct erofs_dev_context *devs = EROFS_SB(sb)->devs;
struct erofs_device_info *dif;
erofs_off_t startoff;
- int id;
+ unsigned long id;
erofs_fill_from_devinfo(map, sb, &EROFS_SB(sb)->dif0);
map->m_bdev = sb->s_bdev; /* use s_bdev for the primary device */
if (map->m_deviceid) {
down_read(&devs->rwsem);
- dif = idr_find(&devs->tree, map->m_deviceid - 1);
+ dif = xa_load(&devs->tree, map->m_deviceid - 1);
if (!dif) {
up_read(&devs->rwsem);
return -ENODEV;
@@ -231,7 +231,7 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
up_read(&devs->rwsem);
} else if (devs->extra_devices && !devs->flatdev) {
down_read(&devs->rwsem);
- idr_for_each_entry(&devs->tree, dif, id) {
+ xa_for_each(&devs->tree, id, dif) {
if (!dif->uniaddr)
continue;
diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h
index 580f8d9f14e7..f6126a7bfbc7 100644
--- a/fs/erofs/internal.h
+++ b/fs/erofs/internal.h
@@ -64,7 +64,7 @@ struct erofs_mount_opts {
};
struct erofs_dev_context {
- struct idr tree;
+ struct xarray tree;
struct rw_semaphore rwsem;
unsigned int extra_devices;
diff --git a/fs/erofs/super.c b/fs/erofs/super.c
index 86fa5c6a0c70..08e6a9c57d59 100644
--- a/fs/erofs/super.c
+++ b/fs/erofs/super.c
@@ -188,7 +188,8 @@ static int erofs_scan_devices(struct super_block *sb,
erofs_off_t pos;
struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
struct erofs_device_info *dif;
- int id, err = 0;
+ int err = 0;
+ unsigned long id;
sbi->total_blocks = sbi->dif0.blocks;
if (!erofs_sb_has_device_table(sbi))
@@ -217,20 +218,22 @@ static int erofs_scan_devices(struct super_block *sb,
pos = le16_to_cpu(dsb->devt_slotoff) * EROFS_DEVT_SLOT_SIZE;
down_read(&sbi->devs->rwsem);
if (sbi->devs->extra_devices) {
- idr_for_each_entry(&sbi->devs->tree, dif, id) {
+ xa_for_each(&sbi->devs->tree, id, dif) {
err = erofs_init_device(&buf, sb, dif, &pos);
if (err)
break;
}
} else {
for (id = 0; id < ondisk_extradevs; id++) {
+ u32 id_val;
+
dif = kzalloc_obj(*dif);
if (!dif) {
err = -ENOMEM;
break;
}
- err = idr_alloc(&sbi->devs->tree, dif, 0, 0, GFP_KERNEL);
+ err = xa_alloc(&sbi->devs->tree, &id_val, dif, xa_limit_32b, GFP_KERNEL);
if (err < 0) {
kfree(dif);
break;
@@ -480,7 +483,9 @@ static int erofs_fc_parse_param(struct fs_context *fc,
if (!erofs_fc_set_dax_mode(fc, result.uint_32))
return -EINVAL;
break;
- case Opt_device:
+ case Opt_device: {
+ u32 id;
+
dif = kzalloc_obj(*dif);
if (!dif)
return -ENOMEM;
@@ -490,7 +495,7 @@ static int erofs_fc_parse_param(struct fs_context *fc,
return -ENOMEM;
}
down_write(&sbi->devs->rwsem);
- ret = idr_alloc(&sbi->devs->tree, dif, 0, 0, GFP_KERNEL);
+ ret = xa_alloc(&sbi->devs->tree, &id, dif, xa_limit_32b, GFP_KERNEL);
up_write(&sbi->devs->rwsem);
if (ret < 0) {
kfree(dif->path);
@@ -499,6 +504,7 @@ static int erofs_fc_parse_param(struct fs_context *fc,
}
++sbi->devs->extra_devices;
break;
+ }
case Opt_domain_id:
if (!IS_ENABLED(CONFIG_EROFS_FS_PAGE_CACHE_SHARE)) {
errorfc(fc, "%s option not supported", erofs_fs_parameters[opt].name);
@@ -797,24 +803,21 @@ static int erofs_fc_reconfigure(struct fs_context *fc)
return 0;
}
-static int erofs_release_device_info(int id, void *ptr, void *data)
-{
- struct erofs_device_info *dif = ptr;
-
- fs_put_dax(dif->dax_dev, NULL);
- if (dif->file)
- fput(dif->file);
- kfree(dif->path);
- kfree(dif);
- return 0;
-}
-
static void erofs_free_dev_context(struct erofs_dev_context *devs)
{
+ struct erofs_device_info *dif;
+ unsigned long index;
+
if (!devs)
return;
- idr_for_each(&devs->tree, &erofs_release_device_info, NULL);
- idr_destroy(&devs->tree);
+ xa_for_each(&devs->tree, index, dif) {
+ fs_put_dax(dif->dax_dev, NULL);
+ if (dif->file)
+ fput(dif->file);
+ kfree(dif->path);
+ kfree(dif);
+ }
+ xa_destroy(&devs->tree);
kfree(devs);
}
@@ -858,7 +861,7 @@ static int erofs_init_fs_context(struct fs_context *fc)
}
fc->s_fs_info = sbi;
- idr_init(&sbi->devs->tree);
+ xa_init_flags(&sbi->devs->tree, XA_FLAGS_ALLOC);
init_rwsem(&sbi->devs->rwsem);
erofs_default_options(sbi);
fc->ops = &erofs_context_ops;
--
2.47.3
reply other threads:[~2026-07-15 3:35 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260715033507.1666-1-aditya.ansh182@gmail.com \
--to=aditya.ansh182@gmail.com \
--cc=chao@kernel.org \
--cc=dhavale@google.com \
--cc=guochunhai@vivo.com \
--cc=jefflexu@linux.alibaba.com \
--cc=lihongbo22@huawei.com \
--cc=linux-erofs@lists.ozlabs.org \
--cc=linux-kernel@vger.kernel.org \
--cc=xiang@kernel.org \
--cc=zbestahu@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome