mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
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