[PATCH v1 04/11] perf tools: Defer /proc lookup until nsinfo is used
From: Namhyung Kim
Date: Fri Oct 23 2026 - 03:15:17 EST
Do not read /proc/<pid>/task/<tid>/ eagerly in nsinfo__new_thread().
Instead, initialize struct nsinfo on demand via nsinfo__ensure_init()
when namespace information is queried or entered.
Also reset the initialization state on exec and PERF_RECORD_NAMESPACES
events so namespace changes are picked up.
Assisted-by: LLM
Signed-off-by: Namhyung Kim <namhyung@xxxxxxxxxx>
---
tools/perf/util/namespaces.c | 46 ++++++++++++++++++++++++++++--------
tools/perf/util/namespaces.h | 2 ++
tools/perf/util/thread.c | 4 ++++
3 files changed, 42 insertions(+), 10 deletions(-)
diff --git a/tools/perf/util/namespaces.c b/tools/perf/util/namespaces.c
index f426eba04d6ef449..843d075d30409029 100644
--- a/tools/perf/util/namespaces.c
+++ b/tools/perf/util/namespaces.c
@@ -103,6 +103,11 @@ int nsinfo__init(struct nsinfo *nsi)
struct stat new_stat;
int rv = -1;
+ if (!nsi)
+ return -1;
+
+ RC_CHK_ACCESS(nsi)->inited = true;
+
if (snprintf(oldns, PATH_MAX, "/proc/self/ns/mnt") >= PATH_MAX)
return rv;
@@ -140,6 +145,12 @@ int nsinfo__init(struct nsinfo *nsi)
return rv;
}
+static void nsinfo__ensure_init(struct nsinfo *nsi)
+{
+ if (nsi && !RC_CHK_ACCESS(nsi)->inited)
+ nsinfo__init(nsi);
+}
+
static struct nsinfo *nsinfo__alloc(void)
{
struct nsinfo *res;
@@ -167,15 +178,6 @@ struct nsinfo *nsinfo__new_thread(pid_t pid, pid_t tid)
RC_CHK_ACCESS(nsi)->tid = tid;
RC_CHK_ACCESS(nsi)->tgid = pid;
RC_CHK_ACCESS(nsi)->nstgid = pid;
- nsinfo__clear_need_setns(nsi);
- RC_CHK_ACCESS(nsi)->in_pidns = false;
- /* Init may fail if the process exits while we're trying to look at its
- * proc information. In that case, save the pid but don't try to enter
- * the namespace.
- */
- if (nsinfo__init(nsi) == -1)
- nsinfo__clear_need_setns(nsi);
-
return nsi;
}
@@ -196,6 +198,8 @@ struct nsinfo *nsinfo__copy(const struct nsinfo *nsi)
if (nsi == NULL)
return NULL;
+ nsinfo__ensure_init((struct nsinfo *)nsi);
+
nnsi = nsinfo__alloc();
if (!nnsi)
return NULL;
@@ -204,7 +208,8 @@ struct nsinfo *nsinfo__copy(const struct nsinfo *nsi)
RC_CHK_ACCESS(nnsi)->tid = nsinfo__tid(nsi);
RC_CHK_ACCESS(nnsi)->tgid = nsinfo__tgid(nsi);
RC_CHK_ACCESS(nnsi)->nstgid = nsinfo__nstgid(nsi);
- RC_CHK_ACCESS(nnsi)->need_setns = nsinfo__need_setns(nsi);
+ RC_CHK_ACCESS(nnsi)->inited = RC_CHK_ACCESS(nsi)->inited;
+ RC_CHK_ACCESS(nnsi)->need_setns = RC_CHK_ACCESS(nsi)->need_setns;
RC_CHK_ACCESS(nnsi)->in_pidns = nsinfo__in_pidns(nsi);
if (nsinfo__mntns_path(nsi)) {
RC_CHK_ACCESS(nnsi)->mntns_path = strdup(nsinfo__mntns_path(nsi));
@@ -251,21 +256,41 @@ void nsinfo__put(struct nsinfo *nsi)
bool nsinfo__need_setns(const struct nsinfo *nsi)
{
+ if (!nsi)
+ return false;
+
+ nsinfo__ensure_init((struct nsinfo *)nsi);
return RC_CHK_ACCESS(nsi)->need_setns;
}
void nsinfo__clear_need_setns(struct nsinfo *nsi)
{
+ if (!nsi)
+ return;
+
+ RC_CHK_ACCESS(nsi)->inited = true;
RC_CHK_ACCESS(nsi)->need_setns = false;
+ zfree(&RC_CHK_ACCESS(nsi)->mntns_path);
+}
+
+void nsinfo__reset_init(struct nsinfo *nsi)
+{
+ if (!nsi)
+ return;
+
+ nsinfo__clear_need_setns(nsi);
+ RC_CHK_ACCESS(nsi)->inited = false;
}
pid_t nsinfo__tgid(const struct nsinfo *nsi)
{
+ nsinfo__ensure_init((struct nsinfo *)nsi);
return RC_CHK_ACCESS(nsi)->tgid;
}
pid_t nsinfo__nstgid(const struct nsinfo *nsi)
{
+ nsinfo__ensure_init((struct nsinfo *)nsi);
return RC_CHK_ACCESS(nsi)->nstgid;
}
@@ -281,6 +306,7 @@ pid_t nsinfo__tid(const struct nsinfo *nsi)
bool nsinfo__in_pidns(const struct nsinfo *nsi)
{
+ nsinfo__ensure_init((struct nsinfo *)nsi);
return RC_CHK_ACCESS(nsi)->in_pidns;
}
diff --git a/tools/perf/util/namespaces.h b/tools/perf/util/namespaces.h
index ea645954944de4be..77fe6f0eaf2f0618 100644
--- a/tools/perf/util/namespaces.h
+++ b/tools/perf/util/namespaces.h
@@ -35,6 +35,7 @@ DECLARE_RC_STRUCT(nsinfo) {
pid_t tid;
pid_t tgid;
pid_t nstgid;
+ bool inited;
bool need_setns;
bool in_pidns;
char *mntns_path;
@@ -57,6 +58,7 @@ void nsinfo__put(struct nsinfo *nsi);
bool nsinfo__need_setns(const struct nsinfo *nsi);
void nsinfo__clear_need_setns(struct nsinfo *nsi);
+void nsinfo__reset_init(struct nsinfo *nsi);
pid_t nsinfo__tgid(const struct nsinfo *nsi);
pid_t nsinfo__nstgid(const struct nsinfo *nsi);
pid_t nsinfo__pid(const struct nsinfo *nsi);
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index d12eb6bc63313b00..377c39ec624bb7bb 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -199,6 +199,8 @@ int thread__set_namespaces(struct thread *thread, u64 timestamp,
down_write(thread__namespaces_lock(thread));
ret = __thread__set_namespaces(thread, timestamp, event);
up_write(thread__namespaces_lock(thread));
+ if (!ret && event)
+ nsinfo__reset_init(thread__nsinfo(thread));
return ret;
}
@@ -282,6 +284,8 @@ int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
down_write(thread__comm_lock(thread));
ret = ____thread__set_comm(thread, str, timestamp, exec);
up_write(thread__comm_lock(thread));
+ if (!ret && exec)
+ nsinfo__reset_init(thread__nsinfo(thread));
return ret;
}
--
2.56.0.257.gf7497c7d27-goog