DEFINE_MUTEX(kernfs_mutex);
static DEFINE_SPINLOCK(kernfs_rename_lock); /* kn->parent and ->name */
static char kernfs_pr_cont_buf[PATH_MAX]; /* protected by rename_lock */
-static DEFINE_SPINLOCK(kernfs_idr_lock); /* root->ino_idr */
#define rb_to_kn(X) rb_entry((X), struct kernfs_node, rb)
simple_xattrs_free(&kn->iattr->xattrs);
kmem_cache_free(kernfs_iattrs_cache, kn->iattr);
}
- spin_lock(&kernfs_idr_lock);
- idr_remove(&root->ino_idr, kn->id.ino);
- spin_unlock(&kernfs_idr_lock);
+ xa_erase(&root->inodes, kn->id.ino);
kmem_cache_free(kernfs_node_cache, kn);
kn = parent;
goto repeat;
} else {
/* just released the root kn, free @root too */
- idr_destroy(&root->ino_idr);
kfree(root);
}
}
unsigned flags)
{
struct kernfs_node *kn;
- u32 gen;
- int cursor;
int ret;
name = kstrdup_const(name, GFP_KERNEL);
if (!kn)
goto err_out1;
- idr_preload(GFP_KERNEL);
- spin_lock(&kernfs_idr_lock);
- cursor = idr_get_cursor(&root->ino_idr);
- ret = idr_alloc_cyclic(&root->ino_idr, kn, 1, 0, GFP_ATOMIC);
- if (ret >= 0 && ret < cursor)
+ xa_lock(&root->inodes);
+ ret = __xa_alloc_cyclic(&root->inodes, &kn->id.ino, kn, xa_limit_32b,
+ &root->inode_next, GFP_KERNEL);
+ if (ret == 1)
root->next_generation++;
- gen = root->next_generation;
- spin_unlock(&kernfs_idr_lock);
- idr_preload_end();
+ kn->id.generation = root->next_generation;
+ xa_unlock(&root->inodes);
+
if (ret < 0)
goto err_out2;
- kn->id.ino = ret;
- kn->id.generation = gen;
/*
* set ino first. This RELEASE is paired with atomic_inc_not_zero in
return kn;
err_out3:
- idr_remove(&root->ino_idr, kn->id.ino);
+ xa_erase(&root->inodes, kn->id.ino);
err_out2:
kmem_cache_free(kernfs_node_cache, kn);
err_out1:
struct kernfs_node *kn;
rcu_read_lock();
- kn = idr_find(&root->ino_idr, ino);
+ kn = xa_load(&root->inodes, ino);
if (!kn)
goto out;
if (!root)
return ERR_PTR(-ENOMEM);
- idr_init(&root->ino_idr);
- INIT_LIST_HEAD(&root->supers);
+ xa_init_flags(&root->inodes, XA_FLAGS_ALLOC1);
root->next_generation = 1;
+ INIT_LIST_HEAD(&root->supers);
kn = __kernfs_new_node(root, NULL, "", S_IFDIR | S_IRUGO | S_IXUGO,
GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
KERNFS_DIR);
if (!kn) {
- idr_destroy(&root->ino_idr);
kfree(root);
return ERR_PTR(-ENOMEM);
}