sched-ext discussion
[PATCH] sched_ext: don't rehome a dead task in scx_cgroup_task_migrated
LLM 分析
sched_ext:cgroup 迁移回调 rehoming 死亡任务 race 的驳回讨论
系列概况
- 标题:
[PATCH] sched_ext: don't rehome a dead task in scx_cgroup_task_migrated - 作者:Tao Cui cuitao@kylinos.cn
- 版本:单 patch,无版本号(
[PATCH]) - 规模:1 file changed, 7 insertions(+)
- 修改文件:
kernel/sched/ext/sub.c - 代码统计:新增 7 行(
SCX_TASK_DEAD检查 + 提前返回 +task_rq_unlock) - Message-ID:
20260811103122.357067-1-cui.tao@linux.dev - 完整性:完整(含
Fixes:tag 与Signed-off-by),但已被 maintainer 在第 2 封邮件驳回,第 3 封作者本人认错,整条 patch 预计不会被合并。
补丁目的
scx_cgroup_task_migrated() 是 cgroup 迁移完成时通知 sched_ext 的回调。补丁想在这里加一个守卫:当任务已经被 sched_ext_dead() 标记为 SCX_TASK_DEAD 时,跳过 scx_rehome_task(),避免把死亡任务重新挂到新 cgroup 后泄漏 BPF 调度器的 per-task 资源(cgrp、aux 等)。
简单说:作者以为「cgroup 迁移 commit 和 MIGRATED 回调之间存在窗口,任务可能在这期间退出、被错误唤醒并重新启用」,所以想堵这个窗口。
关键实现
补丁 diff 关键内容:
static void scx_cgroup_task_migrated(struct cgroup_task_migrate_ctx *ctx)
{
...
+ if (scx_get_task_state(p) == SCX_TASK_DEAD) {
+ /* sched_ext_dead() raced us */
+ task_rq_unlock(rq, p, &rf);
+ return;
+ }
scx_rehome_task(to, p);
...
}
逻辑是:拿住 rq 锁之后先看任务是否已走到 sched_ext_dead(),是的话直接放锁返回。作者注释写的是 sched_ext_dead() raced us。
Fixes: bf9dee58ab56 ("sched_ext: Re-home tasks on cgroup migration") 指明这条修复针对引入 scx_rehome_task() 到 cgroup 迁移路径的那个 commit。
讨论走向(驳回)
Maintainer Tejun Heo 在第 2 封回复里给出非常具体的锁顺序分析:
SCX_TASK_DEAD只在finish_task_switch()->sched_ext_dead()里设置;finish_task_switch()之前必经exit_signals(),而exit_signals()在cgroup_threadgroup_change_begin()内拿 threadgroup rwsem;MIGRATED通知由cgroup_migrate_execute()执行,全程cgroup_attach_lock()write-held 同一把 rwsem;- 因此迁移集合内的任务在迁移完成前根本走不到 exit 路径;已在退出的任务在更早的
cgroup_migrate_add_task()阶段就被PF_EXITING检查过滤掉了; - 作者引用的
DEAD检查都在scx_task_iter那些不走 threadgroup rwsem 的遍历里,那是另一个语境。
Tejun 还附带流程建议:code review 发现疑似 bug,先尝试 repro 再写补丁。
第 3 封作者直接认错:You're right, I missed that. I walked it again, a task past exit_signals() is filtered。
类比
把 cgroup 迁移回调路径想象成一次「集体搬迁」:
cgroup_attach_lock()是小区大门锁,写锁期间整个小区只允许「搬家工人」(迁移回调)进出;- 任何想「出门」(进入 exit 流程)的住户都得先到门卫那里登记拿 threadgroup rwsem;
- 因为大门一直被搬家工人占着,
exit_signals()根本进不来; - 「已经在门卫那里排队等出门」的住户,在
cgroup_migrate_add_task()阶段就被认出「你这人已经在走 exit 流程了,别混进搬家队伍」过滤掉。
所以「搬家工人(MIGRATED 回调)」碰到一个真正死亡的任务这件事,在锁结构下不会发生。补丁作者相当于在完全关着的小区里又装了一道门——保险,但不是必需。
ASCII 锁顺序图
cgroup_migrate_add_task()
|
v
PF_EXITING test -> filter dying tasks
|
v
cgroup_threadgroup_change_begin()
cgroup_attach_lock() (write-held rwsem)
|
v
+------ cgroup_migrate_execute() --------+
| MIGRATED notifiers |
| +-- scx_cgroup_task_migrated() |
| | +-- task_rq_lock(p, &rf) |
| | +-- (proposed) DEAD check? |
| | +-- scx_rehome_task(to, p) |
+----------------------------------------+
|
v
cgroup_attach_unlock()
cgroup_threadgroup_change_end()
|
v
task can now enter exit_signals()
|
v
finish_task_switch()
|
v
sched_ext_dead() -> SCX_TASK_DEAD
作者宣称的窗口 vs 真实锁顺序对比:
Author-claimed window (does NOT actually exist):
----------------------------------------------------
migration commit --+
| <-- supposed gap where task exits
MIGRATED callback --+
Reality (lock ordering):
----------------------------------------------------
attach_lock(write) +==============================+
| MIGRATED callbacks |
+==============================+
^
| tasks in set cannot
| enter exit_signals()
v
attach_lock release
----------------------------------------------------
then exit_signals() possible
Highlight:风险与注意点
- 盲目模仿其他调用点的检查模式:作者以「其他
scx_rehome_task()调用点都检查DEAD,这里也加上」为由添加检查,但其他调用点(典型是scx_task_iter_*遍历)运行在完全不同的锁上下文里,迁移回调处于attach_lockwrite-held 下,DEAD 路径根本进不来。复制模式前要先看上下文是否一致,不能照搬。 - 流程教训:Maintainer 明确点出「code review 发现疑似 bug -> 先尝试 repro -> 再写补丁」。涉及 lock/race 的修复,没有 repro 容易把不存在的窗口当成真问题。
- patch 状态:截至本 thread 最后,作者承认分析错误,这条 patch 应当不会合并;下游 review/bisect 工作应在 lore 上先确认是否被撤回或重新提交。
- 后续观察点:真正值得继续留意的是
scx_task_iter_*类「不走 threadgroup rwsem」的遍历路径是否需要DEAD跳过rehome——那才是补丁作者最初类比的真实语境。 Fixes:tag 准确性:若补丁最终被丢弃,Fixes: bf9dee58ab56这条 tag 也不应传播到 stable 队列。
与其他相关 patch 系列的关联
bf9dee58ab56("sched_ext: Re-home tasks on cgroup migration"):本 patch 的Fixes:指向对象,向 cgroup migration 路径引入了scx_rehome_task()。scx_task_iter_*遍历系列:作者类比中那些已有的DEAD检查所在路径;与本 thread 不同的锁上下文,未在本 thread 中重新讨论。
一句话总结
这是一条原本想堵「cgroup 迁移 MIGRATED 回调里 rehoming 已死亡任务」race 的单文件补丁,被 maintainer 用 cgroup_attach_lock 与 exit_signals() 的锁顺序论证驳回,作者本人在第 3 封回复中认错,patch 大概率不会合并。