From 7e984142d5d344d6826b11acb87408d52781cec0 Mon Sep 17 00:00:00 2001 From: LinuxDev9002 Date: Sat, 18 Jul 2026 14:14:31 -0700 Subject: [PATCH] Document fsession PID and shutdown semantics --- src/52-fsession-latency/README.md | 13 ++++++++----- src/52-fsession-latency/README.zh.md | 13 ++++++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/52-fsession-latency/README.md b/src/52-fsession-latency/README.md index 3c9d1f2..d4dae67 100644 --- a/src/52-fsession-latency/README.md +++ b/src/52-fsession-latency/README.md @@ -23,6 +23,8 @@ SERVICE_PID=$(pgrep -n my-service) sudo ./fsession_latency --pid "$SERVICE_PID" --threshold-us 10000 --duration 30 ``` +`--pid` compares against the TGID returned by `bpf_get_current_pid_tgid()`, which is always the TGID in the host (initial) PID namespace. The `pgrep` example above works for a process running directly on the host. For a process inside a container or nested PID namespace, you must resolve and pass its host-namespace TGID; a namespace-local PID will silently match nothing. + CLI usage: ```text @@ -143,9 +145,10 @@ The user-space program in `fsession_latency.c` performs these steps: 1. Parse CLI arguments (threshold, duration, PID filter). 2. Open the BPF skeleton and set `rodata` constants (`threshold_ns`, `target_tgid`) before loading. 3. Load and attach the fsession program to `vfs_read`. -4. Create a ring buffer and poll it with a 100 ms timeout until the duration expires or a signal arrives. -5. Print each event as it arrives (comm, tgid, pid, requested bytes, result, latency in microseconds). -6. Print a summary line with aggregate counters from BSS. +4. Create a ring buffer and poll it with a 100 ms timeout until the duration expires or a signal arrives. Print each event as it arrives (comm, tgid, pid, requested bytes, result, latency in microseconds). +5. Detach the fsession program so BPF statistics stop changing. +6. Call `ring_buffer__consume()` to drain events already submitted to the ring buffer before detach. +7. Print the summary line with stable aggregate counters from BSS. The summary line exposes ring-buffer drops so the operator knows if events were lost under load. @@ -183,7 +186,7 @@ The test validates: 1. An unmatched PID (2^32 - 1) produces zero calls, proving the TGID filter works. 2. A 10-second threshold (10,000,000 us) produces no slow events even though reads complete, proving the threshold comparison works. 3. A 10 ms threshold with a pipe read delayed by 50 ms produces at least one slow event, proving the end-to-end reporting path works. -4. Threshold 0 with continuous target-TGID reads through the one-second deadline produces calls and events, and the CLI still exits successfully. This protects the normal-success exit path when the final `ring_buffer__poll()` call consumes events. +4. Threshold 0 with continuous target-TGID reads through the one-second deadline produces calls and events, and the CLI still exits successfully. The test also asserts `slow == events + dropped`, so every slow call at the window boundary is either delivered or explicitly counted as a ring-buffer reservation drop. ## Requirements @@ -201,7 +204,7 @@ The test validates: - Measures time inside `vfs_read` only. This is not full request latency, storage-device service time, or application p99. - Covers only paths that invoke `vfs_read`. mmap and other paths that bypass it are invisible. -- Exact TGID filter only. No cgroup, process-tree, path, inode, mount, or container selector. +- Exact TGID filter only. No cgroup, process-tree, path, inode, mount, PID-namespace, or container selector. The filter operates on the host-namespace TGID; there is no way to pass a namespace-local PID or select by container runtime. - One-shot duration. Not a daemon, alerting system, or metrics exporter. - Ring buffer can drop matching events under load. The `dropped` counter exposes that condition; other counters remain aggregate observations. - Command names can repeat and PID reuse is possible outside the bounded tracing window. diff --git a/src/52-fsession-latency/README.zh.md b/src/52-fsession-latency/README.zh.md index 94235d9..4aff606 100644 --- a/src/52-fsession-latency/README.zh.md +++ b/src/52-fsession-latency/README.zh.md @@ -23,6 +23,8 @@ SERVICE_PID=$(pgrep -n my-service) sudo ./fsession_latency --pid "$SERVICE_PID" --threshold-us 10000 --duration 30 ``` +`--pid` 比较的是 `bpf_get_current_pid_tgid()` 返回的 TGID,即宿主机(初始)PID 命名空间中的 TGID。上面的 `pgrep` 示例适用于直接运行在宿主机上的进程。如果目标进程位于容器或嵌套 PID 命名空间内,必须解析并传入其宿主机命名空间的 TGID;传入命名空间内部的 PID 会静默匹配不到任何进程。 + 命令行用法: ```text @@ -143,9 +145,10 @@ struct latency_stats { 1. 解析命令行参数(阈值、持续时间、PID 过滤器)。 2. 打开 BPF skeleton,在加载前设置 `rodata` 常量(`threshold_ns`、`target_tgid`)。 3. 加载并附加 fsession 程序到 `vfs_read`。 -4. 创建 ring buffer,以 100 ms 超时轮询,直到持续时间到期或收到信号。 -5. 每收到一个事件立即打印(comm、tgid、pid、请求字节数、结果、延迟微秒数)。 -6. 打印汇总行,包含从 BSS 读取的聚合计数器。 +4. 创建 ring buffer,以 100 ms 超时轮询,直到持续时间到期或收到信号。每收到一个事件立即打印(comm、tgid、pid、请求字节数、结果、延迟微秒数)。 +5. 解除 fsession 程序的附加,使 BPF 统计计数器不再变化。 +6. 调用 `ring_buffer__consume()` 排空解除附加前已提交到 ring buffer 的事件。 +7. 打印汇总行,此时聚合计数器已稳定。 汇总行中的 `dropped` 字段暴露 ring buffer 丢失事件的情况,让运维人员知道是否有数据丢失。 @@ -183,7 +186,7 @@ sudo make test 1. 不匹配的 PID (2^32 - 1) 产生零次调用,证明 TGID 过滤器有效。 2. 10 秒阈值 (10,000,000 us) 即使有读操作完成也不产生慢事件,证明阈值比较逻辑正确。 3. 10 ms 阈值加上延迟 50 ms 的管道读产生至少一个慢事件,证明端到端上报路径正常工作。 -4. 阈值为 0 时,持续对目标 TGID 执行读操作直到一秒截止时间结束,产生调用和事件,且 CLI 仍然成功退出。该场景保护最后一次 `ring_buffer__poll()` 消费事件后的正常退出路径。 +4. 阈值为 0 时,持续对目标 TGID 执行读操作直到一秒截止时间结束,产生调用和事件,且 CLI 仍然成功退出。该场景还断言 `slow == events + dropped`,确保窗口边界的每一个慢调用要么被投递为事件,要么被明确计入 ring buffer 预留失败。 ## 环境要求 @@ -201,7 +204,7 @@ sudo make test - 仅测量 `vfs_read` 内部的时间,不等于完整请求延迟、存储设备服务时间或应用 p99。 - 仅覆盖调用 `vfs_read` 的路径。mmap 和其他绕过 `vfs_read` 的路径不可见。 -- 仅支持精确 TGID 过滤,不支持 cgroup、进程树、路径、inode、挂载点或容器选择器。 +- 仅支持精确 TGID 过滤,不支持 cgroup、进程树、路径、inode、挂载点、PID 命名空间或容器选择器。过滤器在宿主机命名空间 TGID 上工作,无法传入命名空间内部的 PID 或按容器运行时选择。 - 单次运行,不是守护进程、告警系统或指标导出器。 - Ring buffer 在高负载下可能丢失匹配事件。`dropped` 计数器暴露该情况,其他计数器为聚合观察值。 - 命令名称可能重复,PID 在有界追踪窗口外可能被复用。