Commit cec59c44 authored by Jinliang Zheng's avatar Jinliang Zheng Committed by Greg Kroah-Hartman
Browse files

kernfs: switch global kernfs_idr_lock to per-fs lock



The kernfs implementation has big lock granularity(kernfs_idr_lock) so
every kernfs-based(e.g., sysfs, cgroup) fs are able to compete the lock.

This patch switches the global kernfs_idr_lock to per-fs lock, which
put the spinlock into kernfs_root.

Signed-off-by: default avatarJinliang Zheng <alexjlzheng@tencent.com>
Acked-by: default avatarTejun Heo <tj@kernel.org>
Link: https://lore.kernel.org/r/20250415153659.14950-2-alexjlzheng@tencent.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 2806c6b8
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ 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)

@@ -584,9 +583,9 @@ void kernfs_put(struct kernfs_node *kn)
	if (kernfs_type(kn) == KERNFS_LINK)
		kernfs_put(kn->symlink.target_kn);

	spin_lock(&kernfs_idr_lock);
	spin_lock(&root->kernfs_idr_lock);
	idr_remove(&root->ino_idr, (u32)kernfs_ino(kn));
	spin_unlock(&kernfs_idr_lock);
	spin_unlock(&root->kernfs_idr_lock);

	call_rcu(&kn->rcu, kernfs_free_rcu);

@@ -639,13 +638,13 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
		goto err_out1;

	idr_preload(GFP_KERNEL);
	spin_lock(&kernfs_idr_lock);
	spin_lock(&root->kernfs_idr_lock);
	ret = idr_alloc_cyclic(&root->ino_idr, kn, 1, 0, GFP_ATOMIC);
	if (ret >= 0 && ret < root->last_id_lowbits)
		root->id_highbits++;
	id_highbits = root->id_highbits;
	root->last_id_lowbits = ret;
	spin_unlock(&kernfs_idr_lock);
	spin_unlock(&root->kernfs_idr_lock);
	idr_preload_end();
	if (ret < 0)
		goto err_out2;
@@ -681,9 +680,9 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
	return kn;

 err_out3:
	spin_lock(&kernfs_idr_lock);
	spin_lock(&root->kernfs_idr_lock);
	idr_remove(&root->ino_idr, (u32)kernfs_ino(kn));
	spin_unlock(&kernfs_idr_lock);
	spin_unlock(&root->kernfs_idr_lock);
 err_out2:
	kmem_cache_free(kernfs_node_cache, kn);
 err_out1:
@@ -989,6 +988,7 @@ struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops,
		return ERR_PTR(-ENOMEM);

	idr_init(&root->ino_idr);
	spin_lock_init(&root->kernfs_idr_lock);
	init_rwsem(&root->kernfs_rwsem);
	init_rwsem(&root->kernfs_iattr_rwsem);
	init_rwsem(&root->kernfs_supers_rwsem);
+1 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ struct kernfs_root {

	/* private fields, do not use outside kernfs proper */
	struct idr		ino_idr;
	spinlock_t		kernfs_idr_lock;	/* root->ino_idr */
	u32			last_id_lowbits;
	u32			id_highbits;
	struct kernfs_syscall_ops *syscall_ops;