aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorCorey Ashford <cjashfor@linux.vnet.ibm.com>2010-11-19 20:37:24 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-11-20 10:04:15 -0500
commitd9cf837ef9629ab34167bd6fc0141383ddb8813a (patch)
tree3da536a15ea586dacb113f50f76e566a96216908 /tools/perf
parent4aafd3f71a257a3522932944b5204262dfdff147 (diff)
perf stat: Change and clean up sys_perf_event_open error handling
This patch makes several changes to "perf stat": - "perf stat" will no longer go ahead and run the application when one or more of the specified events could not be opened. - Use error() and die() instead of pr_err() so that the output is more consistent with "perf top" and "perf record". - Handle permission errors in a more robust way, and in a similar way to "perf record" and "perf top". In addition, the sys_perf_event_open() error handling of "perf top" and "perf record" is made more consistent and adds the following phrase when an event doesn't open (with something ther than an access or permission error): "/bin/dmesg may provide additional information." This is added because kernel code doesn't have a good way of expressing detailed errors to user space, so its only avenue is to use printk's. However, many users may not think of looking at dmesg to find out why an event is being rejected. Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Peter Zijlstra <fweisbec@gmail.com> Cc: Ian Munsie <ianmunsi@au1.ibm.com> Cc: Michael Ellerman <michaele@au1.ibm.com> LKML-Reference: <1290217044-26293-1-git-send-email-cjashfor@linux.vnet.ibm.com> Signed-off-by: Corey Ashford <cjashfor@linux.vnet.ibm.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/builtin-record.c2
-rw-r--r--tools/perf/builtin-stat.c38
-rw-r--r--tools/perf/builtin-top.c6
3 files changed, 29 insertions, 17 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 93bd2ff001fb..d9dd47885218 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -326,7 +326,7 @@ try_again:
326 goto try_again; 326 goto try_again;
327 } 327 }
328 printf("\n"); 328 printf("\n");
329 error("perfcounter syscall returned with %d (%s)\n", 329 error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n",
330 fd[nr_cpu][counter][thread_index], strerror(err)); 330 fd[nr_cpu][counter][thread_index], strerror(err));
331 331
332#if defined(__i386__) || defined(__x86_64__) 332#if defined(__i386__) || defined(__x86_64__)
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index b3e568ffad27..970a7f2a083d 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -153,9 +153,9 @@ struct stats walltime_nsecs_stats;
153 attrs[counter].config == PERF_COUNT_##c) 153 attrs[counter].config == PERF_COUNT_##c)
154 154
155#define ERR_PERF_OPEN \ 155#define ERR_PERF_OPEN \
156"Error: counter %d, sys_perf_event_open() syscall returned with %d (%s)\n" 156"counter %d, sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information."
157 157
158static int create_perf_stat_counter(int counter) 158static int create_perf_stat_counter(int counter, bool *perm_err)
159{ 159{
160 struct perf_event_attr *attr = attrs + counter; 160 struct perf_event_attr *attr = attrs + counter;
161 int thread; 161 int thread;
@@ -171,11 +171,14 @@ static int create_perf_stat_counter(int counter)
171 for (cpu = 0; cpu < nr_cpus; cpu++) { 171 for (cpu = 0; cpu < nr_cpus; cpu++) {
172 fd[cpu][counter][0] = sys_perf_event_open(attr, 172 fd[cpu][counter][0] = sys_perf_event_open(attr,
173 -1, cpumap[cpu], -1, 0); 173 -1, cpumap[cpu], -1, 0);
174 if (fd[cpu][counter][0] < 0) 174 if (fd[cpu][counter][0] < 0) {
175 pr_debug(ERR_PERF_OPEN, counter, 175 if (errno == EPERM || errno == EACCES)
176 *perm_err = true;
177 error(ERR_PERF_OPEN, counter,
176 fd[cpu][counter][0], strerror(errno)); 178 fd[cpu][counter][0], strerror(errno));
177 else 179 } else {
178 ++ncreated; 180 ++ncreated;
181 }
179 } 182 }
180 } else { 183 } else {
181 attr->inherit = !no_inherit; 184 attr->inherit = !no_inherit;
@@ -186,12 +189,15 @@ static int create_perf_stat_counter(int counter)
186 for (thread = 0; thread < thread_num; thread++) { 189 for (thread = 0; thread < thread_num; thread++) {
187 fd[0][counter][thread] = sys_perf_event_open(attr, 190 fd[0][counter][thread] = sys_perf_event_open(attr,
188 all_tids[thread], -1, -1, 0); 191 all_tids[thread], -1, -1, 0);
189 if (fd[0][counter][thread] < 0) 192 if (fd[0][counter][thread] < 0) {
190 pr_debug(ERR_PERF_OPEN, counter, 193 if (errno == EPERM || errno == EACCES)
194 *perm_err = true;
195 error(ERR_PERF_OPEN, counter,
191 fd[0][counter][thread], 196 fd[0][counter][thread],
192 strerror(errno)); 197 strerror(errno));
193 else 198 } else {
194 ++ncreated; 199 ++ncreated;
200 }
195 } 201 }
196 } 202 }
197 203
@@ -332,6 +338,7 @@ static int run_perf_stat(int argc __used, const char **argv)
332 int status = 0; 338 int status = 0;
333 int counter, ncreated = 0; 339 int counter, ncreated = 0;
334 int child_ready_pipe[2], go_pipe[2]; 340 int child_ready_pipe[2], go_pipe[2];
341 bool perm_err = false;
335 const bool forks = (argc > 0); 342 const bool forks = (argc > 0);
336 char buf; 343 char buf;
337 344
@@ -390,12 +397,15 @@ static int run_perf_stat(int argc __used, const char **argv)
390 } 397 }
391 398
392 for (counter = 0; counter < nr_counters; counter++) 399 for (counter = 0; counter < nr_counters; counter++)
393 ncreated += create_perf_stat_counter(counter); 400 ncreated += create_perf_stat_counter(counter, &perm_err);
394 401
395 if (ncreated == 0) { 402 if (ncreated < nr_counters) {
396 pr_err("No permission to collect %sstats.\n" 403 if (perm_err)
397 "Consider tweaking /proc/sys/kernel/perf_event_paranoid.\n", 404 error("You may not have permission to collect %sstats.\n"
398 system_wide ? "system-wide " : ""); 405 "\t Consider tweaking"
406 " /proc/sys/kernel/perf_event_paranoid or running as root.",
407 system_wide ? "system-wide " : "");
408 die("Not all events could be opened.\n");
399 if (child_pid != -1) 409 if (child_pid != -1)
400 kill(child_pid, SIGTERM); 410 kill(child_pid, SIGTERM);
401 return -1; 411 return -1;
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index dd625808c2a5..3d2b47d5121a 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1214,7 +1214,9 @@ try_again:
1214 int err = errno; 1214 int err = errno;
1215 1215
1216 if (err == EPERM || err == EACCES) 1216 if (err == EPERM || err == EACCES)
1217 die("No permission - are you root?\n"); 1217 die("Permission error - are you root?\n"
1218 "\t Consider tweaking"
1219 " /proc/sys/kernel/perf_event_paranoid.\n");
1218 /* 1220 /*
1219 * If it's cycles then fall back to hrtimer 1221 * If it's cycles then fall back to hrtimer
1220 * based cpu-clock-tick sw counter, which 1222 * based cpu-clock-tick sw counter, which
@@ -1231,7 +1233,7 @@ try_again:
1231 goto try_again; 1233 goto try_again;
1232 } 1234 }
1233 printf("\n"); 1235 printf("\n");
1234 error("perfcounter syscall returned with %d (%s)\n", 1236 error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n",
1235 fd[i][counter][thread_index], strerror(err)); 1237 fd[i][counter][thread_index], strerror(err));
1236 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 1238 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
1237 exit(-1); 1239 exit(-1);