summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2026-05-17 10:31:10 -1000
committerTejun Heo <tj@kernel.org>2026-05-17 10:31:10 -1000
commit1136fb1213d108f4776d4d8649ea96c57e93b41d (patch)
treedd8a7b5f1201834f38762b4cb7be298aff212a28
parentc9017d335aab23c4514daed79c939af52a9aa7f6 (diff)
parent515e3996a4c26e7f955c13b3b19522a2c8642af9 (diff)
downloadlinux-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.c44
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;
}