From: Tejun Heo Date: Tue, 10 Mar 2026 17:12:21 +0000 (-1000) Subject: sched_ext: Reject sub-sched attachment to a disabled parent X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6b4576b09714def33890e04ef49621bca3614bbf;p=thirdparty%2Fkernel%2Flinux.git sched_ext: Reject sub-sched attachment to a disabled parent scx_claim_exit() propagates exits to descendants under scx_sched_lock. A sub-sched being attached concurrently could be missed if it links after the propagation. Check the parent's exit_kind in scx_link_sched() under scx_sched_lock to interlock against scx_claim_exit() - either the parent sees the child in its iteration or the child sees the parent's non-NONE exit_kind and fails attachment. Fixes: ebeca1f930ea ("sched_ext: Introduce cgroup sub-sched support") Signed-off-by: Tejun Heo Reviewed-by: Andrea Righi --- diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c index efba05725139a..e7ab3647e35fe 100644 --- a/kernel/sched/ext.c +++ b/kernel/sched/ext.c @@ -5247,6 +5247,17 @@ static s32 scx_link_sched(struct scx_sched *sch) s32 ret; if (parent) { + /* + * scx_claim_exit() propagates exit_kind transition to + * its sub-scheds while holding scx_sched_lock - either + * we can see the parent's non-NONE exit_kind or the + * parent can shoot us down. + */ + if (atomic_read(&parent->exit_kind) != SCX_EXIT_NONE) { + scx_error(sch, "parent disabled"); + return -ENOENT; + } + ret = rhashtable_lookup_insert_fast(&scx_sched_hash, &sch->hash_node, scx_sched_hash_params); if (ret) { @@ -5638,6 +5649,11 @@ static bool scx_claim_exit(struct scx_sched *sch, enum scx_exit_kind kind) * serialized, running them in separate threads allows parallelizing * ops.exit(), which can take arbitrarily long prolonging bypass mode. * + * To guarantee forward progress, this propagation must be in-line so + * that ->aborting is synchronously asserted for all sub-scheds. The + * propagation is also the interlocking point against sub-sched + * attachment. See scx_link_sched(). + * * This doesn't cause recursions as propagation only takes place for * non-propagation exits. */