sched-ext discussion
[PATCH sched_ext/for-7.2-fixes] sched_ext: Fix scx_bpf_dsq_reenq___compat kfunc extern prototype
LLM 分析
sched_ext:修复 scx_bpf_dsq_reenq___compat kfunc extern 声明
系列概况
- Title: [PATCH sched_ext/for-7.2-fixes] sched_ext: Fix scx_bpf_dsq_reenq___compat kfunc extern prototype
- Author: Tejun Heo tj@kernel.org
- Version: 单封 patch(无 v 编号)
- Scale: 1 个文件,3 +/−
- 修改文件: tools/sched_ext/include/scx/compat.bpf.h
- 代码统计: 1 file changed, 3 insertions(+), 3 deletions(-)
- Message-ID: 20260814205955.3490381-1-tj@kernel.org
- 完整性: 含 patch 正文 + maintainer 应用回执,完整
补丁目的
修正 compat.bpf.h 中 scx_bpf_dsq_reenq___compat weak extern 的参数签名,让它与 KF_IMPLICIT_ARGS 注册的内核 BTF 原型一致;libbpf 才能在真正支持该 kfunc 的内核上成功 resolve,通用 reenq 路径不再被静默关掉。
旧流程的问题
旧 extern 显式多写一个 const struct bpf_prog_aux *aux__prog 参数;而 scx_bpf_dsq_reenq() 在内核用 KF_IMPLICIT_ARGS 注册,BTF 原型把 aux 隐式省略。libbpf 一比对就对不上。
后果:
- weak extern 在所有内核上都 unresolved,
bpf_ksym_exists(...)永远 false; __COMPAT_has_generic_reenq()始终返 false,包装函数恒走scx_bpf_reenqueue_local()老分支;scx_qmap的 lowpri 等通用 reenq 用户被禁用;- 跨本地 DSQ 的 reenq 反而以 "kernel too old" 失败,即便内核已经支持;
- 用户完全无感——没有编译告警,也没有运行时报错,特性"静默死亡"。
新流程
去掉 extern 与调用点的 aux 参数,使声明与 BTF 原型一致;libbpf 在支持该 kfunc 的内核上能正确 resolve,__COMPAT_has_generic_reenq() 恢复返回 true,调用者重新走真正的 reenq 路径。同时把注释里过时的 "v6.20" 订正为 "v7.1",并加 Fixes: 与 Cc: stable 标签。
Patch 概览
tools/sched_ext/include/scx/compat.bpf.h- 注释:
v6.20->v7.1。 - extern:去掉
aux__prog参数。 - 包装函数调用点:去掉第三参数
NULL。
- 注释:
关键实现
/* 旧 extern */
void scx_bpf_dsq_reenq___compat(
u64 dsq_id, u64 reenq_flags,
const struct bpf_prog_aux *aux__prog) __ksym __weak;
/* 新 extern */
void scx_bpf_dsq_reenq___compat(
u64 dsq_id, u64 reenq_flags) __ksym __weak;
/* 旧调用点 */
scx_bpf_dsq_reenq___compat(dsq_id, reenq_flags, NULL);
/* 新调用点 */
scx_bpf_dsq_reenq___compat(dsq_id, reenq_flags);
类比
KF_IMPLICIT_ARGS 像酒店 VIP "自动签房卡" 通道:客人签合同时合同里看不到那张附加卡,前台会自己塞一张进去。旧 extern 偏要合同上写"我拿两张卡",前台一对不上号就把客人拒之门外。修好之后合同只写一张卡,前台实际发的也是一张,匹配成功,VIP 通道重新打开。
compat extern (OLD) BTF (KF_IMPLICIT_ARGS)
===================== ========================
u64 dsq_id u64 dsq_id
u64 reenq_flags u64 reenq_flags
bpf_prog_aux *aux__prog (aux dropped)
| |
+----- libbpf resolve ----> signature mismatch
|
v
weak extern never resolves
|
v
__COMPAT_has_generic_reenq() = false
|
v
fallback to reenq_local, non-local = "kernel too old"
AFTER FIX:
|
v
extern matches BTF -> libbpf resolves
|
v
__COMPAT_has_generic_reenq() = true on supported kernels
|
v
calls scx_bpf_dsq_reenq() directly, no fallback
Highlight:风险与注意点
- 凡用
KF_IMPLICIT_ARGS注册的 kfunc,compat 层 weak extern 都必须省略被隐式吃掉的辅助参数;否则 libbpf resolve 永远失败,特性"静默死亡"——这是这类问题最容易踩的坑。 compat.bpf.h是 user-space skeleton 与内核 BTF 的隐式契约,BTF 一旦变动都要回头检查 extern 是否仍对齐;这类签名错位不会编译报错,也不会写 dmesg。- patch 本意发往
for-7.2-fixes,但因为 7.2 已经定型被挪到sched_ext/for-7.3;需要单独走stable@vger.kernel.org # v7.1+后向移植通道。 - 注释里把该 kfunc 误写成 v6.20(实际 v7.1 引入),文档或 CHANGELOG 还可能存在同源描述,应一并订正以免误导。
compat.bpf.h同时包含了__COMPAT_has_generic_reenq与scx_bpf_dsq_reenq两个包装器,它们的判断逻辑都依赖bpf_ksym_exists(...);只要 weak extern resolve 不对,整条 generic reenq 兼容层就被锁死。
版本变化
仅一版 patch,无 vN -> vN+1 演进;关键差异在落点分支从 sched_ext/for-7.2-fixes 改为 sched_ext/for-7.3,意味着它会随 7.3 发布并 stable 后向移植到 7.1+。
一句话总结
让 compat 层声明与 KF_IMPLICIT_ARGS 注册的 BTF 原型对齐,修复 scx_bpf_dsq_reenq 在所有内核上被静默判定为"不存在"的 bug,恢复 scx_qmap 等使用者的跨 DSQ reenq 路径。