[PATCH 1/3] kernfs: activate a new node without dropping kernfs_rwsem

From: Shakeel Butt

Date: Sat Sep 12 2026 - 22:15:32 EST


kernfs_add_one() links the node in, drops the kernfs_rwsem write lock,
then calls kernfs_activate(), which takes it again. Roots that do not
set KERNFS_ROOT_CREATE_DEACTIVATED, such as sysfs, therefore pay two
write locks for every file, directory and symlink created.

A new node has no children, so kernfs_activate() would walk only that
node. Call kernfs_activate_one() before dropping the lock instead. Its
two WARN_ON_ONCE()s still hold: the node was just linked, and nothing
can have changed its active count yet. This also closes the window
where a node is linked but not yet activated.

lock_stat, creating and destroying five dummy netdevs:

before after
kernfs_rwsem write acquires 1200 830

Assisted-by: LLM
Signed-off-by: Shakeel Butt <shakeel.butt@xxxxxxxxx>
---
fs/kernfs/dir.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index 07abf59f0264..8953e8a07537 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -30,6 +30,8 @@ static char kernfs_pr_cont_buf[PATH_MAX]; /* protected by pr_cont_lock */

#define rb_to_kn(X) rb_entry((X), struct kernfs_node, rb)

+static void kernfs_activate_one(struct kernfs_node *kn);
+
static bool __kernfs_active(struct kernfs_node *kn)
{
return atomic_read(&kn->active) >= 0;
@@ -861,7 +863,6 @@ int kernfs_add_one(struct kernfs_node *kn)
}

up_write(&root->kernfs_iattr_rwsem);
- up_write(&root->kernfs_rwsem);

/*
* Activate the new node unless CREATE_DEACTIVATED is requested.
@@ -869,9 +870,15 @@ int kernfs_add_one(struct kernfs_node *kn)
* activating the node with kernfs_activate(). A node which hasn't
* been activated is not visible to userland and its removal won't
* trigger deactivation.
+ *
+ * @kn has no children yet, so kernfs_activate() would walk only @kn.
+ * Do it here rather than dropping the write lock and taking it again
+ * for every new node.
*/
- if (!(kernfs_root(kn)->flags & KERNFS_ROOT_CREATE_DEACTIVATED))
- kernfs_activate(kn);
+ if (!(root->flags & KERNFS_ROOT_CREATE_DEACTIVATED))
+ kernfs_activate_one(kn);
+
+ up_write(&root->kernfs_rwsem);
return 0;

out_unlock:
--
2.53.0-Meta