diff options
author | Ingo Molnar <mingo@kernel.org> | 2015-09-16 03:12:07 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-09-16 03:12:07 -0400 |
commit | a4d71093e759b7cfe0babbc6ae89c8130532f6ad (patch) | |
tree | 760399c41577b0e70ca4ecd32a807b19a625d432 /tools/perf/util/parse-events.c | |
parent | 9059b284caecb628fac826c2c5cc8ee85708eec1 (diff) | |
parent | bbbe6bf6037d77816c4a19aaf35f4cecf662b49a (diff) |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
User visible changes:
- Enhance the error reporting of tracepoint event parsing, e.g.:
$ oldperf record -e sched:sched_switc usleep 1
event syntax error: 'sched:sched_switc'
\___ unknown tracepoint
Run 'perf list' for a list of valid events
Now we get the much nicer:
$ perf record -e sched:sched_switc ls
event syntax error: 'sched:sched_switc'
\___ can't access trace events
Error: No permissions to read /sys/kernel/debug/tracing/events/sched/sched_switc
Hint: Try 'sudo mount -o remount,mode=755 /sys/kernel/debug'
And after we have those mount point permissions fixed:
$ perf record -e sched:sched_switc ls
event syntax error: 'sched:sched_switc'
\___ unknown tracepoint
Error: File /sys/kernel/debug/tracing/events/sched/sched_switc not found.
Hint: Perhaps this kernel misses some CONFIG_ setting to enable this feature?.
Now its just a matter of using what git uses to suggest alternatives when we
make a typo, i.e. that it is just an 'h' missing :-)
I.e. basically now the event parsing routing uses the strerror_open()
routines introduced by and used in 'perf trace' work. (Jiri Olsa)
Infrastructure changes:
- Export init/exit_probe_symbol_maps() from 'perf probe' for use in eBPF.
(Namhyung Kim)
- Free perf_probe_event in cleanup_perf_probe_events(). (Namhyung Kim)
- regs_query_register_offset() infrastructure + implementation for x86.
First user will be the perf/eBPF code. (Wang Nan)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/util/parse-events.c')
-rw-r--r-- | tools/perf/util/parse-events.c | 66 |
1 files changed, 50 insertions, 16 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 3840176642f8..d3fb90be6216 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #include <linux/hw_breakpoint.h> | 1 | #include <linux/hw_breakpoint.h> |
2 | #include <linux/err.h> | ||
2 | #include "util.h" | 3 | #include "util.h" |
3 | #include "../perf.h" | 4 | #include "../perf.h" |
4 | #include "evlist.h" | 5 | #include "evlist.h" |
@@ -386,22 +387,52 @@ int parse_events_add_cache(struct list_head *list, int *idx, | |||
386 | return add_event(list, idx, &attr, name, NULL); | 387 | return add_event(list, idx, &attr, name, NULL); |
387 | } | 388 | } |
388 | 389 | ||
390 | static void tracepoint_error(struct parse_events_error *error, int err, | ||
391 | char *sys, char *name) | ||
392 | { | ||
393 | char help[BUFSIZ]; | ||
394 | |||
395 | /* | ||
396 | * We get error directly from syscall errno ( > 0), | ||
397 | * or from encoded pointer's error ( < 0). | ||
398 | */ | ||
399 | err = abs(err); | ||
400 | |||
401 | switch (err) { | ||
402 | case EACCES: | ||
403 | error->str = strdup("can't access trace events"); | ||
404 | break; | ||
405 | case ENOENT: | ||
406 | error->str = strdup("unknown tracepoint"); | ||
407 | break; | ||
408 | default: | ||
409 | error->str = strdup("failed to add tracepoint"); | ||
410 | break; | ||
411 | } | ||
412 | |||
413 | tracing_path__strerror_open_tp(err, help, sizeof(help), sys, name); | ||
414 | error->help = strdup(help); | ||
415 | } | ||
416 | |||
389 | static int add_tracepoint(struct list_head *list, int *idx, | 417 | static int add_tracepoint(struct list_head *list, int *idx, |
390 | char *sys_name, char *evt_name) | 418 | char *sys_name, char *evt_name, |
419 | struct parse_events_error *error __maybe_unused) | ||
391 | { | 420 | { |
392 | struct perf_evsel *evsel; | 421 | struct perf_evsel *evsel; |
393 | 422 | ||
394 | evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++); | 423 | evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++); |
395 | if (!evsel) | 424 | if (IS_ERR(evsel)) { |
396 | return -ENOMEM; | 425 | tracepoint_error(error, PTR_ERR(evsel), sys_name, evt_name); |
426 | return PTR_ERR(evsel); | ||
427 | } | ||
397 | 428 | ||
398 | list_add_tail(&evsel->node, list); | 429 | list_add_tail(&evsel->node, list); |
399 | |||
400 | return 0; | 430 | return 0; |
401 | } | 431 | } |
402 | 432 | ||
403 | static int add_tracepoint_multi_event(struct list_head *list, int *idx, | 433 | static int add_tracepoint_multi_event(struct list_head *list, int *idx, |
404 | char *sys_name, char *evt_name) | 434 | char *sys_name, char *evt_name, |
435 | struct parse_events_error *error) | ||
405 | { | 436 | { |
406 | char evt_path[MAXPATHLEN]; | 437 | char evt_path[MAXPATHLEN]; |
407 | struct dirent *evt_ent; | 438 | struct dirent *evt_ent; |
@@ -411,7 +442,7 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx, | |||
411 | snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name); | 442 | snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name); |
412 | evt_dir = opendir(evt_path); | 443 | evt_dir = opendir(evt_path); |
413 | if (!evt_dir) { | 444 | if (!evt_dir) { |
414 | perror("Can't open event dir"); | 445 | tracepoint_error(error, errno, sys_name, evt_name); |
415 | return -1; | 446 | return -1; |
416 | } | 447 | } |
417 | 448 | ||
@@ -425,7 +456,7 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx, | |||
425 | if (!strglobmatch(evt_ent->d_name, evt_name)) | 456 | if (!strglobmatch(evt_ent->d_name, evt_name)) |
426 | continue; | 457 | continue; |
427 | 458 | ||
428 | ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name); | 459 | ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name, error); |
429 | } | 460 | } |
430 | 461 | ||
431 | closedir(evt_dir); | 462 | closedir(evt_dir); |
@@ -433,15 +464,17 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx, | |||
433 | } | 464 | } |
434 | 465 | ||
435 | static int add_tracepoint_event(struct list_head *list, int *idx, | 466 | static int add_tracepoint_event(struct list_head *list, int *idx, |
436 | char *sys_name, char *evt_name) | 467 | char *sys_name, char *evt_name, |
468 | struct parse_events_error *error) | ||
437 | { | 469 | { |
438 | return strpbrk(evt_name, "*?") ? | 470 | return strpbrk(evt_name, "*?") ? |
439 | add_tracepoint_multi_event(list, idx, sys_name, evt_name) : | 471 | add_tracepoint_multi_event(list, idx, sys_name, evt_name, error) : |
440 | add_tracepoint(list, idx, sys_name, evt_name); | 472 | add_tracepoint(list, idx, sys_name, evt_name, error); |
441 | } | 473 | } |
442 | 474 | ||
443 | static int add_tracepoint_multi_sys(struct list_head *list, int *idx, | 475 | static int add_tracepoint_multi_sys(struct list_head *list, int *idx, |
444 | char *sys_name, char *evt_name) | 476 | char *sys_name, char *evt_name, |
477 | struct parse_events_error *error) | ||
445 | { | 478 | { |
446 | struct dirent *events_ent; | 479 | struct dirent *events_ent; |
447 | DIR *events_dir; | 480 | DIR *events_dir; |
@@ -449,7 +482,7 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx, | |||
449 | 482 | ||
450 | events_dir = opendir(tracing_events_path); | 483 | events_dir = opendir(tracing_events_path); |
451 | if (!events_dir) { | 484 | if (!events_dir) { |
452 | perror("Can't open event dir"); | 485 | tracepoint_error(error, errno, sys_name, evt_name); |
453 | return -1; | 486 | return -1; |
454 | } | 487 | } |
455 | 488 | ||
@@ -465,7 +498,7 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx, | |||
465 | continue; | 498 | continue; |
466 | 499 | ||
467 | ret = add_tracepoint_event(list, idx, events_ent->d_name, | 500 | ret = add_tracepoint_event(list, idx, events_ent->d_name, |
468 | evt_name); | 501 | evt_name, error); |
469 | } | 502 | } |
470 | 503 | ||
471 | closedir(events_dir); | 504 | closedir(events_dir); |
@@ -473,12 +506,13 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx, | |||
473 | } | 506 | } |
474 | 507 | ||
475 | int parse_events_add_tracepoint(struct list_head *list, int *idx, | 508 | int parse_events_add_tracepoint(struct list_head *list, int *idx, |
476 | char *sys, char *event) | 509 | char *sys, char *event, |
510 | struct parse_events_error *error) | ||
477 | { | 511 | { |
478 | if (strpbrk(sys, "*?")) | 512 | if (strpbrk(sys, "*?")) |
479 | return add_tracepoint_multi_sys(list, idx, sys, event); | 513 | return add_tracepoint_multi_sys(list, idx, sys, event, error); |
480 | else | 514 | else |
481 | return add_tracepoint_event(list, idx, sys, event); | 515 | return add_tracepoint_event(list, idx, sys, event, error); |
482 | } | 516 | } |
483 | 517 | ||
484 | static int | 518 | static int |