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

perf cgroup: Maintain cgroup hierarchy



Each cgroup is kept in the perf_env's cgroup_tree sorted by the cgroup
id.  Hist entries have cgroup id can compare it directly and later it
can be used to find a group name using this tree.

Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lore.kernel.org/lkml/20200325124536.2800725-5-namhyung@kernel.org


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent ba78c1c5
Loading
Loading
Loading
Loading
+80 −0
Original line number Original line Diff line number Diff line
@@ -191,3 +191,83 @@ int parse_cgroups(const struct option *opt, const char *str,
	}
	}
	return 0;
	return 0;
}
}

static struct cgroup *__cgroup__findnew(struct rb_root *root, uint64_t id,
					bool create, const char *path)
{
	struct rb_node **p = &root->rb_node;
	struct rb_node *parent = NULL;
	struct cgroup *cgrp;

	while (*p != NULL) {
		parent = *p;
		cgrp = rb_entry(parent, struct cgroup, node);

		if (cgrp->id == id)
			return cgrp;

		if (cgrp->id < id)
			p = &(*p)->rb_left;
		else
			p = &(*p)->rb_right;
	}

	if (!create)
		return NULL;

	cgrp = malloc(sizeof(*cgrp));
	if (cgrp == NULL)
		return NULL;

	cgrp->name = strdup(path);
	if (cgrp->name == NULL) {
		free(cgrp);
		return NULL;
	}

	cgrp->fd = -1;
	cgrp->id = id;
	refcount_set(&cgrp->refcnt, 1);

	rb_link_node(&cgrp->node, parent, p);
	rb_insert_color(&cgrp->node, root);

	return cgrp;
}

struct cgroup *cgroup__findnew(struct perf_env *env, uint64_t id,
			       const char *path)
{
	struct cgroup *cgrp;

	down_write(&env->cgroups.lock);
	cgrp = __cgroup__findnew(&env->cgroups.tree, id, true, path);
	up_write(&env->cgroups.lock);
	return cgrp;
}

struct cgroup *cgroup__find(struct perf_env *env, uint64_t id)
{
	struct cgroup *cgrp;

	down_read(&env->cgroups.lock);
	cgrp = __cgroup__findnew(&env->cgroups.tree, id, false, NULL);
	up_read(&env->cgroups.lock);
	return cgrp;
}

void perf_env__purge_cgroups(struct perf_env *env)
{
	struct rb_node *node;
	struct cgroup *cgrp;

	down_write(&env->cgroups.lock);
	while (!RB_EMPTY_ROOT(&env->cgroups.tree)) {
		node = rb_first(&env->cgroups.tree);
		cgrp = rb_entry(node, struct cgroup, node);

		rb_erase(node, &env->cgroups.tree);
		cgroup__put(cgrp);
	}
	up_write(&env->cgroups.lock);
}
+13 −4
Original line number Original line Diff line number Diff line
@@ -3,16 +3,19 @@
#define __CGROUP_H__
#define __CGROUP_H__


#include <linux/refcount.h>
#include <linux/refcount.h>
#include <linux/rbtree.h>
#include "util/env.h"


struct option;
struct option;


struct cgroup {
struct cgroup {
	struct rb_node		node;
	u64			id;
	char			*name;
	char			*name;
	int			fd;
	int			fd;
	refcount_t		refcnt;
	refcount_t		refcnt;
};
};



extern int nr_cgroups; /* number of explicit cgroups defined */
extern int nr_cgroups; /* number of explicit cgroups defined */


struct cgroup *cgroup__get(struct cgroup *cgroup);
struct cgroup *cgroup__get(struct cgroup *cgroup);
@@ -26,4 +29,10 @@ void evlist__set_default_cgroup(struct evlist *evlist, struct cgroup *cgroup);


int parse_cgroups(const struct option *opt, const char *str, int unset);
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);

void perf_env__purge_cgroups(struct perf_env *env);

#endif /* __CGROUP_H__ */
#endif /* __CGROUP_H__ */
+2 −0
Original line number Original line Diff line number Diff line
@@ -6,6 +6,7 @@
#include <linux/ctype.h>
#include <linux/ctype.h>
#include <linux/zalloc.h>
#include <linux/zalloc.h>
#include "bpf-event.h"
#include "bpf-event.h"
#include "cgroup.h"
#include <errno.h>
#include <errno.h>
#include <sys/utsname.h>
#include <sys/utsname.h>
#include <bpf/libbpf.h>
#include <bpf/libbpf.h>
@@ -168,6 +169,7 @@ void perf_env__exit(struct perf_env *env)
	int i;
	int i;


	perf_env__purge_bpf(env);
	perf_env__purge_bpf(env);
	perf_env__purge_cgroups(env);
	zfree(&env->hostname);
	zfree(&env->hostname);
	zfree(&env->os_release);
	zfree(&env->os_release);
	zfree(&env->version);
	zfree(&env->version);
+6 −0
Original line number Original line Diff line number Diff line
@@ -88,6 +88,12 @@ struct perf_env {
		u32			btfs_cnt;
		u32			btfs_cnt;
	} bpf_progs;
	} bpf_progs;


	/* same reason as above (for perf-top) */
	struct {
		struct rw_semaphore	lock;
		struct rb_root		tree;
	} cgroups;

	/* For fast cpu to numa node lookup via perf_env__numa_node */
	/* For fast cpu to numa node lookup via perf_env__numa_node */
	int			*numa_map;
	int			*numa_map;
	int			 nr_numa_map;
	int			 nr_numa_map;
+8 −1
Original line number Original line Diff line number Diff line
@@ -33,6 +33,7 @@
#include "asm/bug.h"
#include "asm/bug.h"
#include "bpf-event.h"
#include "bpf-event.h"
#include <internal/lib.h> // page_size
#include <internal/lib.h> // page_size
#include "cgroup.h"


#include <linux/ctype.h>
#include <linux/ctype.h>
#include <symbol/kallsyms.h>
#include <symbol/kallsyms.h>
@@ -654,13 +655,19 @@ int machine__process_namespaces_event(struct machine *machine __maybe_unused,
	return err;
	return err;
}
}


int machine__process_cgroup_event(struct machine *machine __maybe_unused,
int machine__process_cgroup_event(struct machine *machine,
				  union perf_event *event,
				  union perf_event *event,
				  struct perf_sample *sample __maybe_unused)
				  struct perf_sample *sample __maybe_unused)
{
{
	struct cgroup *cgrp;

	if (dump_trace)
	if (dump_trace)
		perf_event__fprintf_cgroup(event, stdout);
		perf_event__fprintf_cgroup(event, stdout);


	cgrp = cgroup__findnew(machine->env, event->cgroup.id, event->cgroup.path);
	if (cgrp == NULL)
		return -ENOMEM;

	return 0;
	return 0;
}
}