aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorJason Baron <jbaron@redhat.com>2009-07-21 14:16:29 -0400
committerPeter Zijlstra <a.p.zijlstra@chello.nl>2009-07-22 12:05:57 -0400
commit5beeded123c5befa21f1c6e16219f2a3eb7dd197 (patch)
tree4ac812126910994516300c53171c7267b97f6f5d /tools/perf
parentf6bdafef2ab911f03321fa83d8da1df99878009e (diff)
perf_counter: Detect debugfs location
If "/sys/kernel/debug" is not a debugfs mount point, search for the debugfs filesystem in /proc/mounts, but also allows the user to specify '--debugfs-dir=blah' or set the environment variable: 'PERF_DEBUGFS_DIR' Signed-off-by: Jason Baron <jbaron@redhat.com> [ also made it probe "/debug" by default ] Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <20090721181629.GA3094@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/perf.c77
-rw-r--r--tools/perf/util/cache.h1
-rw-r--r--tools/perf/util/parse-events.c33
-rw-r--r--tools/perf/util/parse-events.h5
-rw-r--r--tools/perf/util/string.h3
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
16const char perf_usage_string[] = 18const 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
30static char debugfs_mntpt[MAXPATHLEN];
31
28static int pager_command_config(const char *var, const char *value, void *data) 32static 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
63static 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
59static int handle_options(const char*** argv, int* argc, int* envchanged) 72static 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" */
380static 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
350int main(int argc, const char **argv) 423int 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
22typedef int (*config_fn_t)(const char *, const char *, void *); 23typedef int (*config_fn_t)(const char *, const char *, void *);
23extern int perf_default_config(const char *, const char *, void *); 24extern 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
9extern char *strcasestr(const char *haystack, const char *needle); 10extern char *strcasestr(const char *haystack, const char *needle);
10 11
@@ -12,8 +13,6 @@ int nr_counters;
12 13
13struct perf_counter_attr attrs[MAX_COUNTERS]; 14struct perf_counter_attr attrs[MAX_COUNTERS];
14 15
15static char default_debugfs_path[] = "/sys/kernel/debug/tracing/events";
16
17struct event_symbol { 16struct 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
23char 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
133static int valid_debugfs_mount(void) 134int 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
6struct option;
7
6extern int nr_counters; 8extern int nr_counters;
7 9
8extern struct perf_counter_attr attrs[MAX_COUNTERS]; 10extern 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
16extern void print_events(void); 18extern void print_events(void);
17 19
20extern char debugfs_path[];
21extern 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
6int hex2u64(const char *ptr, u64 *val); 6int hex2u64(const char *ptr, u64 *val);
7 7
8#define _STR(x) #x
9#define STR(x) _STR(x)
10
8#endif 11#endif