[PATCH v4 1/2] perf stat: Propagate supported flag to follower cgroup BPF events

From: Ian Rogers

Date: Tue May 19 2026 - 12:00:40 EST


When using BPF counters with cgroups, follower events (for cgroups
other than the first one) are not opened. Because they are not opened,
their `supported` flag was left as `false`.

During metric calculation, `prepare_metric` checks if the event is
supported. If it is not supported (like the follower events), it
explicitly sets the value to `NAN`, which eventually causes the metric
to be reported as `nan %`.

Fix this by propagating the `supported` flag from the "leader" events
(the ones opened for the first cgroup) to the "follower" events.

Also add a validation check to `bperf_load_program` to ensure `nr_cgroups`
is not zero and the number of events is a multiple of `nr_cgroups`,
preventing a potential division-by-zero (SIGFPE) exception when
`num_events` evaluates to 0 (e.g., with a trailing comma in cgroups list).

Reported-by: Svilen Kanev <skanev@xxxxxxxxxx>
Acked-by: Namhyung Kim <namhyung@xxxxxxxxxx>
Assisted-by: Antigravity:gemini-3-flash
Signed-off-by: Ian Rogers <irogers@xxxxxxxxxx>
---
tools/perf/util/bpf_counter_cgroup.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)

diff --git a/tools/perf/util/bpf_counter_cgroup.c b/tools/perf/util/bpf_counter_cgroup.c
index 519fee3dc3d0..e1ce5aa3b957 100644
--- a/tools/perf/util/bpf_counter_cgroup.c
+++ b/tools/perf/util/bpf_counter_cgroup.c
@@ -104,6 +104,11 @@ static int bperf_load_program(struct evlist *evlist)

set_max_rlimit();

+ if (nr_cgroups == 0 || evlist->core.nr_entries % nr_cgroups != 0) {
+ pr_err("Invalid cgroup or event count\n");
+ return -EINVAL;
+ }
+
test_max_events_program_load();

skel = bperf_cgroup_bpf__open();
@@ -186,6 +191,21 @@ static int bperf_load_program(struct evlist *evlist)
i++;
}

+ /*
+ * Propagate supported flag from leaders to followers. Follower events
+ * are not opened, so their supported flag remains false.
+ */
+ {
+ struct evsel *leader;
+ int num_events = evlist->core.nr_entries / nr_cgroups;
+
+ evlist__for_each_entry(evlist, evsel) {
+ leader = evlist__find_evsel(evlist, evsel->core.idx % num_events);
+ if (leader)
+ evsel->supported = leader->supported;
+ }
+ }
+
/*
* bperf uses BPF_PROG_TEST_RUN to get accurate reading. Check
* whether the kernel support it
--
2.54.0.631.ge1b05301d1-goog