Merge tag 'ecryptfs-3.18-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git...
[firefly-linux-kernel-4.4.55.git] / tools / perf / util / cloexec.c
1 #include "util.h"
2 #include "../perf.h"
3 #include "cloexec.h"
4 #include "asm/bug.h"
5
6 static unsigned long flag = PERF_FLAG_FD_CLOEXEC;
7
8 static int perf_flag_probe(void)
9 {
10         /* use 'safest' configuration as used in perf_evsel__fallback() */
11         struct perf_event_attr attr = {
12                 .type = PERF_COUNT_SW_CPU_CLOCK,
13                 .config = PERF_COUNT_SW_CPU_CLOCK,
14         };
15         int fd;
16         int err;
17
18         /* check cloexec flag */
19         fd = sys_perf_event_open(&attr, 0, -1, -1,
20                                  PERF_FLAG_FD_CLOEXEC);
21         err = errno;
22
23         if (fd >= 0) {
24                 close(fd);
25                 return 1;
26         }
27
28         WARN_ONCE(err != EINVAL,
29                   "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n",
30                   err, strerror(err));
31
32         /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */
33         fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
34         err = errno;
35
36         if (WARN_ONCE(fd < 0,
37                       "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n",
38                       err, strerror(err)))
39                 return -1;
40
41         close(fd);
42
43         return 0;
44 }
45
46 unsigned long perf_event_open_cloexec_flag(void)
47 {
48         static bool probed;
49
50         if (!probed) {
51                 if (perf_flag_probe() <= 0)
52                         flag = 0;
53                 probed = true;
54         }
55
56         return flag;
57 }