]> git.itanic.dy.fi Git - linux-stable/commitdiff
perf tools: Add read_all_cgroups() and __cgroup_find()
authorNamhyung Kim <namhyung@kernel.org>
Wed, 6 Sep 2023 17:48:59 +0000 (10:48 -0700)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Tue, 12 Sep 2023 20:32:00 +0000 (17:32 -0300)
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: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung 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.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/cgroup.c
tools/perf/util/cgroup.h

index bfb13306d82c0a2f943fafefd0f5015bec6c32fa..d03651098dde811b851b7bfcae6af7b053a9732a 100644 (file)
@@ -48,28 +48,36 @@ static int open_cgroup(const char *name)
 }
 
 #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 file_handle fh;
                uint64_t cgroup_id;
        } handle;
        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"))
                return -1;
 
        scnprintf(path, PATH_MAX, "%s/%s", mnt, cgrp->name);
 
-       handle.fh.handle_bytes = sizeof(handle.cgroup_id);
-       if (name_to_handle_at(AT_FDCWD, path, &handle.fh, &mount_id, 0) < 0)
-               return -1;
-
-       cgrp->id = handle.cgroup_id;
+       cgrp->id = __read_cgroup_id(path);
        return 0;
 }
+#else
+static inline u64 __read_cgroup_id(const char *path __maybe_unused) { return -1ULL; }
 #endif  /* HAVE_FILE_HANDLE */
 
 #ifndef CGROUP2_SUPER_MAGIC
@@ -562,6 +570,11 @@ struct cgroup *cgroup__findnew(struct perf_env *env, uint64_t id,
        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 *cgrp;
@@ -587,3 +600,35 @@ void perf_env__purge_cgroups(struct perf_env *env)
        }
        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();
+}
index 12256b78608c2f9d0ce89e169bd3581795d3fca9..beb6fe1012ede629a56e8c364c5a2faf9e76bace 100644 (file)
@@ -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,
                               const char *path);
 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);
 
@@ -49,6 +50,9 @@ static inline int read_cgroup_id(struct cgroup *cgrp __maybe_unused)
 }
 #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);
 
 #endif /* __CGROUP_H__ */