summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2026-05-11 13:18:23 -1000
committerTejun Heo <tj@kernel.org>2026-05-12 11:28:56 -1000
commitcceb874eee46fe4b3d3c6c496f19125d9a3a9a8f (patch)
tree0e95ed7f1013afcc60734dd84ceac95ca84c8b6a /kernel
parentb273b75b8d677aea06dd06d80b61b3bb06e94680 (diff)
downloadlinux-cceb874eee46fe4b3d3c6c496f19125d9a3a9a8f.tar.gz
linux-cceb874eee46fe4b3d3c6c496f19125d9a3a9a8f.zip
sched_ext: Defer sub_kset base put to scx_sched_free_rcu_work
scx_sub_enable_workfn() pins parent->kobj before dropping scx_sched_lock, but that does not pin parent->sub_kset. Concurrent disable can kset_unregister and free sub_kset before scx_alloc_and_add_sched() dereferences it. Split sub_kset teardown: kobject_del() at disable keeps sysfs removal; defer kobject_put() to scx_sched_free_rcu_work so the memory survives. A racing child sees state_in_sysfs=0 with valid memory, sysfs_create_dir() fails, and the existing exit_kind gate in scx_link_sched() turns it away with -ENOENT. Fixes: 411d3ef1a705 ("sched_ext: Unregister sub_kset on scheduler disable") Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sched/ext.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c
index 6d69ba29cfd7..23f7b3f63b09 100644
--- a/kernel/sched/ext.c
+++ b/kernel/sched/ext.c
@@ -4821,6 +4821,8 @@ static void scx_sched_free_rcu_work(struct work_struct *work)
kfree(sch->cgrp_path);
if (sch_cgroup(sch))
cgroup_put(sch_cgroup(sch));
+ if (sch->sub_kset)
+ kobject_put(&sch->sub_kset->kobj);
#endif /* CONFIG_EXT_SUB_SCHED */
for_each_possible_cpu(cpu) {
@@ -5861,7 +5863,7 @@ static void scx_sub_disable(struct scx_sched *sch)
if (sch->ops.exit)
SCX_CALL_OP(sch, exit, NULL, sch->exit_info);
if (sch->sub_kset)
- kset_unregister(sch->sub_kset);
+ kobject_del(&sch->sub_kset->kobj);
kobject_del(&sch->kobj);
}
#else /* CONFIG_EXT_SUB_SCHED */
@@ -5995,7 +5997,7 @@ static void scx_root_disable(struct scx_sched *sch)
*/
#ifdef CONFIG_EXT_SUB_SCHED
if (sch->sub_kset)
- kset_unregister(sch->sub_kset);
+ kobject_del(&sch->sub_kset->kobj);
#endif
kobject_del(&sch->kobj);