Document fsession PID and shutdown semantics

This commit is contained in:
LinuxDev9002
2026-07-18 14:14:31 -07:00
parent 48a4e3fb70
commit 7e984142d5
2 changed files with 16 additions and 10 deletions

View File

@@ -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.

View File

@@ -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 在有界追踪窗口外可能被复用。