Skip to content

Commit 9753358

Browse files
committed
sched_ext: Fix SCX_TASK_INIT -> SCX_TASK_READY transitions in scx_ops_enable()
scx_ops_enable() has two task iteration loops. The first one calls scx_ops_init_task() on every task and the latter switches the eligible ones into SCX. The first loop left the tasks in SCX_TASK_INIT state and then the second loop switched it into READY before switching the task into SCX. The distinction between INIT and READY is only meaningful in the fork path where it's used to tell whether the task finished forking so that we can tell ops.exit_task() accordingly. Leaving task in INIT state between the two loops is incosistent with the fork path and incorrect. The following can be triggered by running a program which keeps toggling a task between SCHED_OTHER and SCHED_SCX while enabling a task: sched_ext: Invalid task state transition 1 -> 3 for fish[1526] WARNING: CPU: 2 PID: 1615 at kernel/sched/ext.c:3393 scx_ops_enable_task+0x1a1/0x200 ... Sched_ext: qmap (enabling+all) RIP: 0010:scx_ops_enable_task+0x1a1/0x200 ... switching_to_scx+0x13/0xa0 __sched_setscheduler+0x850/0xa50 do_sched_setscheduler+0x104/0x1c0 __x64_sys_sched_setscheduler+0x18/0x30 do_syscall_64+0x7b/0x140 entry_SYSCALL_64_after_hwframe+0x76/0x7e Fix it by transitioning to READY in the first loop right after scx_ops_init_task() succeeds. Signed-off-by: Tejun Heo <[email protected]> Cc: David Vernet <[email protected]>
1 parent 8c2090c commit 9753358

File tree

1 file changed

+3
-2
lines changed

1 file changed

+3
-2
lines changed

kernel/sched/ext.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5166,6 +5166,8 @@ static int scx_ops_enable(struct sched_ext_ops *ops, struct bpf_link *link)
51665166
goto err_disable_unlock_all;
51675167
}
51685168

5169+
scx_set_task_state(p, SCX_TASK_READY);
5170+
51695171
put_task_struct(p);
51705172
spin_lock_irq(&scx_tasks_lock);
51715173
}
@@ -5178,7 +5180,7 @@ static int scx_ops_enable(struct sched_ext_ops *ops, struct bpf_link *link)
51785180
WRITE_ONCE(scx_switching_all, !(ops->flags & SCX_OPS_SWITCH_PARTIAL));
51795181

51805182
/*
5181-
* We're fully committed and can't fail. The PREPPED -> ENABLED
5183+
* We're fully committed and can't fail. The task READY -> ENABLED
51825184
* transitions here are synchronized against sched_ext_free() through
51835185
* scx_tasks_lock.
51845186
*/
@@ -5190,7 +5192,6 @@ static int scx_ops_enable(struct sched_ext_ops *ops, struct bpf_link *link)
51905192

51915193
sched_deq_and_put_task(p, DEQUEUE_SAVE | DEQUEUE_MOVE, &ctx);
51925194

5193-
scx_set_task_state(p, SCX_TASK_READY);
51945195
__setscheduler_prio(p, p->prio);
51955196
check_class_changing(task_rq(p), p, old_class);
51965197

0 commit comments

Comments
 (0)