From: Mykyta Yatsenko yatsenko@meta.com
[ Upstream commit 105eb5dc74109a9f53c2f26c9a918d9347a73595 ]
bpf_cookie can fail on perf_event_open(), when it runs after the task_work selftest. The task_work test causes perf to lower sysctl_perf_event_sample_rate, and bpf_cookie uses sample_freq, which is validated against that sysctl. As a result, perf_event_open() rejects the attr if the (now tighter) limit is exceeded.
From perf_event_open():
if (attr.freq) { if (attr.sample_freq > sysctl_perf_event_sample_rate) return -EINVAL; } else { if (attr.sample_period & (1ULL << 63)) return -EINVAL; }
Switch bpf_cookie to use sample_period, which is not checked against sysctl_perf_event_sample_rate.
Signed-off-by: Mykyta Yatsenko yatsenko@meta.com Signed-off-by: Andrii Nakryiko andrii@kernel.org Link: https://lore.kernel.org/bpf/20250925215230.265501-1-mykyta.yatsenko5@gmail.c... Signed-off-by: Sasha Levin sashal@kernel.org ---
LLM Generated explanations, may be completely bogus:
YES
- What it fixes and why it matters - The perf-event subtest in bpf_cookie can fail with -EINVAL when run after tests that cause perf to throttle sampling (e.g., task_work stress), because the test uses frequency mode and sets `attr.sample_freq` above the current global limit. The kernel validates frequency mode against `sysctl_perf_event_sample_rate` and rejects it when exceeded (kernel/events/core.c:13403). In contrast, period mode only rejects if the high bit is set (kernel/events/core.c:13406), so it avoids this global-throttling pitfall. - Perf can dynamically lower `sysctl_perf_event_sample_rate` under high overhead (see assignment in kernel/events/core.c:654), so this flakiness can affect real test runs on slower systems or after heavy tests.
- Specific code change - In `tools/testing/selftests/bpf/prog_tests/bpf_cookie.c:453-454`, the test currently sets: - `attr.freq = 1;` - `attr.sample_freq = 10000;` - The commit switches to period mode by replacing those with: - `attr.sample_period = 100000;` - This removes reliance on `sysctl_perf_event_sample_rate` entirely for this test, eliminating the spurious -EINVAL from `perf_event_open()` and making the selftest deterministic.
- Scope, risk, and stable criteria - Selftests-only change; no kernel runtime code touched. - Minimal and contained (1 insertion, 2 deletions in a single file). - No API or architectural changes; uses long-supported perf_event_attr fields. - Purpose is purely to fix test flakiness, not to add features. - Low regression risk: switching from frequency to period mode is semantically equivalent for this test’s goal (ensuring perf samples fire to trigger the attached BPF program during `burn_cpu()`), while avoiding global sysctl dependency. - The issue exists in this stable tree: the local file still uses `attr.freq`/`attr.sample_freq` at `tools/testing/selftests/bpf/prog_tests/bpf_cookie.c:453-454`.
- Additional context - The upstream kernel already contains this exact fix (commit 105eb5dc74109 “selftests/bpf: Fix flaky bpf_cookie selftest”). - Earlier attempts at hardening tests by lowering frequency (e.g., to 1000) still risk hitting the dynamic throttle; period mode is the robust approach.
Given this is a small, targeted selftest flakiness fix with negligible risk and clear benefit to stable testing reliability, it is suitable for backporting.
tools/testing/selftests/bpf/prog_tests/bpf_cookie.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_cookie.c b/tools/testing/selftests/bpf/prog_tests/bpf_cookie.c index 4a0670c056bad..75f4dff7d0422 100644 --- a/tools/testing/selftests/bpf/prog_tests/bpf_cookie.c +++ b/tools/testing/selftests/bpf/prog_tests/bpf_cookie.c @@ -450,8 +450,7 @@ static void pe_subtest(struct test_bpf_cookie *skel) attr.size = sizeof(attr); attr.type = PERF_TYPE_SOFTWARE; attr.config = PERF_COUNT_SW_CPU_CLOCK; - attr.freq = 1; - attr.sample_freq = 10000; + attr.sample_period = 100000; pfd = syscall(__NR_perf_event_open, &attr, -1, 0, -1, PERF_FLAG_FD_CLOEXEC); if (!ASSERT_GE(pfd, 0, "perf_fd")) goto cleanup;