]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
Merge branch 'for-7.1-fixes' into for-7.2
authorTejun Heo <tj@kernel.org>
Sun, 10 May 2026 22:51:09 +0000 (12:51 -1000)
committerTejun Heo <tj@kernel.org>
Sun, 10 May 2026 22:51:09 +0000 (12:51 -1000)
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 <tj@kernel.org>
1  2 
include/linux/sched/ext.h
kernel/sched/ext.c
kernel/sched/ext_idle.c

Simple merge
index fbdc1819d4cb0353b6cf065e5163f010930552ac,4efe0099f79af870149c378fec897d28332a6f94..b8dd3358959d737fd015c20dac28cdc4779f14e9
@@@ -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]",
                        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);
Simple merge