perf/core improvements and fixes:

. Update attr test with PERF_FLAG_FD_CLOEXEC flag (Jiri Olsa)
 
 . Enable close-on-exec flag on perf file descriptor (Yann Droneaud)
 
 Signed-off-by: Jiri Olsa <jolsa@kernel.org>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJTyMsUAAoJEPZqUSBWB3s9Oq8P/i1nD9f5HyO3E8J1xrvqfTNV
 0H4OHa09zrRuDiHuYjhNgpoCfKT0UA7lvUHTiOyNOL46T1P8FlWznhegdz84mCsP
 Iz57Yr4qTE9iGIeOPGJWSnkG++tcngZBuop73I/UfZz1sngz02PunQYu9eoQQQTL
 XGOc6VkgNJK1nfuPNW/e/bwcdcEoEoRqjCX8VHlW32q7HnM/RpH/SinqdETTV2g9
 4NA+xSQsaqcYTnb3W8NqgpVoW1SCV8VagR/+pN0ajHouEEtHfwvYlrhWmZsaEBAC
 GMbFMgTH3LXlFmQgZq56cMvUsKDmlJCwwL4d60fsXiIkkQBzuRU6sfh93oBI+UFr
 oEI7thFMGvCKXk7q9zICgJn19RkJ0ZeSrmPHLkvtSlWwLxnINFb3XRGpwtgFRdw5
 K3esnCbBy+PSmj8rH8TvzQ24aGJ0ohOmlBmJ7zZJMkPEygh1HFWDDC5ICFvY6Bsy
 ST/8hvbKnLCgZgNUGI4TZhPfj/ldN/GLWeW7UFY2tlCmuJdgnsJtjpr0/QxfDZMF
 O7u6XIzZe8LCHQHL+WxPJrPpLaCnDPLKXq3Dur5ze8rVdcfmvXSF6XxeaZ6Y3RtP
 YhTLXMSnKMgm+g0d9qL+msyftyAVzjd2NVy0jumP3T9jC6cxmCxQJWkoCskD4c8l
 5D8RUTa++P7zQqy1zzCT
 =qp4/
 -----END PGP SIGNATURE-----

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf into perf/core

Pull perf/core improvements and fixes from Jiri Olsa:

. Update attr test with PERF_FLAG_FD_CLOEXEC flag (Jiri Olsa)

. Enable close-on-exec flag on perf file descriptor (Yann Droneaud)

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Ingo Molnar 2014-07-18 12:19:20 +02:00
commit 2336ebc326
13 changed files with 101 additions and 14 deletions

View file

@ -376,6 +376,7 @@ LIB_OBJS += $(OUTPUT)util/record.o
LIB_OBJS += $(OUTPUT)util/srcline.o
LIB_OBJS += $(OUTPUT)util/data.o
LIB_OBJS += $(OUTPUT)util/tsc.o
LIB_OBJS += $(OUTPUT)util/cloexec.o
LIB_OBJS += $(OUTPUT)ui/setup.o
LIB_OBJS += $(OUTPUT)ui/helpline.o

View file

@ -10,6 +10,7 @@
#include "../util/util.h"
#include "../util/parse-options.h"
#include "../util/header.h"
#include "../util/cloexec.h"
#include "bench.h"
#include "mem-memcpy-arch.h"
@ -83,7 +84,8 @@ static struct perf_event_attr cycle_attr = {
static void init_cycle(void)
{
cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0);
cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1,
perf_event_open_cloexec_flag());
if (cycle_fd < 0 && errno == ENOSYS)
die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");

View file

@ -10,6 +10,7 @@
#include "../util/util.h"
#include "../util/parse-options.h"
#include "../util/header.h"
#include "../util/cloexec.h"
#include "bench.h"
#include "mem-memset-arch.h"
@ -83,7 +84,8 @@ static struct perf_event_attr cycle_attr = {
static void init_cycle(void)
{
cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0);
cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1,
perf_event_open_cloexec_flag());
if (cycle_fd < 0 && errno == ENOSYS)
die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");

View file

@ -10,6 +10,7 @@
#include "util/header.h"
#include "util/session.h"
#include "util/tool.h"
#include "util/cloexec.h"
#include "util/parse-options.h"
#include "util/trace-event.h"
@ -434,7 +435,8 @@ static int self_open_counters(void)
attr.type = PERF_TYPE_SOFTWARE;
attr.config = PERF_COUNT_SW_TASK_CLOCK;
fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
fd = sys_perf_event_open(&attr, 0, -1, -1,
perf_event_open_cloexec_flag());
if (fd < 0)
pr_err("Error: sys_perf_event_open() syscall returned "

View file

@ -1,7 +1,8 @@
[event]
fd=1
group_fd=-1
flags=0
# 0 or PERF_FLAG_FD_CLOEXEC flag
flags=0|8
cpu=*
type=0|1
size=96

View file

@ -1,7 +1,8 @@
[event]
fd=1
group_fd=-1
flags=0
# 0 or PERF_FLAG_FD_CLOEXEC flag
flags=0|8
cpu=*
type=0
size=96

View file

@ -25,6 +25,7 @@
#include "tests.h"
#include "debug.h"
#include "perf.h"
#include "cloexec.h"
static int fd1;
static int fd2;
@ -78,7 +79,8 @@ static int bp_event(void *fn, int setup_signal)
pe.exclude_kernel = 1;
pe.exclude_hv = 1;
fd = sys_perf_event_open(&pe, 0, -1, -1, 0);
fd = sys_perf_event_open(&pe, 0, -1, -1,
perf_event_open_cloexec_flag());
if (fd < 0) {
pr_debug("failed opening event %llx\n", pe.config);
return TEST_FAIL;

View file

@ -24,6 +24,7 @@
#include "tests.h"
#include "debug.h"
#include "perf.h"
#include "cloexec.h"
static int overflows;
@ -91,7 +92,8 @@ int test__bp_signal_overflow(void)
pe.exclude_kernel = 1;
pe.exclude_hv = 1;
fd = sys_perf_event_open(&pe, 0, -1, -1, 0);
fd = sys_perf_event_open(&pe, 0, -1, -1,
perf_event_open_cloexec_flag());
if (fd < 0) {
pr_debug("failed opening event %llx\n", pe.config);
return TEST_FAIL;

View file

@ -6,6 +6,7 @@
#include "perf.h"
#include "debug.h"
#include "tests.h"
#include "cloexec.h"
#if defined(__x86_64__) || defined(__i386__)
@ -104,7 +105,8 @@ static int __test__rdpmc(void)
sa.sa_sigaction = segfault_handler;
sigaction(SIGSEGV, &sa, NULL);
fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
fd = sys_perf_event_open(&attr, 0, -1, -1,
perf_event_open_cloexec_flag());
if (fd < 0) {
pr_err("Error: sys_perf_event_open() syscall returned "
"with %d (%s)\n", fd, strerror(errno));

57
tools/perf/util/cloexec.c Normal file
View file

@ -0,0 +1,57 @@
#include "util.h"
#include "../perf.h"
#include "cloexec.h"
#include "asm/bug.h"
static unsigned long flag = PERF_FLAG_FD_CLOEXEC;
static int perf_flag_probe(void)
{
/* use 'safest' configuration as used in perf_evsel__fallback() */
struct perf_event_attr attr = {
.type = PERF_COUNT_SW_CPU_CLOCK,
.config = PERF_COUNT_SW_CPU_CLOCK,
};
int fd;
int err;
/* check cloexec flag */
fd = sys_perf_event_open(&attr, 0, -1, -1,
PERF_FLAG_FD_CLOEXEC);
err = errno;
if (fd >= 0) {
close(fd);
return 1;
}
WARN_ONCE(err != EINVAL,
"perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n",
err, strerror(err));
/* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */
fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
err = errno;
if (WARN_ONCE(fd < 0,
"perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n",
err, strerror(err)))
return -1;
close(fd);
return 0;
}
unsigned long perf_event_open_cloexec_flag(void)
{
static bool probed;
if (!probed) {
if (perf_flag_probe() <= 0)
flag = 0;
probed = true;
}
return flag;
}

View file

@ -0,0 +1,6 @@
#ifndef __PERF_CLOEXEC_H
#define __PERF_CLOEXEC_H
unsigned long perf_event_open_cloexec_flag(void);
#endif /* __PERF_CLOEXEC_H */

View file

@ -29,6 +29,7 @@ static struct {
bool sample_id_all;
bool exclude_guest;
bool mmap2;
bool cloexec;
} perf_missing_features;
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
@ -994,7 +995,7 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
struct thread_map *threads)
{
int cpu, thread;
unsigned long flags = 0;
unsigned long flags = PERF_FLAG_FD_CLOEXEC;
int pid = -1, err;
enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE;
@ -1003,11 +1004,13 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
return -ENOMEM;
if (evsel->cgrp) {
flags = PERF_FLAG_PID_CGROUP;
flags |= PERF_FLAG_PID_CGROUP;
pid = evsel->cgrp->fd;
}
fallback_missing_features:
if (perf_missing_features.cloexec)
flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC;
if (perf_missing_features.mmap2)
evsel->attr.mmap2 = 0;
if (perf_missing_features.exclude_guest)
@ -1076,7 +1079,10 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
if (err != -EINVAL || cpu > 0 || thread > 0)
goto out_close;
if (!perf_missing_features.mmap2 && evsel->attr.mmap2) {
if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) {
perf_missing_features.cloexec = true;
goto fallback_missing_features;
} else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) {
perf_missing_features.mmap2 = true;
goto fallback_missing_features;
} else if (!perf_missing_features.exclude_guest &&

View file

@ -4,6 +4,7 @@
#include "parse-events.h"
#include <api/fs/fs.h>
#include "util.h"
#include "cloexec.h"
typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel);
@ -11,6 +12,7 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
{
struct perf_evlist *evlist;
struct perf_evsel *evsel;
unsigned long flags = perf_event_open_cloexec_flag();
int err = -EAGAIN, fd;
evlist = perf_evlist__new();
@ -22,14 +24,14 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
evsel = perf_evlist__first(evlist);
fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 0);
fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, flags);
if (fd < 0)
goto out_delete;
close(fd);
fn(evsel);
fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 0);
fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, flags);
if (fd < 0) {
if (errno == EINVAL)
err = -EINVAL;
@ -219,7 +221,8 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
cpu = evlist->cpus->map[0];
}
fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 0);
fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1,
perf_event_open_cloexec_flag());
if (fd >= 0) {
close(fd);
ret = true;