Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5d2cd909 authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo
Browse files

perf evsel: Fix use of inherit



perf stat doesn't mmap and its perfectly fine for it to use task-bound
counters with inheritance.

So set the attr.inherit on the caller and leave the syscall itself to
validate it.

When the mmap fails perf_evlist__mmap will just emit a warning if this
is the failure reason.

Reported-by: default avatarPeter Zijlstra <peterz@infradead.org>
Acked-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
Link: http://lkml.kernel.org/r/20110414170121.GC3229@ghostprotocols.net


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent db9a9cbc
Loading
Loading
Loading
Loading
+5 −2
Original line number Original line Diff line number Diff line
@@ -163,6 +163,7 @@ static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
	struct perf_event_attr *attr = &evsel->attr;
	struct perf_event_attr *attr = &evsel->attr;
	int track = !evsel->idx; /* only the first counter needs these */
	int track = !evsel->idx; /* only the first counter needs these */


	attr->inherit		= !no_inherit;
	attr->read_format	= PERF_FORMAT_TOTAL_TIME_ENABLED |
	attr->read_format	= PERF_FORMAT_TOTAL_TIME_ENABLED |
				  PERF_FORMAT_TOTAL_TIME_RUNNING |
				  PERF_FORMAT_TOTAL_TIME_RUNNING |
				  PERF_FORMAT_ID;
				  PERF_FORMAT_ID;
@@ -251,6 +252,9 @@ static void open_counters(struct perf_evlist *evlist)
{
{
	struct perf_evsel *pos;
	struct perf_evsel *pos;


	if (evlist->cpus->map[0] < 0)
		no_inherit = true;

	list_for_each_entry(pos, &evlist->entries, node) {
	list_for_each_entry(pos, &evlist->entries, node) {
		struct perf_event_attr *attr = &pos->attr;
		struct perf_event_attr *attr = &pos->attr;
		/*
		/*
@@ -271,8 +275,7 @@ static void open_counters(struct perf_evlist *evlist)
retry_sample_id:
retry_sample_id:
		attr->sample_id_all = sample_id_all_avail ? 1 : 0;
		attr->sample_id_all = sample_id_all_avail ? 1 : 0;
try_again:
try_again:
		if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group,
		if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group) < 0) {
				     !no_inherit) < 0) {
			int err = errno;
			int err = errno;


			if (err == EPERM || err == EACCES) {
			if (err == EPERM || err == EACCES) {
+4 −3
Original line number Original line Diff line number Diff line
@@ -167,16 +167,17 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
		attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
		attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
				    PERF_FORMAT_TOTAL_TIME_RUNNING;
				    PERF_FORMAT_TOTAL_TIME_RUNNING;


	attr->inherit = !no_inherit;

	if (system_wide)
	if (system_wide)
		return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false, false);
		return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false);


	attr->inherit = !no_inherit;
	if (target_pid == -1 && target_tid == -1) {
	if (target_pid == -1 && target_tid == -1) {
		attr->disabled = 1;
		attr->disabled = 1;
		attr->enable_on_exec = 1;
		attr->enable_on_exec = 1;
	}
	}


	return perf_evsel__open_per_thread(evsel, evsel_list->threads, false, false);
	return perf_evsel__open_per_thread(evsel, evsel_list->threads, false);
}
}


/*
/*
+5 −5
Original line number Original line Diff line number Diff line
@@ -290,7 +290,7 @@ static int test__open_syscall_event(void)
		goto out_thread_map_delete;
		goto out_thread_map_delete;
	}
	}


	if (perf_evsel__open_per_thread(evsel, threads, false, false) < 0) {
	if (perf_evsel__open_per_thread(evsel, threads, false) < 0) {
		pr_debug("failed to open counter: %s, "
		pr_debug("failed to open counter: %s, "
			 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
			 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
			 strerror(errno));
			 strerror(errno));
@@ -303,7 +303,7 @@ static int test__open_syscall_event(void)
	}
	}


	if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) {
	if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) {
		pr_debug("perf_evsel__open_read_on_cpu\n");
		pr_debug("perf_evsel__read_on_cpu\n");
		goto out_close_fd;
		goto out_close_fd;
	}
	}


@@ -365,7 +365,7 @@ static int test__open_syscall_event_on_all_cpus(void)
		goto out_thread_map_delete;
		goto out_thread_map_delete;
	}
	}


	if (perf_evsel__open(evsel, cpus, threads, false, false) < 0) {
	if (perf_evsel__open(evsel, cpus, threads, false) < 0) {
		pr_debug("failed to open counter: %s, "
		pr_debug("failed to open counter: %s, "
			 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
			 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
			 strerror(errno));
			 strerror(errno));
@@ -418,7 +418,7 @@ static int test__open_syscall_event_on_all_cpus(void)
			continue;
			continue;


		if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) {
		if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) {
			pr_debug("perf_evsel__open_read_on_cpu\n");
			pr_debug("perf_evsel__read_on_cpu\n");
			err = -1;
			err = -1;
			break;
			break;
		}
		}
@@ -529,7 +529,7 @@ static int test__basic_mmap(void)


		perf_evlist__add(evlist, evsels[i]);
		perf_evlist__add(evlist, evsels[i]);


		if (perf_evsel__open(evsels[i], cpus, threads, false, false) < 0) {
		if (perf_evsel__open(evsels[i], cpus, threads, false) < 0) {
			pr_debug("failed to open counter: %s, "
			pr_debug("failed to open counter: %s, "
				 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
				 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
				 strerror(errno));
				 strerror(errno));
+2 −1
Original line number Original line Diff line number Diff line
@@ -845,9 +845,10 @@ static void start_counters(struct perf_evlist *evlist)
		}
		}


		attr->mmap = 1;
		attr->mmap = 1;
		attr->inherit = inherit;
try_again:
try_again:
		if (perf_evsel__open(counter, top.evlist->cpus,
		if (perf_evsel__open(counter, top.evlist->cpus,
				     top.evlist->threads, group, inherit) < 0) {
				     top.evlist->threads, group) < 0) {
			int err = errno;
			int err = errno;


			if (err == EPERM || err == EACCES) {
			if (err == EPERM || err == EACCES) {
+10 −4
Original line number Original line Diff line number Diff line
@@ -12,6 +12,7 @@
#include "evlist.h"
#include "evlist.h"
#include "evsel.h"
#include "evsel.h"
#include "util.h"
#include "util.h"
#include "debug.h"


#include <sys/mman.h>
#include <sys/mman.h>


@@ -250,15 +251,19 @@ int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
	return evlist->mmap != NULL ? 0 : -ENOMEM;
	return evlist->mmap != NULL ? 0 : -ENOMEM;
}
}


static int __perf_evlist__mmap(struct perf_evlist *evlist, int cpu, int prot,
static int __perf_evlist__mmap(struct perf_evlist *evlist, struct perf_evsel *evsel,
			       int mask, int fd)
			       int cpu, int prot, int mask, int fd)
{
{
	evlist->mmap[cpu].prev = 0;
	evlist->mmap[cpu].prev = 0;
	evlist->mmap[cpu].mask = mask;
	evlist->mmap[cpu].mask = mask;
	evlist->mmap[cpu].base = mmap(NULL, evlist->mmap_len, prot,
	evlist->mmap[cpu].base = mmap(NULL, evlist->mmap_len, prot,
				      MAP_SHARED, fd, 0);
				      MAP_SHARED, fd, 0);
	if (evlist->mmap[cpu].base == MAP_FAILED)
	if (evlist->mmap[cpu].base == MAP_FAILED) {
		if (evlist->cpus->map[cpu] == -1 && evsel->attr.inherit)
			ui__warning("Inherit is not allowed on per-task "
				    "events using mmap.\n");
		return -1;
		return -1;
	}


	perf_evlist__add_pollfd(evlist, fd);
	perf_evlist__add_pollfd(evlist, fd);
	return 0;
	return 0;
@@ -312,7 +317,8 @@ int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite)
					if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT,
					if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT,
						  FD(first_evsel, cpu, 0)) != 0)
						  FD(first_evsel, cpu, 0)) != 0)
						goto out_unmap;
						goto out_unmap;
				} else if (__perf_evlist__mmap(evlist, cpu, prot, mask, fd) < 0)
				} else if (__perf_evlist__mmap(evlist, evsel, cpu,
							       prot, mask, fd) < 0)
					goto out_unmap;
					goto out_unmap;


				if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
				if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
Loading