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)
next prev parent reply other threads:[~2026-09-29 12:04 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-29 1:42 Ian Rogers
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 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 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®