summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShakeel Butt <shakeel.butt@linux.dev>2026-03-11 04:00:59 +0300
committerTejun Heo <tj@kernel.org>2026-03-12 01:16:21 +0300
commit05070cd654f38346d051b8c411faff196fa58880 (patch)
treec3345845cbb27bca7b745d2d909991fb28eb2ca3
parent5b30afc20b3fea29b9beb83c6415c4ff06f774aa (diff)
downloadlinux-05070cd654f38346d051b8c411faff196fa58880.tar.xz
cgroup: reduce cgroup_file_kn_lock hold time in cgroup_file_notify()
cgroup_file_notify() calls kernfs_notify() while holding the global cgroup_file_kn_lock. kernfs_notify() does non-trivial work including wake_up_interruptible() and acquisition of a second global spinlock (kernfs_notify_lock), inflating the hold time. Take a kernfs_get() reference under the lock and call kernfs_notify() after dropping it, following the pattern from cgroup_file_show(). Reported-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev> Signed-off-by: Tejun Heo <tj@kernel.org>
-rw-r--r--kernel/cgroup/cgroup.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index cdc63be63f2c..26d8df60a59f 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -4632,6 +4632,7 @@ int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
void cgroup_file_notify(struct cgroup_file *cfile)
{
unsigned long flags;
+ struct kernfs_node *kn = NULL;
spin_lock_irqsave(&cgroup_file_kn_lock, flags);
if (cfile->kn) {
@@ -4641,11 +4642,17 @@ void cgroup_file_notify(struct cgroup_file *cfile)
if (time_in_range(jiffies, last, next)) {
timer_reduce(&cfile->notify_timer, next);
} else {
- kernfs_notify(cfile->kn);
+ kn = cfile->kn;
+ kernfs_get(kn);
cfile->notified_at = jiffies;
}
}
spin_unlock_irqrestore(&cgroup_file_kn_lock, flags);
+
+ if (kn) {
+ kernfs_notify(kn);
+ kernfs_put(kn);
+ }
}
EXPORT_SYMBOL_GPL(cgroup_file_notify);