diff options
| author | Tejun Heo <tj@kernel.org> | 2026-05-17 10:31:10 -1000 |
|---|---|---|
| committer | Tejun Heo <tj@kernel.org> | 2026-05-17 10:31:10 -1000 |
| commit | 1136fb1213d108f4776d4d8649ea96c57e93b41d (patch) | |
| tree | dd8a7b5f1201834f38762b4cb7be298aff212a28 | |
| parent | c9017d335aab23c4514daed79c939af52a9aa7f6 (diff) | |
| parent | 515e3996a4c26e7f955c13b3b19522a2c8642af9 (diff) | |
| download | linux-1136fb1213d108f4776d4d8649ea96c57e93b41d.tar.gz linux-1136fb1213d108f4776d4d8649ea96c57e93b41d.zip | |
Merge branch 'for-7.1-fixes' into for-7.2
Pull to receive:
39e25a210060 ("sched_ext: Drop NONE early return in scx_disable_and_exit_task()")
b273b75b8d67 ("sched_ext: INIT_LIST_HEAD() &sch->all in scx_alloc_and_add_sched()")
cceb874eee46 ("sched_ext: Defer sub_kset base put to scx_sched_free_rcu_work")
6ae315d37924 ("sched_ext: Use HK_TYPE_DOMAIN_BOOT to detect isolcpus= domain isolation")
515e3996a4c2 ("sched_ext: Fix deadlock between scx_root_disable() and concurrent forks")
to prepare for-7.2 for further sub-sched changes.
Signed-off-by: Tejun Heo <tj@kernel.org>
| -rw-r--r-- | kernel/sched/ext.c | 44 |
1 files changed, 29 insertions, 15 deletions
diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c index 64f8a096f133..9c458552d14f 100644 --- a/kernel/sched/ext.c +++ b/kernel/sched/ext.c @@ -3816,22 +3816,14 @@ static void scx_sub_init_cancel_task(struct scx_sched *sch, struct task_struct * static void scx_disable_and_exit_task(struct scx_sched *sch, struct task_struct *p) { - /* - * %NONE means @p is already detached at the SCX level (e.g. handed - * back to the parent by scx_fail_parent() with no init to undo). - * Skip to avoid clobbering scx_task_sched() and writing %NONE again - * on a state that's already %NONE. - */ - if (scx_get_task_state(p) == SCX_TASK_NONE) - return; - __scx_disable_and_exit_task(sch, p); /* * If set, @p exited between __scx_init_task() and scx_enable_task() in * scx_sub_enable() and is initialized for both the associated sched and * its parent. Exit for the child too - scx_enable_task() never ran for - * it, so undo only init_task. + * it, so undo only init_task. The flag is only set on the sub-enable + * path, so it's always clear when @p arrives here in %SCX_TASK_NONE. */ if (p->scx.flags & SCX_TASK_SUB_INIT) { if (!WARN_ON_ONCE(!scx_enabling_sub_sched)) @@ -4975,6 +4967,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) { @@ -5098,10 +5092,30 @@ static const struct kset_uevent_ops scx_uevent_ops = { */ bool task_should_scx(int policy) { - if (!scx_enabled() || unlikely(scx_enable_state() == SCX_DISABLING)) + /* if disabled, nothing should be on it */ + if (!scx_enabled()) return false; + + /* scx is taking over all SCHED_OTHER and SCHED_EXT tasks */ if (READ_ONCE(scx_switching_all)) return true; + + /* + * scx is tearing down - keep new SCHED_EXT tasks out. + * + * Must come after scx_switching_all test, which serves as a proxy + * for __scx_switched_all. While __scx_switched_all is set, we must + * return true via the branch above: a fork routed to fair would + * stall because next_active_class() skips fair. + * + * This can develop into a deadlock - scx holds scx_enable_mutex across + * kthread_create() in scx_alloc_and_add_sched(); if the new kthread is + * the stalled task, the disable path can never grab the mutex to clear + * scx_switching_all. + */ + if (unlikely(scx_enable_state() == SCX_DISABLING)) + return false; + return policy == SCHED_EXT; } @@ -6035,7 +6049,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 */ @@ -6161,7 +6175,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); @@ -6850,6 +6864,7 @@ static struct scx_sched *scx_alloc_and_add_sched(struct scx_enable_cmd *cmd, rcu_assign_pointer(ops->priv, sch); sch->kobj.kset = scx_kset; + INIT_LIST_HEAD(&sch->all); #ifdef CONFIG_EXT_SUB_SCHED char *buf = kzalloc(PATH_MAX, GFP_KERNEL); @@ -7677,8 +7692,7 @@ static s32 scx_enable(struct scx_enable_cmd *cmd, struct bpf_link *link) static struct kthread_worker *helper; static DEFINE_MUTEX(helper_mutex); - if (!cpumask_equal(housekeeping_cpumask(HK_TYPE_DOMAIN), - cpu_possible_mask)) { + if (housekeeping_enabled(HK_TYPE_DOMAIN_BOOT)) { pr_err("sched_ext: Not compatible with \"isolcpus=\" domain isolation\n"); return -EINVAL; } |
