Skip to content

Commit 83236b2

Browse files
committed
sched_ext: Disable preemption between scx_claim_exit() and kicking helper work
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>
1 parent ee0ff66 commit 83236b2

1 file changed

Lines changed: 12 additions & 0 deletions

File tree

kernel/sched/ext.c

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

4426+
/*
4427+
* Claim the exit on @sch. The caller must ensure that the helper kthread work
4428+
* is kicked before the current task can be preempted. Once exit_kind is
4429+
* claimed, scx_error() can no longer trigger, so if the current task gets
4430+
* preempted and the BPF scheduler fails to schedule it back, the helper work
4431+
* will never be kicked and the whole system can wedge.
4432+
*/
44264433
static bool scx_claim_exit(struct scx_sched *sch, enum scx_exit_kind kind)
44274434
{
44284435
int none = SCX_EXIT_NONE;
44294436

4437+
lockdep_assert_preemption_disabled();
4438+
44304439
if (!atomic_try_cmpxchg(&sch->exit_kind, &none, kind))
44314440
return false;
44324441

@@ -4449,6 +4458,7 @@ static void scx_disable(enum scx_exit_kind kind)
44494458
rcu_read_lock();
44504459
sch = rcu_dereference(scx_root);
44514460
if (sch) {
4461+
guard(preempt)();
44524462
scx_claim_exit(sch, kind);
44534463
kthread_queue_work(sch->helper, &sch->disable_work);
44544464
}
@@ -4771,6 +4781,8 @@ static bool scx_vexit(struct scx_sched *sch,
47714781
{
47724782
struct scx_exit_info *ei = sch->exit_info;
47734783

4784+
guard(preempt)();
4785+
47744786
if (!scx_claim_exit(sch, kind))
47754787
return false;
47764788

0 commit comments

Comments
 (0)