[PATCH v10 16/18] perf env: Add helper to lazily compute the os_release
From: Ian Rogers
Date: Mon Jun 01 2026 - 03:01:51 EST
In live mode the os_release isn't being initialized, make a lazy
initialization helper that assumes when the os_release isn't
initialized this is live mode.
Signed-off-by: Ian Rogers <irogers@xxxxxxxxxx>
---
tools/perf/util/data-convert-bt.c | 2 +-
tools/perf/util/data-convert-json.c | 6 ++++--
tools/perf/util/env.c | 21 +++++++++++++++++++++
tools/perf/util/env.h | 1 +
tools/perf/util/header.c | 16 +++++++++++-----
tools/perf/util/symbol.c | 4 ++--
6 files changed, 40 insertions(+), 10 deletions(-)
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index b3f745cff2a7..cc51b8677c8e 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -1414,7 +1414,7 @@ do { \
ADD("host", env->hostname);
ADD("sysname", "Linux");
- ADD("release", env->os_release);
+ ADD("release", perf_env__os_release(env));
ADD("version", env->version);
ADD("machine", env->arch);
ADD("domain", "kernel");
diff --git a/tools/perf/util/data-convert-json.c b/tools/perf/util/data-convert-json.c
index a7da93a7ff0e..c71dfb77c697 100644
--- a/tools/perf/util/data-convert-json.c
+++ b/tools/perf/util/data-convert-json.c
@@ -16,6 +16,7 @@
#include "linux/err.h"
#include "util/auxtrace.h"
#include "util/debug.h"
+#include "util/env.h"
#include "util/dso.h"
#include "util/event.h"
#include "util/evsel.h"
@@ -272,7 +273,7 @@ static void output_headers(struct perf_session *session, struct convert_json *c)
{
struct stat st;
const struct perf_header *header = &session->header;
- const struct perf_env *env = perf_session__env(session);
+ struct perf_env *env = perf_session__env(session);
int ret;
int fd = perf_data__fd(session->data);
int i;
@@ -296,7 +297,8 @@ static void output_headers(struct perf_session *session, struct convert_json *c)
output_json_key_format(out, true, 2, "feat-offset", "%" PRIu64, header->feat_offset);
output_json_key_string(out, true, 2, "hostname", env->hostname);
- output_json_key_string(out, true, 2, "os-release", env->os_release);
+ output_json_key_string(out, true, 2, "os-release",
+ perf_env__os_release(env));
output_json_key_string(out, true, 2, "arch", env->arch);
if (env->cpu_desc)
diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c
index f61e10864613..b4fb7420b604 100644
--- a/tools/perf/util/env.c
+++ b/tools/perf/util/env.c
@@ -358,6 +358,27 @@ bool perf_arch_is_big_endian(const char *arch)
return false;
}
+const char *perf_env__os_release(struct perf_env *env)
+{
+ struct utsname uts;
+ int ret;
+
+ if (!env)
+ return perf_version_string;
+
+ if (env->os_release)
+ return env->os_release;
+
+ /*
+ * The os_release is being accessed but wasn't initialized from a data
+ * file, assume this is 'live' mode and use the release from uname. If
+ * uname or strdup fails then use the current perf tool version.
+ */
+ ret = uname(&uts);
+ env->os_release = strdup(ret < 0 ? perf_version_string : uts.release);
+ return env->os_release ?: perf_version_string;
+}
+
int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[])
{
int i;
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
index bc4801d8399b..bbf10446204c 100644
--- a/tools/perf/util/env.h
+++ b/tools/perf/util/env.h
@@ -173,6 +173,7 @@ void perf_env__exit(struct perf_env *env);
int perf_env__kernel_is_64_bit(struct perf_env *env);
bool perf_arch_is_big_endian(const char *arch);
+const char *perf_env__os_release(struct perf_env *env);
int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]);
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index ecdac427d9c4..d7f41db7322c 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -432,13 +432,19 @@ static int write_osrelease(struct feat_fd *ff,
struct evlist *evlist __maybe_unused)
{
struct utsname uts;
- int ret;
+ const char *release = NULL;
- ret = uname(&uts);
- if (ret < 0)
- return -1;
+ if (evlist->session)
+ release = perf_env__os_release(perf_session__env(evlist->session));
- return do_write_string(ff, uts.release);
+ if (!release) {
+ int ret = uname(&uts);
+
+ if (ret < 0)
+ return -1;
+ release = uts.release;
+ }
+ return do_write_string(ff, release);
}
static int write_arch(struct feat_fd *ff, struct evlist *evlist)
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 2ce512f08a1d..077d19af5240 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -2225,7 +2225,7 @@ static int vmlinux_path__init(struct perf_env *env)
{
struct utsname uts;
char bf[PATH_MAX];
- char *kernel_version;
+ const char *kernel_version;
unsigned int i;
vmlinux_path = malloc(sizeof(char *) * (ARRAY_SIZE(vmlinux_paths) +
@@ -2242,7 +2242,7 @@ static int vmlinux_path__init(struct perf_env *env)
return 0;
if (env) {
- kernel_version = env->os_release;
+ kernel_version = perf_env__os_release(env);
} else {
if (uname(&uts) < 0)
goto out_fail;
--
2.54.0.823.g6e5bcc1fc9-goog