sched_ext: Don't enable non-ext tasks in the sub-sched task loops

Root enable and scx_post_fork() enable a task only if it's on the ext class.
Tasks on other classes, possible under an SCX_OPS_SWITCH_PARTIAL root, are
left READY and enabled by switching_to_scx() when they switch over. The sub
enable-commit pass and the sub-disable re-home loop enable unconditionally,
so a fair-class READY task in the subtree becomes ENABLED while not on
sched_ext. A later switch to SCHED_EXT then trips the task state validation
WARN (ENABLED with the previous state not READY) and calls ops.enable() a
second time.

Gate scx_enable_task() on the task's class in both loops.

Fixes: 337ec00b1d ("sched_ext: Implement cgroup sub-sched enabling and disabling")
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Andrea Righi <arighi@nvidia.com>
This commit is contained in:
Tejun Heo
2026-07-16 10:46:04 -10:00
parent 8c13364db9
commit 5cdc928598

View File

@@ -6010,15 +6010,22 @@ static void scx_sub_disable(struct scx_sched *sch)
/*
* $p is initialized for $parent and still attached to
* @sch. Disable and exit for @sch, switch over to
* $parent, override the state to READY to account for
* $p having already been initialized, and then enable.
* $parent and override the state to READY to account
* for $p having already been initialized.
*/
scx_disable_and_exit_task(sch, p);
scx_set_task_state(p, SCX_TASK_INIT_BEGIN);
scx_set_task_state(p, SCX_TASK_INIT);
scx_set_task_sched(p, parent);
scx_set_task_state(p, SCX_TASK_READY);
scx_enable_task(parent, p);
/*
* A task on a non-ext class, possible under an
* %SCX_OPS_SWITCH_PARTIAL root, stays READY and is
* enabled by switching_to_scx() if it switches over.
*/
if (p->sched_class == &ext_sched_class)
scx_enable_task(parent, p);
}
task_rq_unlock(rq, p, &rf);
@@ -7726,10 +7733,14 @@ static void scx_sub_enable_workfn(struct kthread_work *work)
/*
* $p is now only initialized for @sch and READY, which
* is what we want. Assign it to @sch and enable.
* is what we want. Assign it to @sch and, if it's on
* the ext class, enable. A non-ext task, possible under
* an %SCX_OPS_SWITCH_PARTIAL root, stays READY and is
* enabled by switching_to_scx() if it switches over.
*/
scx_set_task_sched(p, sch);
scx_enable_task(sch, p);
if (p->sched_class == &ext_sched_class)
scx_enable_task(sch, p);
p->scx.flags &= ~SCX_TASK_SUB_INIT;
}