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

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.org


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 36019dff
Loading
Loading
Loading
Loading
+53 −8
Original line number Diff line number Diff line
@@ -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();
}
+4 −0
Original line number Diff line number Diff line
@@ -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__ */