lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250116084801.260460-1-suhui@nfschina.com>
Date: Thu, 16 Jan 2025 16:48:02 +0800
From: Su Hui <suhui@...china.com>
To: gregkh@...uxfoundation.org,
	tj@...nel.org
Cc: Su Hui <suhui@...china.com>,
	linux-kernel@...r.kernel.org,
	kernel-janitors@...r.kernel.org
Subject: [PATCH] kernfs: Convert idr to xarray

IDR is deprecated. Use xarray instead.

Signed-off-by: Su Hui <suhui@...china.com>
---
 fs/kernfs/dir.c             | 34 ++++++++++++++--------------------
 fs/kernfs/kernfs-internal.h |  3 ++-
 2 files changed, 16 insertions(+), 21 deletions(-)

diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index 458519e416fe..8d0af0ae6c99 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -10,7 +10,7 @@
 #include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/namei.h>
-#include <linux/idr.h>
+#include <linux/xarray.h>
 #include <linux/slab.h>
 #include <linux/security.h>
 #include <linux/hash.h>
@@ -27,7 +27,6 @@ static DEFINE_RWLOCK(kernfs_rename_lock);	/* kn->parent and ->name */
  */
 static DEFINE_SPINLOCK(kernfs_pr_cont_lock);
 static char kernfs_pr_cont_buf[PATH_MAX];	/* protected by pr_cont_lock */
-static DEFINE_SPINLOCK(kernfs_idr_lock);	/* root->ino_idr */
 
 #define rb_to_kn(X) rb_entry((X), struct kernfs_node, rb)
 
@@ -571,9 +570,7 @@ void kernfs_put(struct kernfs_node *kn)
 	if (kernfs_type(kn) == KERNFS_LINK)
 		kernfs_put(kn->symlink.target_kn);
 
-	spin_lock(&kernfs_idr_lock);
-	idr_remove(&root->ino_idr, (u32)kernfs_ino(kn));
-	spin_unlock(&kernfs_idr_lock);
+	xa_erase(&root->ino_xa, (u32)kernfs_ino(kn));
 
 	call_rcu(&kn->rcu, kernfs_free_rcu);
 
@@ -583,7 +580,7 @@ void kernfs_put(struct kernfs_node *kn)
 			goto repeat;
 	} else {
 		/* just released the root kn, free @root too */
-		idr_destroy(&root->ino_idr);
+		xa_destroy(&root->ino_xa);
 		kfree_rcu(root, rcu);
 	}
 }
@@ -616,6 +613,7 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
 	struct kernfs_node *kn;
 	u32 id_highbits;
 	int ret;
+	u32 id;
 
 	name = kstrdup_const(name, GFP_KERNEL);
 	if (!name)
@@ -625,19 +623,16 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
 	if (!kn)
 		goto err_out1;
 
-	idr_preload(GFP_KERNEL);
-	spin_lock(&kernfs_idr_lock);
-	ret = idr_alloc_cyclic(&root->ino_idr, kn, 1, 0, GFP_ATOMIC);
-	if (ret >= 0 && ret < root->last_id_lowbits)
+	ret = xa_alloc_cyclic(&root->ino_xa, &id, kn, XA_LIMIT(1, INT_MAX),
+			      &root->ino_xa_next_id, GFP_ATOMIC);
+	if (ret >= 0 && id < root->last_id_lowbits)
 		root->id_highbits++;
 	id_highbits = root->id_highbits;
-	root->last_id_lowbits = ret;
-	spin_unlock(&kernfs_idr_lock);
-	idr_preload_end();
+	root->last_id_lowbits = id;
 	if (ret < 0)
 		goto err_out2;
 
-	kn->id = (u64)id_highbits << 32 | ret;
+	kn->id = (u64)id_highbits << 32 | id;
 
 	atomic_set(&kn->count, 1);
 	atomic_set(&kn->active, KN_DEACTIVATED_BIAS);
@@ -668,9 +663,7 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
 	return kn;
 
  err_out3:
-	spin_lock(&kernfs_idr_lock);
-	idr_remove(&root->ino_idr, (u32)kernfs_ino(kn));
-	spin_unlock(&kernfs_idr_lock);
+	xa_erase(&root->ino_xa, (u32)kernfs_ino(kn));
  err_out2:
 	kmem_cache_free(kernfs_node_cache, kn);
  err_out1:
@@ -726,7 +719,7 @@ struct kernfs_node *kernfs_find_and_get_node_by_id(struct kernfs_root *root,
 
 	rcu_read_lock();
 
-	kn = idr_find(&root->ino_idr, (u32)ino);
+	kn = xa_load(&root->ino_xa, (u32)ino);
 	if (!kn)
 		goto err_unlock;
 
@@ -968,11 +961,12 @@ struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops,
 	if (!root)
 		return ERR_PTR(-ENOMEM);
 
-	idr_init(&root->ino_idr);
+	xa_init_flags(&root->ino_xa, XA_FLAGS_ALLOC1);
 	init_rwsem(&root->kernfs_rwsem);
 	init_rwsem(&root->kernfs_iattr_rwsem);
 	init_rwsem(&root->kernfs_supers_rwsem);
 	INIT_LIST_HEAD(&root->supers);
+	root->ino_xa_next_id = 1;
 
 	/*
 	 * On 64bit ino setups, id is ino.  On 32bit, low 32bits are ino.
@@ -989,7 +983,7 @@ struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops,
 			       GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
 			       KERNFS_DIR);
 	if (!kn) {
-		idr_destroy(&root->ino_idr);
+		xa_destroy(&root->ino_xa);
 		kfree(root);
 		return ERR_PTR(-ENOMEM);
 	}
diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h
index b42ee6547cdc..1b77e1a6e5a1 100644
--- a/fs/kernfs/kernfs-internal.h
+++ b/fs/kernfs/kernfs-internal.h
@@ -37,7 +37,8 @@ struct kernfs_root {
 	unsigned int		flags;	/* KERNFS_ROOT_* flags */
 
 	/* private fields, do not use outside kernfs proper */
-	struct idr		ino_idr;
+	struct xarray		ino_xa;
+	u32			ino_xa_next_id;
 	u32			last_id_lowbits;
 	u32			id_highbits;
 	struct kernfs_syscall_ops *syscall_ops;
-- 
2.30.2


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ