sched_ext: Reject setting disallow from init_task outside the enable path

The p->scx.disallow revert assumes the root enable path, where the switching
loop reads the reverted policy right afterwards and leaves the task off SCX.
The sub-scheduler disable path also reaches it when re-initializing the
returned tasks on a root parent. Nothing reads the policy there: the task is
enabled on root anyway and keeps running on the ext class with a silently
rewritten policy.

Kill the sched instead, matching the fork and non-root branches, and update
the disallow documentation, which equated !fork with the load path and
pointed at a stale debugfs path for nr_rejected.

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-17 21:28:57 -10:00
parent 0e2f4ab68a
commit 477869bfaf
2 changed files with 8 additions and 5 deletions
+5 -5
View File
@@ -244,11 +244,11 @@ struct sched_ext_entity {
* to %SCHED_EXT with -%EACCES.
*
* Can be set from ops.init_task() while the BPF scheduler is being
* loaded (!scx_init_task_args->fork). If set and the task's policy is
* already %SCHED_EXT, the task's policy is rejected and forcefully
* reverted to %SCHED_NORMAL. The number of such events are reported
* through /sys/kernel/debug/sched_ext::nr_rejected. Setting this flag
* during fork is not allowed.
* loaded. If set and the task's policy is already %SCHED_EXT, the
* task's policy is rejected and forcefully reverted to %SCHED_NORMAL.
* The number of such events are reported through
* /sys/kernel/sched_ext/nr_rejected. Setting this flag from any other
* ops.init_task() invocation, such as during fork, fails the scheduler.
*/
bool disallow; /* reject switching into SCX */
+3
View File
@@ -3606,6 +3606,9 @@ static int __scx_init_task(struct scx_sched *sch, struct task_struct *p, bool fo
} else if (unlikely(fork)) {
scx_error(sch, "ops.init_task() set task->scx.disallow for %s[%d] during fork",
p->comm, p->pid);
} else if (unlikely(scx_enable_state() != SCX_ENABLING)) {
scx_error(sch, "ops.init_task() set task->scx.disallow for %s[%d] outside the enable path",
p->comm, p->pid);
} else {
struct rq *rq;
struct rq_flags rf;