All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Zijlstra <peterz@infradead.org>
To: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@redhat.com>,
	Arnaldo Carvalho de Melo <acme@kernel.org>,
	Namhyung Kim <namhyung@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Alexander Shishkin <alexander.shishkin@linux.intel.com>,
	Jiri Olsa <jolsa@kernel.org>,
	Adrian Hunter <adrian.hunter@intel.com>,
	James Clark <james.clark@linaro.org>, Song Liu <song@kernel.org>,
	Alexei Starovoitov <ast@kernel.org>,
	linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org,
	bpf@vger.kernel.org, stable@vger.kernel.org
Subject: Re: [PATCH v1] perf/core: Restore header fields in sideband output callbacks
Date: Tue, 29 Sep 2026 14:04:17 +0200	[thread overview]
Message-ID: <20260929120417.GT4120091@noisy.programming.kicks-ass.net> (raw)
In-Reply-To: <20260929014206.4175245-1-irogers@google.com>

On Mon, Sep 28, 2026 at 06:42:06PM -0700, Ian Rogers wrote:
> perf_iterate_sb() invokes its callback for each matching perf_event on
> the CPU and task context, passing a shared caller-allocated event
> structure.
> 
> perf_event_header__init_id() increments header->size by
> event->id_header_size. Unlike perf_event_task_output(),
> perf_event_comm_output(), perf_event_namespaces_output(),
> perf_event_cgroup_output(), perf_event_mmap_output(), and
> perf_callchain_deferred_output(), three sideband callbacks failed to
> save and restore header.size around perf_event_header__init_id():
> - perf_event_ksymbol_output()
> - perf_event_bpf_output()
> - perf_event_text_poke_output()

I also found perf_event_switch_output(). Does something like so also
work?

---
 kernel/events/core.c | 131 ++++++++++++++++++++++++---------------------------
 1 file changed, 61 insertions(+), 70 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index de05df65ab3d..28770ca689c8 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -9108,12 +9108,22 @@ perf_event_read_event(struct perf_event *event,
 	perf_output_end(&handle);
 }
 
-typedef void (perf_iterate_f)(struct perf_event *event, void *data);
+typedef void (perf_iterate_f)(struct perf_event *event, struct perf_event_header *header);
+
+static __always_inline
+void __perf_iterate_output(perf_iterate_f output,
+			   struct perf_event *event,
+			   struct perf_event_header *header)
+{
+	struct perf_event_header old = *header;
+	output(event, header);
+	*header = old;
+}
 
 static void
 perf_iterate_ctx(struct perf_event_context *ctx,
 		   perf_iterate_f output,
-		   void *data, bool all)
+		   struct perf_event_header *header, bool all)
 {
 	struct perf_event *event;
 
@@ -9125,11 +9135,11 @@ perf_iterate_ctx(struct perf_event_context *ctx,
 				continue;
 		}
 
-		output(event, data);
+		__perf_iterate_output(output, event, header);
 	}
 }
 
-static void perf_iterate_sb_cpu(perf_iterate_f output, void *data)
+static void perf_iterate_sb_cpu(perf_iterate_f output, struct perf_event_header *header)
 {
 	struct pmu_event_list *pel = this_cpu_ptr(&pmu_sb_events);
 	struct perf_event *event;
@@ -9147,7 +9157,8 @@ static void perf_iterate_sb_cpu(perf_iterate_f output, void *data)
 			continue;
 		if (!event_filter_match(event))
 			continue;
-		output(event, data);
+
+		__perf_iterate_output(output, event, header);
 	}
 }
 
@@ -9158,7 +9169,7 @@ static void perf_iterate_sb_cpu(perf_iterate_f output, void *data)
  * your event, otherwise it might not get delivered.
  */
 static void
-perf_iterate_sb(perf_iterate_f output, void *data,
+perf_iterate_sb(perf_iterate_f output, struct perf_event_header *header,
 	       struct perf_event_context *task_ctx)
 {
 	struct perf_event_context *ctx;
@@ -9172,15 +9183,15 @@ perf_iterate_sb(perf_iterate_f output, void *data,
 	 * context.
 	 */
 	if (task_ctx) {
-		perf_iterate_ctx(task_ctx, output, data, false);
+		perf_iterate_ctx(task_ctx, output, header, false);
 		goto done;
 	}
 
-	perf_iterate_sb_cpu(output, data);
+	perf_iterate_sb_cpu(output, header);
 
 	ctx = rcu_dereference(current->perf_event_ctxp);
 	if (ctx)
-		perf_iterate_ctx(ctx, output, data, false);
+		perf_iterate_ctx(ctx, output, header, false);
 done:
 	preempt_enable();
 	rcu_read_unlock();
@@ -9347,13 +9358,13 @@ static int perf_event_task_match(struct perf_event *event)
 }
 
 static void perf_event_task_output(struct perf_event *event,
-				   void *data)
+				   struct perf_event_header *header)
 {
-	struct perf_task_event *task_event = data;
+	auto task_event = container_of(header, struct perf_task_event, event_id.header);
+	struct task_struct *task = task_event->task;
 	struct perf_output_handle handle;
 	struct perf_sample_data	sample;
-	struct task_struct *task = task_event->task;
-	int ret, size = task_event->event_id.header.size;
+	int ret;
 
 	if (!perf_event_task_match(event))
 		return;
@@ -9363,7 +9374,7 @@ static void perf_event_task_output(struct perf_event *event,
 	ret = perf_output_begin(&handle, &sample, event,
 				task_event->event_id.header.size);
 	if (ret)
-		goto out;
+		return;
 
 	task_event->event_id.pid = perf_event_pid(event, task);
 	task_event->event_id.tid = perf_event_tid(event, task);
@@ -9385,8 +9396,6 @@ static void perf_event_task_output(struct perf_event *event,
 	perf_event__output_id_sample(event, &handle, &sample);
 
 	perf_output_end(&handle);
-out:
-	task_event->event_id.header.size = size;
 }
 
 static void perf_event_task(struct task_struct *task,
@@ -9418,7 +9427,7 @@ static void perf_event_task(struct task_struct *task,
 	};
 
 	perf_iterate_sb(perf_event_task_output,
-		       &task_event,
+		       &task_event.event_id.header,
 		       task_ctx);
 }
 
@@ -9499,12 +9508,11 @@ static int perf_event_comm_match(struct perf_event *event)
 }
 
 static void perf_event_comm_output(struct perf_event *event,
-				   void *data)
+				   struct perf_event_header *header)
 {
-	struct perf_comm_event *comm_event = data;
+	auto comm_event = container_of(header, struct perf_comm_event, event_id.header);
 	struct perf_output_handle handle;
 	struct perf_sample_data sample;
-	int size = comm_event->event_id.header.size;
 	int ret;
 
 	if (!perf_event_comm_match(event))
@@ -9513,9 +9521,8 @@ static void perf_event_comm_output(struct perf_event *event,
 	perf_event_header__init_id(&comm_event->event_id.header, &sample, event);
 	ret = perf_output_begin(&handle, &sample, event,
 				comm_event->event_id.header.size);
-
 	if (ret)
-		goto out;
+		return;
 
 	comm_event->event_id.pid = perf_event_pid(event, comm_event->task);
 	comm_event->event_id.tid = perf_event_tid(event, comm_event->task);
@@ -9527,8 +9534,6 @@ static void perf_event_comm_output(struct perf_event *event,
 	perf_event__output_id_sample(event, &handle, &sample);
 
 	perf_output_end(&handle);
-out:
-	comm_event->event_id.header.size = size;
 }
 
 static void perf_event_comm_event(struct perf_comm_event *comm_event)
@@ -9546,7 +9551,7 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event)
 	comm_event->event_id.header.size = sizeof(comm_event->event_id) + size;
 
 	perf_iterate_sb(perf_event_comm_output,
-		       comm_event,
+		       &comm_event->event_id.header,
 		       NULL);
 }
 
@@ -9598,12 +9603,11 @@ static int perf_event_namespaces_match(struct perf_event *event)
 }
 
 static void perf_event_namespaces_output(struct perf_event *event,
-					 void *data)
+					 struct perf_event_header *header)
 {
-	struct perf_namespaces_event *namespaces_event = data;
+	auto namespaces_event = container_of(header, struct perf_namespaces_event, event_id.header);
 	struct perf_output_handle handle;
 	struct perf_sample_data sample;
-	u16 header_size = namespaces_event->event_id.header.size;
 	int ret;
 
 	if (!perf_event_namespaces_match(event))
@@ -9614,7 +9618,7 @@ static void perf_event_namespaces_output(struct perf_event *event,
 	ret = perf_output_begin(&handle, &sample, event,
 				namespaces_event->event_id.header.size);
 	if (ret)
-		goto out;
+		return;
 
 	namespaces_event->event_id.pid = perf_event_pid(event,
 							namespaces_event->task);
@@ -9626,8 +9630,6 @@ static void perf_event_namespaces_output(struct perf_event *event,
 	perf_event__output_id_sample(event, &handle, &sample);
 
 	perf_output_end(&handle);
-out:
-	namespaces_event->event_id.header.size = header_size;
 }
 
 static void perf_fill_ns_link_info(struct perf_ns_link_info *ns_link_info,
@@ -9701,7 +9703,7 @@ void perf_event_namespaces(struct task_struct *task)
 #endif
 
 	perf_iterate_sb(perf_event_namespaces_output,
-			&namespaces_event,
+			&namespaces_event.event_id.header,
 			NULL);
 }
 
@@ -9725,12 +9727,11 @@ static int perf_event_cgroup_match(struct perf_event *event)
 	return event->attr.cgroup;
 }
 
-static void perf_event_cgroup_output(struct perf_event *event, void *data)
+static void perf_event_cgroup_output(struct perf_event *event, struct perf_event_header *header)
 {
-	struct perf_cgroup_event *cgroup_event = data;
+	auto cgroup_event = container_of(header, struct perf_cgroup_event, event_id.header);
 	struct perf_output_handle handle;
 	struct perf_sample_data sample;
-	u16 header_size = cgroup_event->event_id.header.size;
 	int ret;
 
 	if (!perf_event_cgroup_match(event))
@@ -9741,7 +9742,7 @@ static void perf_event_cgroup_output(struct perf_event *event, void *data)
 	ret = perf_output_begin(&handle, &sample, event,
 				cgroup_event->event_id.header.size);
 	if (ret)
-		goto out;
+		return;
 
 	perf_output_put(&handle, cgroup_event->event_id);
 	__output_copy(&handle, cgroup_event->path, cgroup_event->path_size);
@@ -9749,8 +9750,6 @@ static void perf_event_cgroup_output(struct perf_event *event, void *data)
 	perf_event__output_id_sample(event, &handle, &sample);
 
 	perf_output_end(&handle);
-out:
-	cgroup_event->event_id.header.size = header_size;
 }
 
 static void perf_event_cgroup(struct cgroup *cgrp)
@@ -9796,7 +9795,7 @@ static void perf_event_cgroup(struct cgroup *cgrp)
 	cgroup_event.path_size = size;
 
 	perf_iterate_sb(perf_event_cgroup_output,
-			&cgroup_event,
+			&cgroup_event.event_id.header,
 			NULL);
 
 	kfree(pathname);
@@ -9832,9 +9831,8 @@ struct perf_mmap_event {
 };
 
 static int perf_event_mmap_match(struct perf_event *event,
-				 void *data)
+				 struct perf_mmap_event *mmap_event)
 {
-	struct perf_mmap_event *mmap_event = data;
 	struct vm_area_struct *vma = mmap_event->vma;
 	int executable = vma->vm_flags & VM_EXEC;
 
@@ -9843,17 +9841,15 @@ static int perf_event_mmap_match(struct perf_event *event,
 }
 
 static void perf_event_mmap_output(struct perf_event *event,
-				   void *data)
+				   struct perf_event_header *header)
 {
-	struct perf_mmap_event *mmap_event = data;
+	auto mmap_event = container_of(header, struct perf_mmap_event, event_id.header);
 	struct perf_output_handle handle;
 	struct perf_sample_data sample;
-	int size = mmap_event->event_id.header.size;
-	u32 type = mmap_event->event_id.header.type;
 	bool use_build_id;
 	int ret;
 
-	if (!perf_event_mmap_match(event, data))
+	if (!perf_event_mmap_match(event, mmap_event))
 		return;
 
 	if (event->attr.mmap2) {
@@ -9870,7 +9866,7 @@ static void perf_event_mmap_output(struct perf_event *event,
 	ret = perf_output_begin(&handle, &sample, event,
 				mmap_event->event_id.header.size);
 	if (ret)
-		goto out;
+		return;
 
 	mmap_event->event_id.pid = perf_event_pid(event, current);
 	mmap_event->event_id.tid = perf_event_tid(event, current);
@@ -9904,9 +9900,6 @@ static void perf_event_mmap_output(struct perf_event *event,
 	perf_event__output_id_sample(event, &handle, &sample);
 
 	perf_output_end(&handle);
-out:
-	mmap_event->event_id.header.size = size;
-	mmap_event->event_id.header.type = type;
 }
 
 static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
@@ -10011,7 +10004,7 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
 		build_id_parse_nofault(vma, mmap_event->build_id, &mmap_event->build_id_size);
 
 	perf_iterate_sb(perf_event_mmap_output,
-		       mmap_event,
+		       &mmap_event->event_id.header,
 		       NULL);
 
 	kfree(buf);
@@ -10236,9 +10229,9 @@ static int perf_event_switch_match(struct perf_event *event)
 	return event->attr.context_switch;
 }
 
-static void perf_event_switch_output(struct perf_event *event, void *data)
+static void perf_event_switch_output(struct perf_event *event, struct perf_event_header *header)
 {
-	struct perf_switch_event *se = data;
+	auto se = container_of(header, struct perf_switch_event, event_id.header);
 	struct perf_output_handle handle;
 	struct perf_sample_data sample;
 	int ret;
@@ -10301,7 +10294,7 @@ static void perf_event_switch(struct task_struct *task,
 				PERF_RECORD_MISC_SWITCH_OUT_PREEMPT;
 	}
 
-	perf_iterate_sb(perf_event_switch_output, &switch_event, NULL);
+	perf_iterate_sb(perf_event_switch_output, &switch_event.event_id.header, NULL);
 }
 
 /*
@@ -10366,9 +10359,9 @@ static int perf_event_ksymbol_match(struct perf_event *event)
 	return event->attr.ksymbol;
 }
 
-static void perf_event_ksymbol_output(struct perf_event *event, void *data)
+static void perf_event_ksymbol_output(struct perf_event *event, struct perf_event_header *header)
 {
-	struct perf_ksymbol_event *ksymbol_event = data;
+	auto ksymbol_event = container_of(header, struct perf_ksymbol_event, event_id.header);
 	struct perf_output_handle handle;
 	struct perf_sample_data sample;
 	int ret;
@@ -10430,7 +10423,7 @@ void perf_event_ksymbol(u16 ksym_type, u64 addr, u32 len, bool unregister,
 		},
 	};
 
-	perf_iterate_sb(perf_event_ksymbol_output, &ksymbol_event, NULL);
+	perf_iterate_sb(perf_event_ksymbol_output, &ksymbol_event.event_id.header, NULL);
 	return;
 err:
 	WARN_ONCE(1, "%s: Invalid KSYMBOL type 0x%x\n", __func__, ksym_type);
@@ -10456,9 +10449,9 @@ static int perf_event_bpf_match(struct perf_event *event)
 	return event->attr.bpf_event;
 }
 
-static void perf_event_bpf_output(struct perf_event *event, void *data)
+static void perf_event_bpf_output(struct perf_event *event, struct perf_event_header *header)
 {
-	struct perf_bpf_event *bpf_event = data;
+	auto bpf_event = container_of(header, struct perf_bpf_event, event_id.header);
 	struct perf_output_handle handle;
 	struct perf_sample_data sample;
 	int ret;
@@ -10536,7 +10529,7 @@ void perf_event_bpf_event(struct bpf_prog *prog,
 	BUILD_BUG_ON(BPF_TAG_SIZE % sizeof(u64));
 
 	memcpy(bpf_event.event_id.tag, prog->tag, BPF_TAG_SIZE);
-	perf_iterate_sb(perf_event_bpf_output, &bpf_event, NULL);
+	perf_iterate_sb(perf_event_bpf_output, &bpf_event.event_id.header, NULL);
 }
 
 struct perf_callchain_deferred_event {
@@ -10549,12 +10542,12 @@ struct perf_callchain_deferred_event {
 	} event;
 };
 
-static void perf_callchain_deferred_output(struct perf_event *event, void *data)
+static void perf_callchain_deferred_output(struct perf_event *event, struct perf_event_header *header)
 {
-	struct perf_callchain_deferred_event *deferred_event = data;
+	auto deferred_event = container_of(header, struct perf_callchain_deferred_event, event.header);
 	struct perf_output_handle handle;
 	struct perf_sample_data sample;
-	int ret, size = deferred_event->event.header.size;
+	int ret;
 
 	if (!event->attr.defer_output)
 		return;
@@ -10565,7 +10558,7 @@ static void perf_callchain_deferred_output(struct perf_event *event, void *data)
 	ret = perf_output_begin(&handle, &sample, event,
 				deferred_event->event.header.size);
 	if (ret)
-		goto out;
+		return;
 
 	perf_output_put(&handle, deferred_event->event);
 	for (int i = 0; i < deferred_event->trace->nr; i++) {
@@ -10575,8 +10568,6 @@ static void perf_callchain_deferred_output(struct perf_event *event, void *data)
 	perf_event__output_id_sample(event, &handle, &sample);
 
 	perf_output_end(&handle);
-out:
-	deferred_event->event.header.size = size;
 }
 
 static void perf_unwind_deferred_callback(struct unwind_work *work,
@@ -10596,7 +10587,7 @@ static void perf_unwind_deferred_callback(struct unwind_work *work,
 		},
 	};
 
-	perf_iterate_sb(perf_callchain_deferred_output, &deferred_event, NULL);
+	perf_iterate_sb(perf_callchain_deferred_output, &deferred_event.event.header, NULL);
 }
 
 struct perf_text_poke_event {
@@ -10618,9 +10609,9 @@ static int perf_event_text_poke_match(struct perf_event *event)
 	return event->attr.text_poke;
 }
 
-static void perf_event_text_poke_output(struct perf_event *event, void *data)
+static void perf_event_text_poke_output(struct perf_event *event, struct perf_event_header *header)
 {
-	struct perf_text_poke_event *text_poke_event = data;
+	auto text_poke_event = container_of(header, struct perf_text_poke_event, event_id.header);
 	struct perf_output_handle handle;
 	struct perf_sample_data sample;
 	u64 padding = 0;
@@ -10680,7 +10671,7 @@ void perf_event_text_poke(const void *addr, const void *old_bytes,
 		},
 	};
 
-	perf_iterate_sb(perf_event_text_poke_output, &text_poke_event, NULL);
+	perf_iterate_sb(perf_event_text_poke_output, &text_poke_event.event_id.header, NULL);
 }
 
 void perf_event_itrace_started(struct perf_event *event)

  parent reply	other threads:[~2026-09-29 12:04 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-29  1:42 [PATCH v1] perf/core: Restore header fields in sideband output callbacks Ian Rogers
2026-09-29  1:48 ` sashiko-bot
2026-09-29 12:04 ` Peter Zijlstra [this message]
2026-09-29 18:21   ` Ian Rogers
2026-09-29 22:23     ` [PATCH v1] perf/core: Replace perf_event_header__init_id with full header init Ian Rogers
2026-09-29 22:35       ` sashiko-bot
2026-10-01  7:07       ` Peter Zijlstra
2026-10-01 16:45         ` Ian Rogers
2026-10-09 23:30       ` patchwork-bot+netdevbpf
2026-09-29 23:37 ` [PATCH v1] perf/core: Restore header fields in sideband output callbacks bot+bpf-ci

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260929120417.GT4120091@noisy.programming.kicks-ass.net \
    --to=peterz@infradead.org \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=irogers@google.com \
    --cc=james.clark@linaro.org \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mingo@redhat.com \
    --cc=namhyung@kernel.org \
    --cc=song@kernel.org \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.