fs/kernfs/dir.c | 34 ++++++++++++++-------------------- fs/kernfs/kernfs-internal.h | 3 ++- 2 files changed, 16 insertions(+), 21 deletions(-)
IDR is deprecated. Use xarray instead.
Signed-off-by: Su Hui <suhui@nfschina.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
On Thu, Jan 16, 2025 at 04:48:02PM +0800, Su Hui wrote: > IDR is deprecated. Use xarray instead. Why? What helped by doing this? Is it faster? Slower? Less memory? More memory? Where did the lock go? You need to provide so much more information here than you provided in order for us to be able to even consider reviewing this change. Please read the documentation for how to write a good changelog text, that is very important, ESPECIALLY when dealing with core kernel bits. thanks, greg k-h
On 2025/1/16 17:54, Greg KH wrote: > On Thu, Jan 16, 2025 at 04:48:02PM +0800, Su Hui wrote: >> IDR is deprecated. Use xarray instead. > Why? What helped by doing this? Is it faster? Slower? Less memory? > More memory? Where did the lock go? > > You need to provide so much more information here than you provided in > order for us to be able to even consider reviewing this change. Please > read the documentation for how to write a good changelog text, that is > very important, ESPECIALLY when dealing with core kernel bits. Sorry for the poor information, I will collect more information and data later. Thanks for your suggestion. Su Hui
© 2016 - 2025 Red Hat, Inc.