mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v1 1/4] perf off-cpu: Use the CPU map index for the bpf-output file descriptor
@ 2026-10-27 17:04 Ian Rogers
  2026-10-27 17:04 ` [PATCH v1 2/4] perf off-cpu: Write the sample ID for PERF_SAMPLE_ID Ian Rogers
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Ian Rogers @ 2026-10-27 17:04 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Jiri Olsa, Ian Rogers, Adrian Hunter, James Clark,
	Ankur Arora, Howard Chu, Thomas Falcon, linux-perf-users,
	linux-kernel

When populating the offcpu_output BPF perf event array, the file
descriptor of the bpf-output event was looked up using the CPU number
rather than the index within the evsel's CPU map. These differ when
CPUs are offline or a subset of CPUs is used, leading to the wrong, or
an out-of-bounds, file descriptor being used. Index the file
descriptor array using the CPU map index.

Fixes: 282c195906c7 ("perf record --off-cpu: Preparation of off-cpu BPF program")
Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/util/bpf_off_cpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/util/bpf_off_cpu.c b/tools/perf/util/bpf_off_cpu.c
index c4639f6a5776..ff8935688b43 100644
--- a/tools/perf/util/bpf_off_cpu.c
+++ b/tools/perf/util/bpf_off_cpu.c
@@ -95,7 +95,7 @@ static void off_cpu_start(void *arg)
 		int cpu_nr = pcpu.cpu;
 
 		err = bpf_map__update_elem(skel->maps.offcpu_output, &cpu_nr, sizeof(int),
-					   xyarray__entry(evsel->core.fd, cpu_nr, 0),
+					   xyarray__entry(evsel->core.fd, i, 0),
 					   sizeof(int), BPF_ANY);
 		if (err) {
 			pr_err("Failed to update perf event map for direct off-cpu dumping\n");
-- 
2.56.0.313.g2479322e68-goog


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v1 2/4] perf off-cpu: Write the sample ID for PERF_SAMPLE_ID
  2026-10-27 17:04 [PATCH v1 1/4] perf off-cpu: Use the CPU map index for the bpf-output file descriptor Ian Rogers
@ 2026-10-27 17:04 ` Ian Rogers
  2026-10-27 17:04 ` [PATCH v1 3/4] perf off-cpu: Fix cgroup_filter map sizing Ian Rogers
  2026-10-27 17:04 ` [PATCH v1 4/4] libperf evlist: Recompute CPU map when an evsel goes system wide Ian Rogers
  2 siblings, 0 replies; 4+ messages in thread
From: Ian Rogers @ 2026-10-27 17:04 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Jiri Olsa, Ian Rogers, Adrian Hunter, James Clark,
	Ankur Arora, Howard Chu, Thomas Falcon, linux-perf-users,
	linux-kernel

OFFCPU_SAMPLE_TYPES allows PERF_SAMPLE_ID, and the sample ID is
computed, but off_cpu_write() only wrote it for PERF_SAMPLE_IDENTIFIER.
When PERF_SAMPLE_ID was set the synthesized samples were one u64 short,
so the remaining fields were misparsed. Write the ID after the time as
the sample format requires.

Fixes: edc41a1099c2 ("perf record: Enable off-cpu analysis with BPF")
Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/util/bpf_off_cpu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/perf/util/bpf_off_cpu.c b/tools/perf/util/bpf_off_cpu.c
index ff8935688b43..16948761cc45 100644
--- a/tools/perf/util/bpf_off_cpu.c
+++ b/tools/perf/util/bpf_off_cpu.c
@@ -373,6 +373,8 @@ int off_cpu_write(struct perf_session *session)
 			data.array[n++] = 0;
 		if (sample_type & PERF_SAMPLE_TIME)
 			data.array[n++] = tstamp;
+		if (sample_type & PERF_SAMPLE_ID)
+			data.array[n++] = sid;
 		if (sample_type & PERF_SAMPLE_CPU)
 			data.array[n++] = 0;
 		if (sample_type & PERF_SAMPLE_PERIOD)
-- 
2.56.0.313.g2479322e68-goog


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v1 3/4] perf off-cpu: Fix cgroup_filter map sizing
  2026-10-27 17:04 [PATCH v1 1/4] perf off-cpu: Use the CPU map index for the bpf-output file descriptor Ian Rogers
  2026-10-27 17:04 ` [PATCH v1 2/4] perf off-cpu: Write the sample ID for PERF_SAMPLE_ID Ian Rogers
@ 2026-10-27 17:04 ` Ian Rogers
  2026-10-27 17:04 ` [PATCH v1 4/4] libperf evlist: Recompute CPU map when an evsel goes system wide Ian Rogers
  2 siblings, 0 replies; 4+ messages in thread
From: Ian Rogers @ 2026-10-27 17:04 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Jiri Olsa, Ian Rogers, Adrian Hunter, James Clark,
	Ankur Arora, Howard Chu, Thomas Falcon, linux-perf-users,
	linux-kernel

off_cpu_prepare() assumed that if evlist__first(evlist)->cgrp is set,
the number of cgroups is evlist__nr_entries(evlist) - 1 (excluding the
dummy bpf-output event). This can under-size cgroup_filter when
non-cgroup events precede cgroup events or when no dummy bpf-output
event is added.

Count the number of evsels in evlist that have a cgroup set and use that
count to size and populate cgroup_filter.

Fixes: 685439a7a037 ("perf record: Add cgroup support for off-cpu profiling")
Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/util/bpf_off_cpu.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/tools/perf/util/bpf_off_cpu.c b/tools/perf/util/bpf_off_cpu.c
index 16948761cc45..71933a71c8d1 100644
--- a/tools/perf/util/bpf_off_cpu.c
+++ b/tools/perf/util/bpf_off_cpu.c
@@ -151,9 +151,10 @@ int off_cpu_prepare(struct evlist *evlist, struct target *target,
 		    struct record_opts *opts)
 {
 	int err, fd, i;
-	int ncpus = 1, ntasks = 1, ncgrps = 1;
+	int ncpus = 1, ntasks = 1, ncgrps = 0;
 	struct strlist *pid_slist = NULL;
 	struct str_node *pos;
+	struct evsel *evsel;
 
 	if (off_cpu_config(evlist) < 0) {
 		pr_err("Failed to config off-cpu BPF event\n");
@@ -208,8 +209,12 @@ int off_cpu_prepare(struct evlist *evlist, struct target *target,
 		skel->rodata->uses_tgid = 1;
 	}
 
-	if (evlist__first(evlist)->cgrp) {
-		ncgrps = evlist__nr_entries(evlist) - 1; /* excluding a dummy */
+	evlist__for_each_entry(evlist, evsel) {
+		if (evsel->cgrp)
+			ncgrps++;
+	}
+
+	if (ncgrps > 0) {
 		bpf_map__set_max_entries(skel->maps.cgroup_filter, ncgrps);
 
 		if (!cgroup_is_v2("perf_event"))
@@ -274,8 +279,7 @@ int off_cpu_prepare(struct evlist *evlist, struct target *target,
 		}
 	}
 
-	if (evlist__first(evlist)->cgrp) {
-		struct evsel *evsel;
+	if (ncgrps > 0) {
 		u8 val = 1;
 
 		fd = bpf_map__fd(skel->maps.cgroup_filter);
-- 
2.56.0.313.g2479322e68-goog


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v1 4/4] libperf evlist: Recompute CPU map when an evsel goes system wide
  2026-10-27 17:04 [PATCH v1 1/4] perf off-cpu: Use the CPU map index for the bpf-output file descriptor Ian Rogers
  2026-10-27 17:04 ` [PATCH v1 2/4] perf off-cpu: Write the sample ID for PERF_SAMPLE_ID Ian Rogers
  2026-10-27 17:04 ` [PATCH v1 3/4] perf off-cpu: Fix cgroup_filter map sizing Ian Rogers
@ 2026-10-27 17:04 ` Ian Rogers
  2 siblings, 0 replies; 4+ messages in thread
From: Ian Rogers @ 2026-10-27 17:04 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Jiri Olsa, Ian Rogers, Adrian Hunter, James Clark,
	Ankur Arora, Howard Chu, Thomas Falcon, linux-perf-users,
	linux-kernel

perf_evlist__go_system_wide() marks the evsel as system wide and then
propagates the evlist's maps to it. __perf_evlist__propagate_maps()
only assigns the PMU CPUs to evsel->cpus if the map is empty, but an
evsel added after the evlist's maps were created already has the user
requested CPUs propagated (e.g. the "any CPU" map of -1 in per-thread
or workload mode). Going system wide then leaves the evsel opened on
the wrong CPUs.

Drop the existing CPU map before propagating so the evsel is given all
of its PMU's CPUs, as is expected for a system wide event.

Fixes: 811082e4b668 ("perf parse-events: Support user CPUs mixed with threads/processes")
Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/lib/perf/evlist.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/tools/lib/perf/evlist.c b/tools/lib/perf/evlist.c
index c1c5b0684eed..46de69aa5a86 100644
--- a/tools/lib/perf/evlist.c
+++ b/tools/lib/perf/evlist.c
@@ -835,7 +835,10 @@ void perf_evlist__go_system_wide(struct perf_evlist *evlist, struct perf_evsel *
 {
 	if (!evsel->system_wide) {
 		evsel->system_wide = true;
-		if (evlist->needs_map_propagation)
+		if (evlist->needs_map_propagation) {
+			perf_cpu_map__put(evsel->cpus);
+			evsel->cpus = NULL;
 			__perf_evlist__propagate_maps(evlist, evsel);
+		}
 	}
 }
-- 
2.56.0.313.g2479322e68-goog


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-10-27 17:04 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-27 17:04 [PATCH v1 1/4] perf off-cpu: Use the CPU map index for the bpf-output file descriptor Ian Rogers
2026-10-27 17:04 ` [PATCH v1 2/4] perf off-cpu: Write the sample ID for PERF_SAMPLE_ID Ian Rogers
2026-10-27 17:04 ` [PATCH v1 3/4] perf off-cpu: Fix cgroup_filter map sizing Ian Rogers
2026-10-27 17:04 ` [PATCH v1 4/4] libperf evlist: Recompute CPU map when an evsel goes system wide Ian Rogers

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®