diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-12-13 13:10:58 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-01-24 14:40:09 -0500 |
commit | 56e52e85366717481cde16b3480f015c7eb32ba3 (patch) | |
tree | 5e68bd51510915b6da7db8e0fdcc5fc766dd6b6a /tools | |
parent | c0a54341c0e89333ef201fc3f3001176962f6121 (diff) |
perf evsel: Introduce perf_evsel__open_strerror method
That consolidates the error messages in 'record', 'stat' and 'top', that
now get a consistent set of messages and allow other tools to use the
new method to report problems using whatever UI toolkit.
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1cudb7wl996kz7ilz83ctvhr@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/builtin-record.c | 54 | ||||
-rw-r--r-- | tools/perf/builtin-stat.c | 16 | ||||
-rw-r--r-- | tools/perf/builtin-top.c | 34 | ||||
-rw-r--r-- | tools/perf/ui/util.c | 11 | ||||
-rw-r--r-- | tools/perf/util/debug.h | 1 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 49 | ||||
-rw-r--r-- | tools/perf/util/evsel.h | 3 |
7 files changed, 68 insertions, 100 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index b8d0a39b484e..de60dd4ee5d3 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -224,7 +224,7 @@ static bool perf_evlist__equal(struct perf_evlist *evlist, | |||
224 | 224 | ||
225 | static int perf_record__open(struct perf_record *rec) | 225 | static int perf_record__open(struct perf_record *rec) |
226 | { | 226 | { |
227 | char msg[128]; | 227 | char msg[512]; |
228 | struct perf_evsel *pos; | 228 | struct perf_evsel *pos; |
229 | struct perf_evlist *evlist = rec->evlist; | 229 | struct perf_evlist *evlist = rec->evlist; |
230 | struct perf_session *session = rec->session; | 230 | struct perf_session *session = rec->session; |
@@ -234,60 +234,18 @@ static int perf_record__open(struct perf_record *rec) | |||
234 | perf_evlist__config(evlist, opts); | 234 | perf_evlist__config(evlist, opts); |
235 | 235 | ||
236 | list_for_each_entry(pos, &evlist->entries, node) { | 236 | list_for_each_entry(pos, &evlist->entries, node) { |
237 | struct perf_event_attr *attr = &pos->attr; | ||
238 | try_again: | 237 | try_again: |
239 | if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { | 238 | if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { |
240 | int err = errno; | 239 | if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { |
241 | |||
242 | if (err == EPERM || err == EACCES) { | ||
243 | ui__error_paranoid(); | ||
244 | rc = -err; | ||
245 | goto out; | ||
246 | } else if (err == ENODEV && opts->target.cpu_list) { | ||
247 | pr_err("No such device - did you specify" | ||
248 | " an out-of-range profile CPU?\n"); | ||
249 | rc = -err; | ||
250 | goto out; | ||
251 | } | ||
252 | |||
253 | if (perf_evsel__fallback(pos, err, msg, sizeof(msg))) { | ||
254 | if (verbose) | 240 | if (verbose) |
255 | ui__warning("%s\n", msg); | 241 | ui__warning("%s\n", msg); |
256 | goto try_again; | 242 | goto try_again; |
257 | } | 243 | } |
258 | 244 | ||
259 | if (err == ENOENT) { | 245 | rc = -errno; |
260 | ui__error("The %s event is not supported.\n", | 246 | perf_evsel__open_strerror(pos, &opts->target, |
261 | perf_evsel__name(pos)); | 247 | errno, msg, sizeof(msg)); |
262 | rc = -err; | 248 | ui__error("%s\n", msg); |
263 | goto out; | ||
264 | } else if ((err == EOPNOTSUPP) && (attr->precise_ip)) { | ||
265 | ui__error("\'precise\' request may not be supported. " | ||
266 | "Try removing 'p' modifier\n"); | ||
267 | rc = -err; | ||
268 | goto out; | ||
269 | } | ||
270 | |||
271 | printf("\n"); | ||
272 | error("sys_perf_event_open() syscall returned with %d " | ||
273 | "(%s) for event %s. /bin/dmesg may provide " | ||
274 | "additional information.\n", | ||
275 | err, strerror(err), perf_evsel__name(pos)); | ||
276 | |||
277 | #if defined(__i386__) || defined(__x86_64__) | ||
278 | if (attr->type == PERF_TYPE_HARDWARE && | ||
279 | err == EOPNOTSUPP) { | ||
280 | pr_err("No hardware sampling interrupt available." | ||
281 | " No APIC? If so then you can boot the kernel" | ||
282 | " with the \"lapic\" boot parameter to" | ||
283 | " force-enable it.\n"); | ||
284 | rc = -err; | ||
285 | goto out; | ||
286 | } | ||
287 | #endif | ||
288 | |||
289 | pr_err("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); | ||
290 | rc = -err; | ||
291 | goto out; | 249 | goto out; |
292 | } | 250 | } |
293 | } | 251 | } |
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index ef067c193f93..1c2ac148a7d5 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -247,6 +247,7 @@ static int read_counter(struct perf_evsel *counter) | |||
247 | 247 | ||
248 | static int __run_perf_stat(int argc __maybe_unused, const char **argv) | 248 | static int __run_perf_stat(int argc __maybe_unused, const char **argv) |
249 | { | 249 | { |
250 | char msg[512]; | ||
250 | unsigned long long t0, t1; | 251 | unsigned long long t0, t1; |
251 | struct perf_evsel *counter; | 252 | struct perf_evsel *counter; |
252 | int status = 0; | 253 | int status = 0; |
@@ -324,20 +325,13 @@ static int __run_perf_stat(int argc __maybe_unused, const char **argv) | |||
324 | continue; | 325 | continue; |
325 | } | 326 | } |
326 | 327 | ||
327 | if (errno == EPERM || errno == EACCES) { | 328 | perf_evsel__open_strerror(counter, &target, |
328 | error("You may not have permission to collect %sstats.\n" | 329 | errno, msg, sizeof(msg)); |
329 | "\t Consider tweaking" | 330 | ui__error("%s\n", msg); |
330 | " /proc/sys/kernel/perf_event_paranoid or running as root.", | 331 | |
331 | target.system_wide ? "system-wide " : ""); | ||
332 | } else { | ||
333 | error("open_counter returned with %d (%s). " | ||
334 | "/bin/dmesg may provide additional information.\n", | ||
335 | errno, strerror(errno)); | ||
336 | } | ||
337 | if (child_pid != -1) | 332 | if (child_pid != -1) |
338 | kill(child_pid, SIGTERM); | 333 | kill(child_pid, SIGTERM); |
339 | 334 | ||
340 | pr_err("Not all events could be opened.\n"); | ||
341 | return -1; | 335 | return -1; |
342 | } | 336 | } |
343 | counter->supported = true; | 337 | counter->supported = true; |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 8d41d0b58956..f5fd260f7b20 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -892,7 +892,7 @@ static void perf_top__mmap_read(struct perf_top *top) | |||
892 | 892 | ||
893 | static void perf_top__start_counters(struct perf_top *top) | 893 | static void perf_top__start_counters(struct perf_top *top) |
894 | { | 894 | { |
895 | char msg[128]; | 895 | char msg[512]; |
896 | struct perf_evsel *counter; | 896 | struct perf_evsel *counter; |
897 | struct perf_evlist *evlist = top->evlist; | 897 | struct perf_evlist *evlist = top->evlist; |
898 | struct perf_record_opts *opts = &top->record_opts; | 898 | struct perf_record_opts *opts = &top->record_opts; |
@@ -900,42 +900,18 @@ static void perf_top__start_counters(struct perf_top *top) | |||
900 | perf_evlist__config(evlist, opts); | 900 | perf_evlist__config(evlist, opts); |
901 | 901 | ||
902 | list_for_each_entry(counter, &evlist->entries, node) { | 902 | list_for_each_entry(counter, &evlist->entries, node) { |
903 | struct perf_event_attr *attr = &counter->attr; | ||
904 | try_again: | 903 | try_again: |
905 | if (perf_evsel__open(counter, top->evlist->cpus, | 904 | if (perf_evsel__open(counter, top->evlist->cpus, |
906 | top->evlist->threads) < 0) { | 905 | top->evlist->threads) < 0) { |
907 | int err = errno; | 906 | if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) { |
908 | |||
909 | if (err == EPERM || err == EACCES) { | ||
910 | ui__error_paranoid(); | ||
911 | goto out_err; | ||
912 | } | ||
913 | |||
914 | if (perf_evsel__fallback(counter, err, msg, sizeof(msg))) { | ||
915 | if (verbose) | 907 | if (verbose) |
916 | ui__warning("%s\n", msg); | 908 | ui__warning("%s\n", msg); |
917 | goto try_again; | 909 | goto try_again; |
918 | } | 910 | } |
919 | 911 | ||
920 | if (err == ENOENT) { | 912 | perf_evsel__open_strerror(counter, &opts->target, |
921 | ui__error("The %s event is not supported.\n", | 913 | errno, msg, sizeof(msg)); |
922 | perf_evsel__name(counter)); | 914 | ui__error("%s\n", msg); |
923 | goto out_err; | ||
924 | } else if (err == EMFILE) { | ||
925 | ui__error("Too many events are opened.\n" | ||
926 | "Try again after reducing the number of events\n"); | ||
927 | goto out_err; | ||
928 | } else if ((err == EOPNOTSUPP) && (attr->precise_ip)) { | ||
929 | ui__error("\'precise\' request may not be supported. " | ||
930 | "Try removing 'p' modifier\n"); | ||
931 | goto out_err; | ||
932 | } | ||
933 | |||
934 | ui__error("The sys_perf_event_open() syscall " | ||
935 | "returned with %d (%s). /bin/dmesg " | ||
936 | "may provide additional information.\n" | ||
937 | "No CONFIG_PERF_EVENTS=y kernel support " | ||
938 | "configured?\n", err, strerror(err)); | ||
939 | goto out_err; | 915 | goto out_err; |
940 | } | 916 | } |
941 | } | 917 | } |
diff --git a/tools/perf/ui/util.c b/tools/perf/ui/util.c index 3014a7cd5271..e3e0a963d03a 100644 --- a/tools/perf/ui/util.c +++ b/tools/perf/ui/util.c | |||
@@ -52,17 +52,6 @@ int ui__warning(const char *format, ...) | |||
52 | return ret; | 52 | return ret; |
53 | } | 53 | } |
54 | 54 | ||
55 | int ui__error_paranoid(void) | ||
56 | { | ||
57 | return ui__error("Permission error - are you root?\n" | ||
58 | "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n" | ||
59 | " -1 - Not paranoid at all\n" | ||
60 | " 0 - Disallow raw tracepoint access for unpriv\n" | ||
61 | " 1 - Disallow cpu events for unpriv\n" | ||
62 | " 2 - Disallow kernel profiling for unpriv\n"); | ||
63 | } | ||
64 | |||
65 | |||
66 | /** | 55 | /** |
67 | * perf_error__register - Register error logging functions | 56 | * perf_error__register - Register error logging functions |
68 | * @eops: The pointer to error logging function struct | 57 | * @eops: The pointer to error logging function struct |
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h index 6e2667fb8211..efbd98805ad0 100644 --- a/tools/perf/util/debug.h +++ b/tools/perf/util/debug.h | |||
@@ -16,6 +16,5 @@ void trace_event(union perf_event *event); | |||
16 | 16 | ||
17 | int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); | 17 | int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); |
18 | int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); | 18 | int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); |
19 | int ui__error_paranoid(void); | ||
20 | 19 | ||
21 | #endif /* __PERF_DEBUG_H */ | 20 | #endif /* __PERF_DEBUG_H */ |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 0c88e5c12dab..e45332d08a58 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -1406,3 +1406,52 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err, | |||
1406 | 1406 | ||
1407 | return false; | 1407 | return false; |
1408 | } | 1408 | } |
1409 | |||
1410 | int perf_evsel__open_strerror(struct perf_evsel *evsel, | ||
1411 | struct perf_target *target, | ||
1412 | int err, char *msg, size_t size) | ||
1413 | { | ||
1414 | switch (err) { | ||
1415 | case EPERM: | ||
1416 | case EACCES: | ||
1417 | return scnprintf(msg, size, "%s", | ||
1418 | "You may not have permission to collect %sstats.\n" | ||
1419 | "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n" | ||
1420 | " -1 - Not paranoid at all\n" | ||
1421 | " 0 - Disallow raw tracepoint access for unpriv\n" | ||
1422 | " 1 - Disallow cpu events for unpriv\n" | ||
1423 | " 2 - Disallow kernel profiling for unpriv", | ||
1424 | target->system_wide ? "system-wide " : ""); | ||
1425 | case ENOENT: | ||
1426 | return scnprintf(msg, size, "The %s event is not supported.", | ||
1427 | perf_evsel__name(evsel)); | ||
1428 | case EMFILE: | ||
1429 | return scnprintf(msg, size, "%s", | ||
1430 | "Too many events are opened.\n" | ||
1431 | "Try again after reducing the number of events."); | ||
1432 | case ENODEV: | ||
1433 | if (target->cpu_list) | ||
1434 | return scnprintf(msg, size, "%s", | ||
1435 | "No such device - did you specify an out-of-range profile CPU?\n"); | ||
1436 | break; | ||
1437 | case EOPNOTSUPP: | ||
1438 | if (evsel->attr.precise_ip) | ||
1439 | return scnprintf(msg, size, "%s", | ||
1440 | "\'precise\' request may not be supported. Try removing 'p' modifier."); | ||
1441 | #if defined(__i386__) || defined(__x86_64__) | ||
1442 | if (evsel->attr.type == PERF_TYPE_HARDWARE) | ||
1443 | return scnprintf(msg, size, "%s", | ||
1444 | "No hardware sampling interrupt available.\n" | ||
1445 | "No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it."); | ||
1446 | #endif | ||
1447 | break; | ||
1448 | default: | ||
1449 | break; | ||
1450 | } | ||
1451 | |||
1452 | return scnprintf(msg, size, | ||
1453 | "The sys_perf_event_open() syscall returned with %d (%s) for event (%s). \n" | ||
1454 | "/bin/dmesg may provide additional information.\n" | ||
1455 | "No CONFIG_PERF_EVENTS=y kernel support configured?\n", | ||
1456 | err, strerror(err), perf_evsel__name(evsel)); | ||
1457 | } | ||
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 26d8cfd86e0a..c68d1b82e843 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
@@ -254,4 +254,7 @@ int perf_evsel__fprintf(struct perf_evsel *evsel, | |||
254 | 254 | ||
255 | bool perf_evsel__fallback(struct perf_evsel *evsel, int err, | 255 | bool perf_evsel__fallback(struct perf_evsel *evsel, int err, |
256 | char *msg, size_t msgsize); | 256 | char *msg, size_t msgsize); |
257 | int perf_evsel__open_strerror(struct perf_evsel *evsel, | ||
258 | struct perf_target *target, | ||
259 | int err, char *msg, size_t size); | ||
257 | #endif /* __PERF_EVSEL_H */ | 260 | #endif /* __PERF_EVSEL_H */ |