feat(starry-perf): implement read for perf event fd#1400
Conversation
Replace raw config values 0/1 in kprobe/uprobe dispatch with named constants PROBE_CONFIG_ENTRY / PROBE_CONFIG_RETURN, matching the Linux PERF_TYPE_PROBE ABI. Also refactor the kprobe config match from a nested if/else chain into flat const-pattern match arms.
为 BpfPerfEventWrapper 实现 try_read_record 方法,使 perf event fd 支持 read(2) 系统调用读取 ringbuf 中的 eBPF 输出记录。 主要变更: - bpf.rs: 添加 mmap_kvirt 字段保存 ringbuf 内核虚拟地址,实现 try_read_record 从 perf_event_mmap_page 读取 data_head/data_tail, 处理环缓冲区 wrapping,读取 perf_event_header 确定记录尺寸, 推进 data_tail;添加 wrapping_add/copy_ring 辅助函数 - mod.rs: 实现 FileLike::read,通过 downcast 获取 BpfPerfEventWrapper 并调用 try_read_record,使用 PAGE_SIZE_4K 作为栈缓冲区尺寸常量
|
Merged into #1414 — consolidated perf event fd read/poll/nonblock support. |
There was a problem hiding this comment.
PR #1400 Review: feat(starry-perf): implement read for perf event fd
总体评价
实现质量较好,代码结构清晰,SAFETY 注释充分。try_read_record 正确实现了 Linux perf ringbuf 语义,包括环形缓冲区 wrapping 处理和 data_tail 推进。
CI 状态
CI workflow run #7544 总体结论为 success。所有子 job 均为 skipped(fork PR + path filter,perf/ 下的改动不触发测试/axvisor/starry 等 job),符合预期。
代码分析
bpf.rs ✅
mmap_kvirt字段在device_mmap时正确保存,try_read_record中通过is_mapped()校验页面生命周期wrapping_add/copy_ring辅助函数正确处理环形缓冲区零次/一次 wrappingrecord_size校验覆盖了< hdr_size和> dst.len()两种非法情况data_tail单调递增符合 Linux perf 环形缓冲区语义
kprobe.rs / uprobe.rs ✅
PROBE_CONFIG_ENTRY/PROBE_CONFIG_RETURN常量替代魔数 0/1,提高可读性- pattern match 语法更简洁
mod.rs ✅
FileLike::read正确加锁、downcast 到BpfPerfEventWrapper,非 BPF perf event 返回Unsupported- 栈缓冲区
PERF_READ_BUF_SIZE = PAGE_SIZE_4K合理
重复/重叠分析
- base 分支上
PerfEvent::read仍为Err(AxError::Unsupported),本 PR 新增功能无重复 - PR #1412(同作者)包含
PROBE_CONFIG_ENTRY/PROBE_CONFIG_RETURN相同常量,属于 partial-overlap。#1412 body 已明确标注与 #1400 的关系,合并时需要处理冲突(trivial)。
小建议
见 inline comment 关于 perf_event_header 对齐和测试覆盖的建议。
结论
代码正确、CI 通过、无阻塞问题。APPROVE。
Powered by mimo-v2.5-pro
| let hdr_size = core::mem::size_of::<perf_event_header>(); | ||
| if hdr_size > dst.len() { | ||
| return Err(AxError::InvalidInput); | ||
| } |
There was a problem hiding this comment.
[nit] dst.as_ptr() as *const perf_event_header 假设了 4 字节对齐,但 dst 是 &mut [u8] 仅保证 1 字节对齐。虽然栈上 4096 字节数组在实践中通常满足对齐要求,但严格来说这是 UB。
建议使用 core::ptr::read_unaligned 或确保缓冲区对齐:
let header: perf_event_header = core::ptr::read_unaligned(dst.as_ptr() as *const perf_event_header);
let record_size = header.size as usize;| } | ||
| } | ||
|
|
||
| /// Stack buffer size for reading a single perf ringbuf record. The |
There was a problem hiding this comment.
[note] 当前没有针对 perf event fd read(2) 的测试用例。现有的 eBPF apps(apps/starry/ebpf/)均未使用 bpf_perf_event_output,因此没有现成的测试基础设施。
建议后续添加一个使用 bpf_perf_event_output 的 eBPF 测试程序,在 test-suit 中验证 read 路径的端到端闭环。这不阻塞当前 PR,但应作为 follow-up 跟踪。
问题
perf event fd 不支持 read(2) 系统调用。当 eBPF program 通过 bpf_perf_event_output 写入 ringbuf 后,用户态无法读取输出记录,数据消费闭环不完整。
变更
bpf.rs: BpfPerfEventWrapper 新增mmap_kvirt字段(在device_mmap时保存 ringbuf 内核虚拟地址),实现try_read_record:wrapping_add/copy_ring处理环形缓冲区操作mod.rs: 实现FileLike::read,通过 downcast 获取 BpfPerfEventWrapper 后调用try_read_record逻辑