Commit 2bc12abc authored by Namhyung Kim's avatar Namhyung Kim Committed by Arnaldo Carvalho de Melo

perf tools: Add read_all_cgroups() and __cgroup_find()

The read_all_cgroups() is to build a tree of cgroups in the system and
users can look up a cgroup using __cgroup_find().

Committer notes:

Had to do this to cover that #else block:

  -static inline u64 __read_cgroup_id(const char *path) { return -1ULL; }
  +static inline u64 __read_cgroup_id(const char *path __maybe_unused) { return -1ULL; }
Reviewed-by: default avatarIan Rogers <irogers@google.com>
Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Hao Luo <haoluo@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Song Liu <song@kernel.org>
Cc: bpf@vger.kernel.org
Link: https://lore.kernel.org/r/20230906174903.346486-2-namhyung@kernel.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 36019dff
...@@ -48,28 +48,36 @@ static int open_cgroup(const char *name) ...@@ -48,28 +48,36 @@ static int open_cgroup(const char *name)
} }
#ifdef HAVE_FILE_HANDLE #ifdef HAVE_FILE_HANDLE
int read_cgroup_id(struct cgroup *cgrp) static u64 __read_cgroup_id(const char *path)
{ {
char path[PATH_MAX + 1];
char mnt[PATH_MAX + 1];
struct { struct {
struct file_handle fh; struct file_handle fh;
uint64_t cgroup_id; uint64_t cgroup_id;
} handle; } handle;
int mount_id; int mount_id;
handle.fh.handle_bytes = sizeof(handle.cgroup_id);
if (name_to_handle_at(AT_FDCWD, path, &handle.fh, &mount_id, 0) < 0)
return -1ULL;
return handle.cgroup_id;
}
int read_cgroup_id(struct cgroup *cgrp)
{
char path[PATH_MAX + 1];
char mnt[PATH_MAX + 1];
if (cgroupfs_find_mountpoint(mnt, PATH_MAX + 1, "perf_event")) if (cgroupfs_find_mountpoint(mnt, PATH_MAX + 1, "perf_event"))
return -1; return -1;
scnprintf(path, PATH_MAX, "%s/%s", mnt, cgrp->name); scnprintf(path, PATH_MAX, "%s/%s", mnt, cgrp->name);
handle.fh.handle_bytes = sizeof(handle.cgroup_id); cgrp->id = __read_cgroup_id(path);
if (name_to_handle_at(AT_FDCWD, path, &handle.fh, &mount_id, 0) < 0)
return -1;
cgrp->id = handle.cgroup_id;
return 0; return 0;
} }
#else
static inline u64 __read_cgroup_id(const char *path __maybe_unused) { return -1ULL; }
#endif /* HAVE_FILE_HANDLE */ #endif /* HAVE_FILE_HANDLE */
#ifndef CGROUP2_SUPER_MAGIC #ifndef CGROUP2_SUPER_MAGIC
...@@ -562,6 +570,11 @@ struct cgroup *cgroup__findnew(struct perf_env *env, uint64_t id, ...@@ -562,6 +570,11 @@ struct cgroup *cgroup__findnew(struct perf_env *env, uint64_t id,
return cgrp; return cgrp;
} }
struct cgroup *__cgroup__find(struct rb_root *root, uint64_t id)
{
return __cgroup__findnew(root, id, /*create=*/false, /*path=*/NULL);
}
struct cgroup *cgroup__find(struct perf_env *env, uint64_t id) struct cgroup *cgroup__find(struct perf_env *env, uint64_t id)
{ {
struct cgroup *cgrp; struct cgroup *cgrp;
...@@ -587,3 +600,35 @@ void perf_env__purge_cgroups(struct perf_env *env) ...@@ -587,3 +600,35 @@ void perf_env__purge_cgroups(struct perf_env *env)
} }
up_write(&env->cgroups.lock); up_write(&env->cgroups.lock);
} }
void read_all_cgroups(struct rb_root *root)
{
char mnt[PATH_MAX];
struct cgroup_name *cn;
int prefix_len;
if (cgroupfs_find_mountpoint(mnt, sizeof(mnt), "perf_event"))
return;
/* cgroup_name will have a full path, skip the root directory */
prefix_len = strlen(mnt);
/* collect all cgroups in the cgroup_list */
if (nftw(mnt, add_cgroup_name, 20, 0) < 0)
return;
list_for_each_entry(cn, &cgroup_list, list) {
const char *name;
u64 cgrp_id;
/* cgroup_name might have a full path, skip the prefix */
name = cn->name + prefix_len;
if (name[0] == '\0')
name = "/";
cgrp_id = __read_cgroup_id(cn->name);
__cgroup__findnew(root, cgrp_id, /*create=*/true, name);
}
release_cgroup_list();
}
...@@ -37,6 +37,7 @@ int parse_cgroups(const struct option *opt, const char *str, int unset); ...@@ -37,6 +37,7 @@ int parse_cgroups(const struct option *opt, const char *str, int unset);
struct cgroup *cgroup__findnew(struct perf_env *env, uint64_t id, struct cgroup *cgroup__findnew(struct perf_env *env, uint64_t id,
const char *path); const char *path);
struct cgroup *cgroup__find(struct perf_env *env, uint64_t id); struct cgroup *cgroup__find(struct perf_env *env, uint64_t id);
struct cgroup *__cgroup__find(struct rb_root *root, uint64_t id);
void perf_env__purge_cgroups(struct perf_env *env); void perf_env__purge_cgroups(struct perf_env *env);
...@@ -49,6 +50,9 @@ static inline int read_cgroup_id(struct cgroup *cgrp __maybe_unused) ...@@ -49,6 +50,9 @@ static inline int read_cgroup_id(struct cgroup *cgrp __maybe_unused)
} }
#endif /* HAVE_FILE_HANDLE */ #endif /* HAVE_FILE_HANDLE */
/* read all cgroups in the system and save them in the rbtree */
void read_all_cgroups(struct rb_root *root);
int cgroup_is_v2(const char *subsys); int cgroup_is_v2(const char *subsys);
#endif /* __CGROUP_H__ */ #endif /* __CGROUP_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment