From: Tanushree Shah <tshah@linux.ibm.com>
To: acme@kernel.org, jolsa@kernel.org, adrian.hunter@intel.com,
vmolnaro@redhat.com, mpetlan@redhat.com, tmricht@linux.ibm.com,
maddy@linux.ibm.com, irogers@google.com, namhyung@kernel.org,
linux-kernel@vger.kernel.org
Cc: linux-perf-users@vger.kernel.org, linuxppc-dev@lists.ozlabs.org,
atrajeev@linux.ibm.com, hbathini@linux.ibm.com,
Tejas.Manhas1@ibm.com, Tanushree.Shah@ibm.com,
Shivani.Nittor@ibm.com, Tanushree Shah <tshah@linux.ibm.com>
Subject: [RFC PATCH 3/4] perf data-convert: Add perf.data to trace.dat conversion backend
Date: Mon, 8 Jun 2026 18:29:51 +0530 [thread overview]
Message-ID: <20260608125951.90425-5-tshah@linux.ibm.com> (raw)
In-Reply-To: <20260608125951.90425-2-tshah@linux.ibm.com>
Add data-convert-trace.c implementing trace_convert__perf2dat() to
convert perf.data tracepoint events to trace.dat format.
process_sample_event() is invoked for each PERF_TYPE_TRACEPOINT sample
during perf_session__process_events(), storing raw event bytes per-cpu
via trace_dat__collect_cpu_event().
Once all samples are collected:
- trace_dat__write_options_section1() writes the OPTIONS section with
CPUCOUNT, TRACECLOCK, HEADER_INFO, FTRACE_EVENTS, EVENT_FORMATS,
KALLSYMS, CMDLINES and DONE options.
- trace_dat__write__options_section2() writes the OPTIONS section with
BUFFER option holding per-cpu data offset placeholders and the DONE
option.
- trace_dat__write_flyrecord_section() builds ring buffer pages
per-cpu and patches BUFFER option with final offsets and sizes
Per-cpu buffers are sized to tep_get_page_size() from the session
tep handle and released on all exit paths.
Signed-off-by: Tanushree Shah <tshah@linux.ibm.com>
---
tools/perf/util/Build | 1 +
tools/perf/util/data-convert-trace.c | 152 +++++++++++++++++++++++++++
tools/perf/util/data-convert.h | 4 +
3 files changed, 157 insertions(+)
create mode 100644 tools/perf/util/data-convert-trace.c
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index c000d8032d25..88022b24e170 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -236,6 +236,7 @@ ifeq ($(CONFIG_LIBTRACEEVENT),y)
endif
perf-util-y += data-convert-json.o
+perf-util-$(CONFIG_LIBTRACEEVENT) += data-convert-trace.o
perf-util-y += scripting-engines/
diff --git a/tools/perf/util/data-convert-trace.c b/tools/perf/util/data-convert-trace.c
new file mode 100644
index 000000000000..e4f8b817be36
--- /dev/null
+++ b/tools/perf/util/data-convert-trace.c
@@ -0,0 +1,152 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2026, IBM Corporation
+ * Author: Tanushree Shah <tshah@linux.ibm.com>
+ *
+ * data-convert-trace.c
+ *
+ * Implements perf.data to trace.dat format conversion for tracepoint events.
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <linux/compiler.h>
+#include <linux/err.h>
+
+#include "data-convert.h"
+#include "session.h"
+#include "evsel.h"
+#include "tool.h"
+#include "debug.h"
+#include "trace-dat.h"
+#include "trace-event.h"
+#include "event.h"
+#include "sample.h"
+#include "evlist.h"
+
+struct trace_convert {
+ struct perf_tool tool;
+ u64 events_count;
+};
+
+/* Store raw tracepoint event data in per-cpu buffer for trace.dat flyrecord */
+static int process_sample_event(const struct perf_tool *tool,
+ union perf_event *event __maybe_unused,
+ struct perf_sample *sample,
+ struct evsel *evsel,
+ struct machine *machine __maybe_unused)
+{
+ struct trace_convert *tc = container_of(tool, struct trace_convert, tool);
+
+ /* Collect raw tracepoint data per-cpu */
+ if (trace_dat_fp && sample->raw_size > 0 &&
+ evsel->core.attr.type == PERF_TYPE_TRACEPOINT) {
+ if (trace_dat__collect_cpu_event(sample->cpu, sample->time,
+ sample->raw_data, sample->raw_size) < 0) {
+ pr_err("Failed to collect CPU event\n");
+ return -ENOMEM;
+ }
+ tc->events_count++;
+ }
+
+ return 0;
+}
+
+/* Convert perf.data tracepoint events to trace.dat format */
+int trace_convert__perf2dat(const char *input, const char *to_trace,
+ struct perf_data_convert_opts *opts)
+{
+ struct perf_session *session;
+ struct trace_convert tc = {
+ .events_count = 0,
+ };
+ struct perf_data data = {
+ .path = input,
+ .mode = PERF_DATA_MODE_READ,
+ .force = opts->force,
+ };
+ int ret = -EINVAL;
+ bool cpu_buffers_initialized = false;
+
+ /* Initialize tool with all required callbacks */
+ perf_tool__init(&tc.tool, /*ordered_events=*/true);
+ tc.tool.sample = process_sample_event;
+
+ /* Open output trace.dat file */
+ trace_dat_fp = fopen(to_trace, "wb");
+ if (!trace_dat_fp) {
+ pr_err("Failed to open output file: %s\n", to_trace);
+ return -EINVAL;
+ }
+
+ /* Open perf.data session - this writes trace.dat metadata sections */
+ session = perf_session__new(&data, &tc.tool);
+ if (IS_ERR(session)) {
+ pr_err("Failed to open perf.data file\n");
+ ret = PTR_ERR(session);
+ goto out_close;
+ }
+
+ /* Initialize per-CPU buffers for flyrecord data */
+ if (session->tevent.pevent) {
+ trace_dat_page_size = tep_get_page_size(session->tevent.pevent);
+ if (trace_dat__init_cpu_buffers(session->header.env.nr_cpus_online) < 0) {
+ pr_err("Failed to initialize CPU buffers\n");
+ ret = -ENOMEM;
+ goto out_delete;
+ }
+ cpu_buffers_initialized = true;
+ }
+
+ /* Process all events - collects raw data per-cpu */
+ ret = perf_session__process_events(session);
+ if (ret < 0) {
+ pr_err("Failed to process events\n");
+ goto out_delete;
+ }
+
+ /* Skip file creation if no tracepoint events found */
+ if (tc.events_count == 0) {
+ pr_warning("No tracepoint events found in '%s', skipping trace.dat creation\n",
+ input);
+ ret = -EINVAL;
+ goto out_delete;
+ }
+
+ /* Write trace.dat options and flyrecord sections */
+ if (trace_dat__write_options_section1() < 0) {
+ pr_err("Failed to write options section1\n");
+ ret = -EIO;
+ goto out_delete;
+ }
+ if (trace_dat__write_options_section2() < 0) {
+ pr_err("Failed to write options section2\n");
+ ret = -EIO;
+ goto out_delete;
+ }
+ if (trace_dat__write_flyrecord_section() < 0) {
+ pr_err("Failed to write flyrecord section\n");
+ ret = -EIO;
+ goto out_delete;
+ }
+
+ pr_info("[ perf data convert: Converted '%s' into trace.dat format '%s' ]\n",
+ input, to_trace);
+ pr_info("[ perf data convert: Converted %llu events ]\n",
+ (unsigned long long)tc.events_count);
+
+ ret = 0;
+
+out_delete:
+ if (cpu_buffers_initialized)
+ trace_dat__free_cpu_buffers();
+ perf_session__delete(session);
+out_close:
+ if (trace_dat_fp) {
+ fclose(trace_dat_fp);
+ trace_dat_fp = NULL;
+ }
+ if (ret != 0)
+ unlink(to_trace);
+ return ret;
+}
diff --git a/tools/perf/util/data-convert.h b/tools/perf/util/data-convert.h
index ee651fa680a1..d958e68367fe 100644
--- a/tools/perf/util/data-convert.h
+++ b/tools/perf/util/data-convert.h
@@ -19,4 +19,8 @@ int bt_convert__perf2ctf(const char *input_name, const char *to_ctf,
int bt_convert__perf2json(const char *input_name, const char *to_ctf,
struct perf_data_convert_opts *opts);
+#ifdef HAVE_LIBTRACEEVENT
+int trace_convert__perf2dat(const char *input, const char *to_trace,
+ struct perf_data_convert_opts *opts);
+#endif /* HAVE_LIBTRACEEVENT */
#endif /* __DATA_CONVERT_H */
--
2.53.0
next prev parent reply other threads:[~2026-06-08 13:01 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-08 12:59 [RFC PATCH 0/4] perf: Add perf.data tracepoint events to trace.dat conversion Tanushree Shah
2026-06-08 12:59 ` [RFC PATCH 1/4] perf/trace-dat: Add trace.dat export infrastructure Tanushree Shah
2026-06-08 12:59 ` [RFC PATCH 2/4] perf/trace-event: Write trace.dat metadata sections during parsing Tanushree Shah
2026-06-08 12:59 ` Tanushree Shah [this message]
2026-06-08 12:59 ` [RFC PATCH 4/4] perf data: Add --to-trace-dat option for converting perf.data tracepoint events into trace.dat format Tanushree Shah
2026-06-08 15:18 ` [RFC PATCH 0/4] perf: Add perf.data tracepoint events to trace.dat conversion Ian Rogers
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=20260608125951.90425-5-tshah@linux.ibm.com \
--to=tshah@linux.ibm.com \
--cc=Shivani.Nittor@ibm.com \
--cc=Tanushree.Shah@ibm.com \
--cc=Tejas.Manhas1@ibm.com \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=atrajeev@linux.ibm.com \
--cc=hbathini@linux.ibm.com \
--cc=irogers@google.com \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=maddy@linux.ibm.com \
--cc=mpetlan@redhat.com \
--cc=namhyung@kernel.org \
--cc=tmricht@linux.ibm.com \
--cc=vmolnaro@redhat.com \
/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