diff options
| -rw-r--r-- | tools/perf/perf.c | 77 | ||||
| -rw-r--r-- | tools/perf/util/cache.h | 1 | ||||
| -rw-r--r-- | tools/perf/util/parse-events.c | 33 | ||||
| -rw-r--r-- | tools/perf/util/parse-events.h | 5 | ||||
| -rw-r--r-- | tools/perf/util/string.h | 3 |
5 files changed, 102 insertions, 17 deletions
diff --git a/tools/perf/perf.c b/tools/perf/perf.c index c5656784c61d..31982ad064b4 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c | |||
| @@ -12,6 +12,8 @@ | |||
| 12 | #include "util/cache.h" | 12 | #include "util/cache.h" |
| 13 | #include "util/quote.h" | 13 | #include "util/quote.h" |
| 14 | #include "util/run-command.h" | 14 | #include "util/run-command.h" |
| 15 | #include "util/parse-events.h" | ||
| 16 | #include "util/string.h" | ||
| 15 | 17 | ||
| 16 | const char perf_usage_string[] = | 18 | const char perf_usage_string[] = |
| 17 | "perf [--version] [--help] COMMAND [ARGS]"; | 19 | "perf [--version] [--help] COMMAND [ARGS]"; |
| @@ -25,6 +27,8 @@ struct pager_config { | |||
| 25 | int val; | 27 | int val; |
| 26 | }; | 28 | }; |
| 27 | 29 | ||
| 30 | static char debugfs_mntpt[MAXPATHLEN]; | ||
| 31 | |||
| 28 | static int pager_command_config(const char *var, const char *value, void *data) | 32 | static int pager_command_config(const char *var, const char *value, void *data) |
| 29 | { | 33 | { |
| 30 | struct pager_config *c = data; | 34 | struct pager_config *c = data; |
| @@ -56,6 +60,15 @@ static void commit_pager_choice(void) { | |||
| 56 | } | 60 | } |
| 57 | } | 61 | } |
| 58 | 62 | ||
| 63 | static void set_debugfs_path(void) | ||
| 64 | { | ||
| 65 | char *path; | ||
| 66 | |||
| 67 | path = getenv(PERF_DEBUGFS_ENVIRONMENT); | ||
| 68 | snprintf(debugfs_path, MAXPATHLEN, "%s/%s", path ?: debugfs_mntpt, | ||
| 69 | "tracing/events"); | ||
| 70 | } | ||
| 71 | |||
| 59 | static int handle_options(const char*** argv, int* argc, int* envchanged) | 72 | static int handle_options(const char*** argv, int* argc, int* envchanged) |
| 60 | { | 73 | { |
| 61 | int handled = 0; | 74 | int handled = 0; |
| @@ -122,6 +135,22 @@ static int handle_options(const char*** argv, int* argc, int* envchanged) | |||
| 122 | setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + 12, 1); | 135 | setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + 12, 1); |
| 123 | if (envchanged) | 136 | if (envchanged) |
| 124 | *envchanged = 1; | 137 | *envchanged = 1; |
| 138 | } else if (!strcmp(cmd, "--debugfs-dir")) { | ||
| 139 | if (*argc < 2) { | ||
| 140 | fprintf(stderr, "No directory given for --debugfs-dir.\n"); | ||
| 141 | usage(perf_usage_string); | ||
| 142 | } | ||
| 143 | strncpy(debugfs_mntpt, (*argv)[1], MAXPATHLEN); | ||
| 144 | debugfs_mntpt[MAXPATHLEN - 1] = '\0'; | ||
| 145 | if (envchanged) | ||
| 146 | *envchanged = 1; | ||
| 147 | (*argv)++; | ||
| 148 | (*argc)--; | ||
| 149 | } else if (!prefixcmp(cmd, "--debugfs-dir=")) { | ||
| 150 | strncpy(debugfs_mntpt, cmd + 14, MAXPATHLEN); | ||
| 151 | debugfs_mntpt[MAXPATHLEN - 1] = '\0'; | ||
| 152 | if (envchanged) | ||
| 153 | *envchanged = 1; | ||
| 125 | } else { | 154 | } else { |
| 126 | fprintf(stderr, "Unknown option: %s\n", cmd); | 155 | fprintf(stderr, "Unknown option: %s\n", cmd); |
| 127 | usage(perf_usage_string); | 156 | usage(perf_usage_string); |
| @@ -228,6 +257,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) | |||
| 228 | if (use_pager == -1 && p->option & USE_PAGER) | 257 | if (use_pager == -1 && p->option & USE_PAGER) |
| 229 | use_pager = 1; | 258 | use_pager = 1; |
| 230 | commit_pager_choice(); | 259 | commit_pager_choice(); |
| 260 | set_debugfs_path(); | ||
| 231 | 261 | ||
| 232 | status = p->fn(argc, argv, prefix); | 262 | status = p->fn(argc, argv, prefix); |
| 233 | if (status) | 263 | if (status) |
| @@ -346,6 +376,49 @@ static int run_argv(int *argcp, const char ***argv) | |||
| 346 | return done_alias; | 376 | return done_alias; |
| 347 | } | 377 | } |
| 348 | 378 | ||
| 379 | /* mini /proc/mounts parser: searching for "^blah /mount/point debugfs" */ | ||
| 380 | static void get_debugfs_mntpt(void) | ||
| 381 | { | ||
| 382 | FILE *file; | ||
| 383 | char fs_type[100]; | ||
| 384 | char debugfs[MAXPATHLEN]; | ||
| 385 | |||
| 386 | /* | ||
| 387 | * try the standard location | ||
| 388 | */ | ||
| 389 | if (valid_debugfs_mount("/sys/kernel/debug/") == 0) { | ||
| 390 | strcpy(debugfs_mntpt, "/sys/kernel/debug/"); | ||
| 391 | return; | ||
| 392 | } | ||
| 393 | |||
| 394 | /* | ||
| 395 | * try the sane location | ||
| 396 | */ | ||
| 397 | if (valid_debugfs_mount("/debug/") == 0) { | ||
| 398 | strcpy(debugfs_mntpt, "/debug/"); | ||
| 399 | return; | ||
| 400 | } | ||
| 401 | |||
| 402 | /* | ||
| 403 | * give up and parse /proc/mounts | ||
| 404 | */ | ||
| 405 | file = fopen("/proc/mounts", "r"); | ||
| 406 | if (file == NULL) | ||
| 407 | return; | ||
| 408 | |||
| 409 | while (fscanf(file, "%*s %" | ||
| 410 | STR(MAXPATHLEN) | ||
| 411 | "s %99s %*s %*d %*d\n", | ||
| 412 | debugfs, fs_type) == 2) { | ||
| 413 | if (strcmp(fs_type, "debugfs") == 0) | ||
| 414 | break; | ||
| 415 | } | ||
| 416 | fclose(file); | ||
| 417 | if (strcmp(fs_type, "debugfs") == 0) { | ||
| 418 | strncpy(debugfs_mntpt, debugfs, MAXPATHLEN); | ||
| 419 | debugfs_mntpt[MAXPATHLEN - 1] = '\0'; | ||
| 420 | } | ||
| 421 | } | ||
| 349 | 422 | ||
| 350 | int main(int argc, const char **argv) | 423 | int main(int argc, const char **argv) |
| 351 | { | 424 | { |
| @@ -354,7 +427,8 @@ int main(int argc, const char **argv) | |||
| 354 | cmd = perf_extract_argv0_path(argv[0]); | 427 | cmd = perf_extract_argv0_path(argv[0]); |
| 355 | if (!cmd) | 428 | if (!cmd) |
| 356 | cmd = "perf-help"; | 429 | cmd = "perf-help"; |
| 357 | 430 | /* get debugfs mount point from /proc/mounts */ | |
| 431 | get_debugfs_mntpt(); | ||
| 358 | /* | 432 | /* |
| 359 | * "perf-xxxx" is the same as "perf xxxx", but we obviously: | 433 | * "perf-xxxx" is the same as "perf xxxx", but we obviously: |
| 360 | * | 434 | * |
| @@ -377,6 +451,7 @@ int main(int argc, const char **argv) | |||
| 377 | argc--; | 451 | argc--; |
| 378 | handle_options(&argv, &argc, NULL); | 452 | handle_options(&argv, &argc, NULL); |
| 379 | commit_pager_choice(); | 453 | commit_pager_choice(); |
| 454 | set_debugfs_path(); | ||
| 380 | if (argc > 0) { | 455 | if (argc > 0) { |
| 381 | if (!prefixcmp(argv[0], "--")) | 456 | if (!prefixcmp(argv[0], "--")) |
| 382 | argv[0] += 2; | 457 | argv[0] += 2; |
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index 161d5f413e28..4b50c412b9c5 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #define PERFATTRIBUTES_FILE ".perfattributes" | 18 | #define PERFATTRIBUTES_FILE ".perfattributes" |
| 19 | #define INFOATTRIBUTES_FILE "info/attributes" | 19 | #define INFOATTRIBUTES_FILE "info/attributes" |
| 20 | #define ATTRIBUTE_MACRO_PREFIX "[attr]" | 20 | #define ATTRIBUTE_MACRO_PREFIX "[attr]" |
| 21 | #define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR" | ||
| 21 | 22 | ||
| 22 | typedef int (*config_fn_t)(const char *, const char *, void *); | 23 | typedef int (*config_fn_t)(const char *, const char *, void *); |
| 23 | extern int perf_default_config(const char *, const char *, void *); | 24 | extern int perf_default_config(const char *, const char *, void *); |
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 5a3cd3a34af1..7bdad8df22a6 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include "parse-events.h" | 5 | #include "parse-events.h" |
| 6 | #include "exec_cmd.h" | 6 | #include "exec_cmd.h" |
| 7 | #include "string.h" | 7 | #include "string.h" |
| 8 | #include "cache.h" | ||
| 8 | 9 | ||
| 9 | extern char *strcasestr(const char *haystack, const char *needle); | 10 | extern char *strcasestr(const char *haystack, const char *needle); |
| 10 | 11 | ||
| @@ -12,8 +13,6 @@ int nr_counters; | |||
| 12 | 13 | ||
| 13 | struct perf_counter_attr attrs[MAX_COUNTERS]; | 14 | struct perf_counter_attr attrs[MAX_COUNTERS]; |
| 14 | 15 | ||
| 15 | static char default_debugfs_path[] = "/sys/kernel/debug/tracing/events"; | ||
| 16 | |||
| 17 | struct event_symbol { | 16 | struct event_symbol { |
| 18 | u8 type; | 17 | u8 type; |
| 19 | u64 config; | 18 | u64 config; |
| @@ -21,6 +20,8 @@ struct event_symbol { | |||
| 21 | char *alias; | 20 | char *alias; |
| 22 | }; | 21 | }; |
| 23 | 22 | ||
| 23 | char debugfs_path[MAXPATHLEN]; | ||
| 24 | |||
| 24 | #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x | 25 | #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x |
| 25 | #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x | 26 | #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x |
| 26 | 27 | ||
| @@ -114,27 +115,27 @@ static unsigned long hw_cache_stat[C(MAX)] = { | |||
| 114 | 115 | ||
| 115 | #define for_each_subsystem(sys_dir, sys_dirent, sys_next, file, st) \ | 116 | #define for_each_subsystem(sys_dir, sys_dirent, sys_next, file, st) \ |
| 116 | while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \ | 117 | while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \ |
| 117 | if (snprintf(file, MAXPATHLEN, "%s/%s", default_debugfs_path, \ | 118 | if (snprintf(file, MAXPATHLEN, "%s/%s", debugfs_path, \ |
| 118 | sys_dirent.d_name) && \ | 119 | sys_dirent.d_name) && \ |
| 119 | (!stat(file, &st)) && (S_ISDIR(st.st_mode)) && \ | 120 | (!stat(file, &st)) && (S_ISDIR(st.st_mode)) && \ |
| 120 | (strcmp(sys_dirent.d_name, ".")) && \ | 121 | (strcmp(sys_dirent.d_name, ".")) && \ |
| 121 | (strcmp(sys_dirent.d_name, ".."))) | 122 | (strcmp(sys_dirent.d_name, ".."))) |
| 122 | 123 | ||
| 123 | #define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, file, st) \ | 124 | #define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, file, st) \ |
| 124 | while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \ | 125 | while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \ |
| 125 | if (snprintf(file, MAXPATHLEN, "%s/%s/%s", default_debugfs_path, \ | 126 | if (snprintf(file, MAXPATHLEN, "%s/%s/%s", debugfs_path, \ |
| 126 | sys_dirent.d_name, evt_dirent.d_name) && \ | 127 | sys_dirent.d_name, evt_dirent.d_name) && \ |
| 127 | (!stat(file, &st)) && (S_ISDIR(st.st_mode)) && \ | 128 | (!stat(file, &st)) && (S_ISDIR(st.st_mode)) && \ |
| 128 | (strcmp(evt_dirent.d_name, ".")) && \ | 129 | (strcmp(evt_dirent.d_name, ".")) && \ |
| 129 | (strcmp(evt_dirent.d_name, ".."))) | 130 | (strcmp(evt_dirent.d_name, ".."))) |
| 130 | 131 | ||
| 131 | #define MAX_EVENT_LENGTH 30 | 132 | #define MAX_EVENT_LENGTH 30 |
| 132 | 133 | ||
| 133 | static int valid_debugfs_mount(void) | 134 | int valid_debugfs_mount(const char *debugfs) |
| 134 | { | 135 | { |
| 135 | struct statfs st_fs; | 136 | struct statfs st_fs; |
| 136 | 137 | ||
| 137 | if (statfs(default_debugfs_path, &st_fs) < 0) | 138 | if (statfs(debugfs, &st_fs) < 0) |
| 138 | return -ENOENT; | 139 | return -ENOENT; |
| 139 | else if (st_fs.f_type != (long) DEBUGFS_MAGIC) | 140 | else if (st_fs.f_type != (long) DEBUGFS_MAGIC) |
| 140 | return -ENOENT; | 141 | return -ENOENT; |
| @@ -152,10 +153,10 @@ static char *tracepoint_id_to_name(u64 config) | |||
| 152 | u64 id; | 153 | u64 id; |
| 153 | char evt_path[MAXPATHLEN]; | 154 | char evt_path[MAXPATHLEN]; |
| 154 | 155 | ||
| 155 | if (valid_debugfs_mount()) | 156 | if (valid_debugfs_mount(debugfs_path)) |
| 156 | return "unkown"; | 157 | return "unkown"; |
| 157 | 158 | ||
| 158 | sys_dir = opendir(default_debugfs_path); | 159 | sys_dir = opendir(debugfs_path); |
| 159 | if (!sys_dir) | 160 | if (!sys_dir) |
| 160 | goto cleanup; | 161 | goto cleanup; |
| 161 | 162 | ||
| @@ -166,7 +167,7 @@ static char *tracepoint_id_to_name(u64 config) | |||
| 166 | for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, | 167 | for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, |
| 167 | evt_path, st) { | 168 | evt_path, st) { |
| 168 | snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", | 169 | snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", |
| 169 | default_debugfs_path, sys_dirent.d_name, | 170 | debugfs_path, sys_dirent.d_name, |
| 170 | evt_dirent.d_name); | 171 | evt_dirent.d_name); |
| 171 | fd = open(evt_path, O_RDONLY); | 172 | fd = open(evt_path, O_RDONLY); |
| 172 | if (fd < 0) | 173 | if (fd < 0) |
| @@ -363,7 +364,7 @@ static int parse_tracepoint_event(const char **strp, | |||
| 363 | u64 id; | 364 | u64 id; |
| 364 | char evt_path[MAXPATHLEN]; | 365 | char evt_path[MAXPATHLEN]; |
| 365 | 366 | ||
| 366 | if (valid_debugfs_mount()) | 367 | if (valid_debugfs_mount(debugfs_path)) |
| 367 | return 0; | 368 | return 0; |
| 368 | 369 | ||
| 369 | evt_name = strchr(*strp, ':'); | 370 | evt_name = strchr(*strp, ':'); |
| @@ -381,8 +382,8 @@ static int parse_tracepoint_event(const char **strp, | |||
| 381 | if (evt_length >= MAX_EVENT_LENGTH) | 382 | if (evt_length >= MAX_EVENT_LENGTH) |
| 382 | return 0; | 383 | return 0; |
| 383 | 384 | ||
| 384 | snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", default_debugfs_path, | 385 | snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, |
| 385 | sys_name, evt_name); | 386 | sys_name, evt_name); |
| 386 | fd = open(evt_path, O_RDONLY); | 387 | fd = open(evt_path, O_RDONLY); |
| 387 | if (fd < 0) | 388 | if (fd < 0) |
| 388 | return 0; | 389 | return 0; |
| @@ -568,10 +569,10 @@ static void print_tracepoint_events(void) | |||
| 568 | struct stat st; | 569 | struct stat st; |
| 569 | char evt_path[MAXPATHLEN]; | 570 | char evt_path[MAXPATHLEN]; |
| 570 | 571 | ||
| 571 | if (valid_debugfs_mount()) | 572 | if (valid_debugfs_mount(debugfs_path)) |
| 572 | return; | 573 | return; |
| 573 | 574 | ||
| 574 | sys_dir = opendir(default_debugfs_path); | 575 | sys_dir = opendir(debugfs_path); |
| 575 | if (!sys_dir) | 576 | if (!sys_dir) |
| 576 | goto cleanup; | 577 | goto cleanup; |
| 577 | 578 | ||
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index e3d552908e60..1ea5d09b6eb1 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h | |||
| @@ -3,6 +3,8 @@ | |||
| 3 | * Parse symbolic events/counts passed in as options: | 3 | * Parse symbolic events/counts passed in as options: |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | struct option; | ||
| 7 | |||
| 6 | extern int nr_counters; | 8 | extern int nr_counters; |
| 7 | 9 | ||
| 8 | extern struct perf_counter_attr attrs[MAX_COUNTERS]; | 10 | extern struct perf_counter_attr attrs[MAX_COUNTERS]; |
| @@ -15,3 +17,6 @@ extern int parse_events(const struct option *opt, const char *str, int unset); | |||
| 15 | 17 | ||
| 16 | extern void print_events(void); | 18 | extern void print_events(void); |
| 17 | 19 | ||
| 20 | extern char debugfs_path[]; | ||
| 21 | extern int valid_debugfs_mount(const char *debugfs); | ||
| 22 | |||
diff --git a/tools/perf/util/string.h b/tools/perf/util/string.h index 3dca2f654cd0..bf39dfadfd24 100644 --- a/tools/perf/util/string.h +++ b/tools/perf/util/string.h | |||
| @@ -5,4 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | int hex2u64(const char *ptr, u64 *val); | 6 | int hex2u64(const char *ptr, u64 *val); |
| 7 | 7 | ||
| 8 | #define _STR(x) #x | ||
| 9 | #define STR(x) _STR(x) | ||
| 10 | |||
| 8 | #endif | 11 | #endif |
