Skip to content
/ linux Public

Commit 522acaa

Browse files
htejungregkh
authored andcommitted
sched_ext: Disable preemption between scx_claim_exit() and kicking helper work
[ Upstream commit 83236b2 ] scx_claim_exit() atomically sets exit_kind, which prevents scx_error() from triggering further error handling. After claiming exit, the caller must kick the helper kthread work which initiates bypass mode and teardown. If the calling task gets preempted between claiming exit and kicking the helper work, and the BPF scheduler fails to schedule it back (since error handling is now disabled), the helper work is never queued, bypass mode never activates, tasks stop being dispatched, and the system wedges. Disable preemption across scx_claim_exit() and the subsequent work kicking in all callers - scx_disable() and scx_vexit(). Add lockdep_assert_preemption_disabled() to scx_claim_exit() to enforce the requirement. Fixes: f0e1a06 ("sched_ext: Implement BPF extensible scheduler class") Cc: stable@vger.kernel.org # v6.12+ Reviewed-by: Andrea Righi <arighi@nvidia.com> Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent c1b8245 commit 522acaa

File tree

1 file changed

+12
-0
lines changed

1 file changed

+12
-0
lines changed

kernel/sched/ext.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4066,10 +4066,19 @@ static void scx_disable_workfn(struct kthread_work *work)
40664066
scx_bypass(false);
40674067
}
40684068

4069+
/*
4070+
* Claim the exit on @sch. The caller must ensure that the helper kthread work
4071+
* is kicked before the current task can be preempted. Once exit_kind is
4072+
* claimed, scx_error() can no longer trigger, so if the current task gets
4073+
* preempted and the BPF scheduler fails to schedule it back, the helper work
4074+
* will never be kicked and the whole system can wedge.
4075+
*/
40694076
static bool scx_claim_exit(struct scx_sched *sch, enum scx_exit_kind kind)
40704077
{
40714078
int none = SCX_EXIT_NONE;
40724079

4080+
lockdep_assert_preemption_disabled();
4081+
40734082
if (!atomic_try_cmpxchg(&sch->exit_kind, &none, kind))
40744083
return false;
40754084

@@ -4092,6 +4101,7 @@ static void scx_disable(enum scx_exit_kind kind)
40924101
rcu_read_lock();
40934102
sch = rcu_dereference(scx_root);
40944103
if (sch) {
4104+
guard(preempt)();
40954105
scx_claim_exit(sch, kind);
40964106
kthread_queue_work(sch->helper, &sch->disable_work);
40974107
}
@@ -4414,6 +4424,8 @@ static void scx_vexit(struct scx_sched *sch,
44144424
{
44154425
struct scx_exit_info *ei = sch->exit_info;
44164426

4427+
guard(preempt)();
4428+
44174429
if (!scx_claim_exit(sch, kind))
44184430
return;
44194431

0 commit comments

Comments
 (0)