sched-ext discussion
[PATCH v3 0/4] selftests: shared lib.bpf.mk for building BPF progs and skeletons
LLM 分析
selftests/lib.bpf.mk:把 BPF selftest 工具链统一到一处
系列概况
| 字段 | 内容 |
|---|---|
| 标题 | [PATCH v3 0/4] selftests: shared lib.bpf.mk for building BPF progs and skeletons |
| 作者 | Ziyang Men <ziyang.meme@gmail.com> (Meta Platforms) |
| 版本 | v3,2026-08-14 首发;与 v2/v1 的差异在封面信里逐条列出 |
| 规模 | 4 个 patch,13 个文件,+1204/−302 行 |
| 修改文件 | tools/testing/selftests/lib.bpf.mk(新增 296 行);selftests/cgroup/{Makefile,.gitignore,config,lib/cgroup_util.{c,h},test_memcontrol.c};selftests/cgroup/{memcg_stat_cross_cpu.bpf.c,*.h,test_memcg_stat_cross_cpu.c}(新增);selftests/hid/{Makefile,.gitignore};selftests/sched_ext/Makefile |
| 代码统计 | patch 1 新增 296 行;patch 2 新增 cgroup 正确性测试 + 三个 cgroup_util helper;patch 3 hid/Makefile 180 行→~30 行;patch 4 sched_ext/Makefile 146 行→~30 行 |
| Message-ID | 20260814075054.507089-1 ~ -5(封面+4 patch);外加 sashiko-bot、bpf-ci、Andrew Morton 共 7 封回复 |
| 完整性 | 完整:封面信 + 4 个 patch + 7 封自动/人工回复 |
补丁目的
selftests/{bpf,sched_ext,hid}/ 各自维护一份近乎相同的 BPF 工具链(libbpf 子构建、bpftool 子构建、vmlinux.h 生成、skeleton/subskeleton 生成),合计约 450 行重复 Makefile。本系列:
- 把工具链抽到公共片段
tools/testing/selftests/lib.bpf.mk。 - 让 hid、sched_ext 改用
include复用,自身 Makefile 缩到 ~30 行。 - 顺手新增 cgroup 的 memcg flush 真正正确性测试——对比 BPF kfunc 读数与
memory.stat文件读数,弥补旧bpf/cgroup_iter_memcg只校验"非零"的弱点。
旧流程的问题
- 三套 Makefile 各自计算 vmlinux/BTF 路径、Clang 系统 include、bpftool 输出位置,长期漂移。
- 缺 vmlinux 时在 parse 阶段
$(error …)直接挡死make clean。 - sched_ext 用 3 次
bpftool gen object链式生成linked1/2/3.o再 diff,hid 只生成 1 次,风格分裂。 - 手工维护的
vpath是全局规则,会污染 caller 自己的%.c规则。 - HOSTCC/HOSTLD 过去通过
Makefile.include,副作用是连带改 caller 的 AR/LD/CXX。
新流程
lib.bpf.mk把 libbpf、bpftool、vmlinux.h、BPF 对象、skeleton/subskeleton 集中在一处,caller 只需声明少量变量:BPF_SRCS、BPF_PROG_EXT、BPF_EXTRA_HDRS、BPF_EXTRA_CFLAGS、BPF_SKEL_EXT、BPF_GEN_SUBSKEL、BPF_OBJ_DIR、BPF_SKEL_DIR。- hid:设
BPF_PROG_EXT := .c兼容老的progs/*.c布局。 - sched_ext:用现代
*.bpf.c+BPF_SKEL_EXT := .bpf.skel.h+BPF_GEN_SUBSKEL := 1,并保留旧$(OUTPUT)/build/...路径。 - cgroup:作为新消费者加入。
- 缺 vmlinux 延迟到真正构建
vmlinux.h的 recipe 里报错,make clean不再被挡。 - HOSTCC/HOSTLD 直接从
lib.mk来,避免 includeMakefile.include带来的 AR/LD 副作用。
Patch 概览
| # | 标题 | 关键改动 |
|---|---|---|
| 1 | add shared lib.bpf.mk | 新建 selftests/lib.bpf.mk,296 行 |
| 2 | cgroup: memcg_stat_cross_cpu flush 正确性测试 | BPF kfunc flush + 文件读数比对 |
| 3 | hid: 用 lib.bpf.mk | hid/Makefile 180 → ~30 行 |
| 4 | sched_ext: 用 lib.bpf.mk | sched_ext/Makefile 146 → ~30 行;28 skel + 28 subskel |
关键实现
核心分层变量 + per-source rule:
BUILD_DIR := $(OUTPUT)/tools/build
BPFOBJ := $(BUILD_DIR)/libbpf/libbpf.a
HOST_BPFOBJ := (cross ? HOST_BUILD_DIR : BUILD_DIR)/libbpf/libbpf.a
DEFAULT_BPFTOOL := $(HOST_SCRATCH_DIR)/sbin/bpftool
caller 接入示例:
BPF_SRCS := memcg_stat_cross_cpu.bpf.c
OVERRIDE_TARGETS := 1
include ../lib.mk
include ../lib.bpf.mk
$(OUTPUT)/test_memcg_stat_cross_cpu: test_memcg_stat_cross_cpu.c $(BPF_SKELS) $(LIBCGROUP_O) $(BPFOBJ)
$(call bpf_link,$@,$< $(LIBCGROUP_O))
每个 BPF 源一条独立 bpf_obj_rule,避免 vpath 串扰;get_sys_includes 用 clang -v -E 抓系统头加 -idirafter 后置以免覆盖项目头;CLANG_BPF_CPU 自动探测 v3 支持,不支持则退到 v2;cross-compile 时 USERCFLAGS 只传给 target libbpf;缺 vmlinux 延迟到 vmlinux.h recipe 报错。BPF_CFLAGS 含 -fms-extensions 以接受 vmlinux.h 中的匿名 struct/union,-MMD -MP 记录所有包含头。
cgroup 测试核心:
SEC("iter.s/cgroup")
int cgroup_memcg_stat_cross_cpu(struct bpf_iter__cgroup *ctx)
{
struct cgroup *cgrp = ctx->cgroup;
/* iter.s 因为 flush kfunc 可能睡眠 */
bpf_mem_cgroup_flush_stats(memcg);
/* 读 anon/file/shmem/pgfault,写到 HASH map by cg_id */
}
新 cgroup_util 加 cg_get_id(name_to_handle_at 取 cgroupfs handle 即内核 cgrp->kn->id,注意不是 st_ino)、cg_touch_pages(写一遍触发 resident fault)、cg_alloc_anon(malloc + fault-in)。测试只建一棵 cgroup 树、一次 flush、然后 BPF 读与 memory.stat 文件读对比。
构建关系图:
caller Makefile (hid/sched_ext/cgroup)
|
+-- include ../lib.mk (OUTPUT, top_srcdir, CC, Q, msg)
|
+-- include ../lib.bpf.mk (BPFOBJ, BPFTOOL, BPF_OBJS, BPF_SKELS, BPF_LDLIBS)
|
+-- libbpf sub-make -> $(OUTPUT)/tools/build/libbpf/libbpf.a
+-- bpftool sub-make -> $(OUTPUT)/host-tools/sbin/bpftool
+-- BPF object rule -> $(OUTPUT)/foo.bpf.o
+-- skeleton rule -> $(OUTPUT)/foo.skel.h (+ foo.subskel.h)
+-- vmlinux.h rule -> $(OUTPUT)/tools/include/vmlinux.h
类比
旧流程像三家餐馆各买一套相同的锅、刀、砧板,任意一家换品牌另两家就跟不上,菜刀型号不齐切出来的菜大小不一。新流程是开一个中央厨房货架(lib.bpf.mk),餐馆只声明要做什么菜(BPF_SRCS),货架自动按规格送工具。cgroup 是新分店,直接领到刀;cgroup 那边的新 BPF 测试像给中央厨房配了支温度计,不再只看"开没开火"(数字非零),而是核对"实际做熟了几道"(BPF 读数与文件读数完全相等)。
Highlight:风险与注意点
- 增量依赖:sashiko-bot 提示
BPFOBJ变更时BPF_OBJS未必触发重链接;当前依赖bpf_obj_rule把$(BPFOBJ)列作 order-only 前置,改 libbpf 源码需手动make clean。 - flags 漂移:bpf-ci 指出 hid patch 的 changelog 应说明 BPF 编译 flags 实际变了(多了
-Wall/-std=gnu11/-fno-strict-aliasing、新增若干 include 路径、-mcpu由硬编码 v3 改为自动探测),而不是描述成"行为一致"。 - 架构 include 探测:
get_sys_includes缺 LoongArch 和 MIPS 的__riscv_xlen-style 探测,sashiko-bot 标记 Low。 - HAVE_BPF 隔离:cgroup 端用
ifneq ($(HAVE_BPF),)包住 BPF 路径,无 clang/BTF 时同目录其它 cgroup 测试照常编译,设计稳健。 - uapi 隔离:
private CFLAGS += -I$(top_srcdir)/tools/include/uapi仅加到test_memcg_stat_cross_cpu,避免污染同目录其它测试对<linux/*.h>的解析。 - review 状态:v3 撞上 merge window,bpfbot 和 sashiko 都提了不少问题;Andrew Morton 在 8-31 已回信"预期多数评审者会等下一版(v4)"。
版本变化
| 版本 | 关键变化 |
|---|---|
| v1 → v2 | 通用化 lib.bpf.mk(源后缀、extra hdrs/cflags、skel 后缀、subskel、可配置输出目录),能服务 hid/sched_ext 而非仅 cgroup;新增 patch 3(hid)、patch 4(sched_ext)。 |
| v2 → v3 | 共享 Makefile:USERCFLAGS/USERLDFLAGS 扩 CFLAGS/LDFLAGS;OPT_FLAGS/RELEASE/EXTRA_CFLAGS 透传到 libbpf/bpftool 子 make;每个 BPF 源一条独立 rule 弃用 vpath;HOSTCC/HOSTLD 改从 lib.mk 来;缺 vmlinux 延迟到 recipe 报错保证 make clean 可用。cgroup selftest:只建一棵 cgroup 树、只 flush 一次;用 cg_read_key_long/value_close 等公共 helper;cpu_set_t 替手写 cpu 列表;anon allocator 从 test_memcontrol.c 移到 cgroup_util;修复 bot 评审。 |
一句话总结
把 selftests 中分散在 bpf/sched_ext/hid 的 ~450 行 BPF 工具链 Makefile 抽成共享片段 tools/testing/selftests/lib.bpf.mk,让 hid/sched_ext 各缩到 ~30 行,并新增 cgroup 端真正的 memcg_stat_cross_cpu flush 跨 CPU 正确性测试;v3 因撞 merge window + bot 反馈,正在等 v4。