[PATCH v9 16/18] perf env: Add helper to lazily compute the os_release

From: Ian Rogers

Date: Sat May 02 2026 - 20:29:00 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/env.c | 21 +++++++++++++++++++++
tools/perf/util/env.h | 1 +
tools/perf/util/header.c | 16 +++++++++++-----
tools/perf/util/symbol.c | 4 ++--
5 files changed, 36 insertions(+), 8 deletions(-)

diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index 3b8f2df823a9..2c88420fe33e 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/env.c b/tools/perf/util/env.c
index 29d5fe37528b..45dde40042b5 100644
--- a/tools/perf/util/env.c
+++ b/tools/perf/util/env.c
@@ -351,6 +351,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 bdf6c5d0fd5d..ce0c392ead69 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -370,13 +370,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 a4b1f837a5a5..fabed5b0fa57 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.545.g6539524ca2-goog