From: Tejun Heo Date: Sun, 10 May 2026 22:51:09 +0000 (-1000) Subject: Merge branch 'for-7.1-fixes' into for-7.2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b5646c627652241f248f0a4ff31b1d32316b0068;p=thirdparty%2Fkernel%2Flinux.git Merge branch 'for-7.1-fixes' into for-7.2 Conflict between: [1] 41e3312861ea ("sched_ext: add p->scx.tid and SCX_OPS_TID_TO_TASK lookup") [2] c941d7391f25 ("sched_ext: Close root-enable vs sched_ext_dead() race with SCX_TASK_INIT_BEGIN") in scx_root_enable_workfn()'s post-init block. [1] added a tid hash insertion under a scoped_guard() for scx_tasks_lock; [2] wraps the same region in task_rq_lock() for a DEAD recheck. A naive merge would invert the iter's outer/inner order. [3] f25ad1e3cbaa ("sched_ext: Add scx_task_iter_relock() and use it in scx_root_enable_workfn()") was added to for-7.2 for a clean resolution: scx_task_iter_relock(iter, p) takes both scx_tasks_lock and @p's rq lock in iter order. Resolved by routing both sides through [3]'s dual-lock helper: the post-init region runs under a single scx_task_iter_relock() acquisition, with [2]'s state machine and [1]'s hash insert in sequence inside it. Signed-off-by: Tejun Heo --- b5646c627652241f248f0a4ff31b1d32316b0068 diff --cc kernel/sched/ext.c index fbdc1819d4cb0,4efe0099f79af..b8dd3358959d7 --- a/kernel/sched/ext.c +++ b/kernel/sched/ext.c @@@ -7079,13 -6936,26 +7188,25 @@@ static void scx_root_enable_workfn(stru if (!tryget_task_struct(p)) continue; + /* + * Set %INIT_BEGIN under the iter's rq lock so that a concurrent + * sched_ext_dead() does not call ops.exit_task() on @p while + * ops.init_task() is running. If sched_ext_dead() runs before + * this store, it has already removed @p from scx_tasks and the + * iter won't visit @p; if it runs after, it observes + * %INIT_BEGIN and transitions to %DEAD without calling ops, + * leaving the post-init recheck below to unwind. + */ + scx_set_task_state(p, SCX_TASK_INIT_BEGIN); scx_task_iter_unlock(&sti); - ret = scx_init_task(sch, p, false); + ret = __scx_init_task(sch, p, false); - rq = task_rq_lock(p, &rf); + scx_task_iter_relock(&sti, p); - if (ret) { + if (unlikely(ret)) { + if (scx_get_task_state(p) != SCX_TASK_DEAD) + scx_set_task_state(p, SCX_TASK_NONE); - task_rq_unlock(rq, p, &rf); put_task_struct(p); scx_task_iter_stop(&sti); scx_error(sch, "ops.init_task() failed (%d) for %s[%d]", @@@ -7093,17 -6963,20 +7214,27 @@@ goto err_disable_unlock_all; } - scx_set_task_sched(p, sch); - scx_set_task_state(p, SCX_TASK_READY); + if (scx_get_task_state(p) == SCX_TASK_DEAD) { + /* + * sched_ext_dead() observed %INIT_BEGIN and set %DEAD. + * ops.exit_task() is owed to the sched __scx_init_task() + * ran against; call it now. + */ + scx_sub_init_cancel_task(sch, p); + } else { + scx_set_task_state(p, SCX_TASK_INIT); + scx_set_task_sched(p, sch); + scx_set_task_state(p, SCX_TASK_READY); + } - task_rq_unlock(rq, p, &rf); + /* + * Insert into the tid hash. scx_tasks_lock is held by the iter; + * list_empty() guards against sched_ext_dead() having taken @p + * off the list while init ran unlocked. + */ + if (scx_tid_to_task_enabled() && !list_empty(&p->scx.tasks_node)) + scx_tid_hash_insert(p); + put_task_struct(p); } scx_task_iter_stop(&sti);