]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
kernfs: switch global kernfs_idr_lock to per-fs lock
authorJinliang Zheng <alexjlzheng@tencent.com>
Tue, 15 Apr 2025 15:36:58 +0000 (23:36 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 25 Apr 2025 14:01:56 +0000 (16:01 +0200)
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: Jinliang Zheng <alexjlzheng@tencent.com>
Acked-by: Tejun Heo <tj@kernel.org>
Link: https://lore.kernel.org/r/20250415153659.14950-2-alexjlzheng@tencent.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/kernfs/dir.c
fs/kernfs/kernfs-internal.h

index fc70d72c3fe805d076ef2d553d79984d468f1273..355d943ffe274721afbb48f19d9c8286ec1d8e6b 100644 (file)
@@ -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);
index 40a2a9cd819d038409316ce5365a6b1753638d8d..24e9514565ac10931fece0a10285422253fbd4c6 100644 (file)
@@ -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;