[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20090721181629.GA3094@redhat.com>
Date: Tue, 21 Jul 2009 14:16:29 -0400
From: Jason Baron <jbaron@...hat.com>
To: Ray Lee <ray-lk@...rabbit.org>, zab@...bo.net
Cc: Steven Rostedt <rostedt@...dmis.org>, mingo@...e.hu,
linux-kernel@...r.kernel.org, paulus@...ba.org,
a.p.zijlstra@...llo.nl, fweisbec@...il.com
Subject: Re: [PATCH 2/2] perf_counter: detect debugfs location
On Tue, Jul 21, 2009 at 10:01:40AM -0700, Ray Lee wrote:
> On Tue, Jul 21, 2009 at 9:44 AM, Steven Rostedt<rostedt@...dmis.org> wrote:
> >
> > On Tue, 21 Jul 2009, Ray Lee wrote:
> >
> >> On Tue, Jul 21, 2009 at 9:20 AM, Jason Baron <jbaron@...hat.com> wrote:
> >> >
> >> > Search for the debugfs filesystem in /proc/mounts, but also allows the user to
> >> > specify '--debugfs-dir=blah' or set the environment variable: 'PERF_DIR_DEBUGFS'
> >>
> >> > -static char default_debugfs_path[] = "/sys/kernel/debug/tracing/events";
> >>
> >> There are server systems out there that run with thousands of mounts.
> >> It would be kinder to the users of those systems (ie, faster perf
> >> startup) if you only went rooting around /proc/mounts if opening the
> >> default location failed.
> >
> > Well, those that have thousand of mounts could probably get away with
> > setting PERF_DIR_DEBUGFS in /etc/profile.
>
> The intent of the patch is obviously to try to Do The Right Thing by
> default. I think that's great. I just think it should DT(fast and)RT
> instead.
>
> > But, a simple stat("/sys/kernel/debug/tracing") should be easy enough.
>
> <nod>
agreed, that would be better. I'm also renaming the environment variable
PERF_DIR_DEBUGFS -> PERF_DEBUGFS_DIR, as Zach Brown pointed out.
Re-spun path below.
thanks,
-Jason
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@...hat.com>
---
tools/perf/perf.c | 63 +++++++++++++++++++++++++++++++++++++++-
tools/perf/util/cache.h | 1 +
tools/perf/util/parse-events.c | 33 +++++++++++----------
tools/perf/util/parse-events.h | 5 +++
tools/perf/util/string.h | 3 ++
5 files changed, 88 insertions(+), 17 deletions(-)
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index c565678..6d5b121 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -12,6 +12,8 @@
#include "util/cache.h"
#include "util/quote.h"
#include "util/run-command.h"
+#include "util/parse-events.h"
+#include "util/string.h"
const char perf_usage_string[] =
"perf [--version] [--help] COMMAND [ARGS]";
@@ -25,6 +27,8 @@ struct pager_config {
int val;
};
+static char debugfs_mntpt[MAXPATHLEN];
+
static int pager_command_config(const char *var, const char *value, void *data)
{
struct pager_config *c = data;
@@ -56,6 +60,15 @@ static void commit_pager_choice(void) {
}
}
+static void set_debugfs_path(void)
+{
+ char *path;
+
+ path = getenv(PERF_DEBUGFS_ENVIRONMENT);
+ snprintf(debugfs_path, MAXPATHLEN, "%s/%s", path ?: debugfs_mntpt,
+ "tracing/events");
+}
+
static int handle_options(const char*** argv, int* argc, int* envchanged)
{
int handled = 0;
@@ -122,6 +135,22 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + 12, 1);
if (envchanged)
*envchanged = 1;
+ } else if (!strcmp(cmd, "--debugfs-dir")) {
+ if (*argc < 2) {
+ fprintf(stderr, "No directory given for --debugfs-dir.\n");
+ usage(perf_usage_string);
+ }
+ strncpy(debugfs_mntpt, (*argv)[1], MAXPATHLEN);
+ debugfs_mntpt[MAXPATHLEN - 1] = '\0';
+ if (envchanged)
+ *envchanged = 1;
+ (*argv)++;
+ (*argc)--;
+ } else if (!prefixcmp(cmd, "--debugfs-dir=")) {
+ strncpy(debugfs_mntpt, cmd + 14, MAXPATHLEN);
+ debugfs_mntpt[MAXPATHLEN - 1] = '\0';
+ if (envchanged)
+ *envchanged = 1;
} else {
fprintf(stderr, "Unknown option: %s\n", cmd);
usage(perf_usage_string);
@@ -228,6 +257,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
if (use_pager == -1 && p->option & USE_PAGER)
use_pager = 1;
commit_pager_choice();
+ set_debugfs_path();
status = p->fn(argc, argv, prefix);
if (status)
@@ -346,6 +376,35 @@ static int run_argv(int *argcp, const char ***argv)
return done_alias;
}
+/* mini /proc/mounts parser: searching for "^blah /mount/point debugfs" */
+static void get_debugfs_mntpt(void)
+{
+ FILE *file;
+ char fs_type[100];
+ char debugfs[MAXPATHLEN];
+
+ if (valid_debugfs_mount("/sys/kernel/debug/") == 0) {
+ strcpy(debugfs_mntpt, "/sys/kernel/debug/");
+ return;
+ }
+
+ file = fopen("/proc/mounts", "r");
+ if (file == NULL)
+ return;
+
+ while (fscanf(file, "%*s %"
+ STR(MAXPATHLEN)
+ "s %99s %*s %*d %*d\n",
+ debugfs, fs_type) == 2) {
+ if (strcmp(fs_type, "debugfs") == 0)
+ break;
+ }
+ fclose(file);
+ if (strcmp(fs_type, "debugfs") == 0) {
+ strncpy(debugfs_mntpt, debugfs, MAXPATHLEN);
+ debugfs_mntpt[MAXPATHLEN - 1] = '\0';
+ }
+}
int main(int argc, const char **argv)
{
@@ -354,7 +413,8 @@ int main(int argc, const char **argv)
cmd = perf_extract_argv0_path(argv[0]);
if (!cmd)
cmd = "perf-help";
-
+ /* get debugfs mount point from /proc/mounts */
+ get_debugfs_mntpt();
/*
* "perf-xxxx" is the same as "perf xxxx", but we obviously:
*
@@ -377,6 +437,7 @@ int main(int argc, const char **argv)
argc--;
handle_options(&argv, &argc, NULL);
commit_pager_choice();
+ set_debugfs_path();
if (argc > 0) {
if (!prefixcmp(argv[0], "--"))
argv[0] += 2;
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 161d5f4..4b50c41 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -18,6 +18,7 @@
#define PERFATTRIBUTES_FILE ".perfattributes"
#define INFOATTRIBUTES_FILE "info/attributes"
#define ATTRIBUTE_MACRO_PREFIX "[attr]"
+#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
typedef int (*config_fn_t)(const char *, const char *, void *);
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 5a3cd3a..7bdad8d 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -5,6 +5,7 @@
#include "parse-events.h"
#include "exec_cmd.h"
#include "string.h"
+#include "cache.h"
extern char *strcasestr(const char *haystack, const char *needle);
@@ -12,8 +13,6 @@ int nr_counters;
struct perf_counter_attr attrs[MAX_COUNTERS];
-static char default_debugfs_path[] = "/sys/kernel/debug/tracing/events";
-
struct event_symbol {
u8 type;
u64 config;
@@ -21,6 +20,8 @@ struct event_symbol {
char *alias;
};
+char debugfs_path[MAXPATHLEN];
+
#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
@@ -114,27 +115,27 @@ static unsigned long hw_cache_stat[C(MAX)] = {
#define for_each_subsystem(sys_dir, sys_dirent, sys_next, file, st) \
while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \
- if (snprintf(file, MAXPATHLEN, "%s/%s", default_debugfs_path, \
- sys_dirent.d_name) && \
+ if (snprintf(file, MAXPATHLEN, "%s/%s", debugfs_path, \
+ sys_dirent.d_name) && \
(!stat(file, &st)) && (S_ISDIR(st.st_mode)) && \
(strcmp(sys_dirent.d_name, ".")) && \
(strcmp(sys_dirent.d_name, "..")))
#define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, file, st) \
while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \
- if (snprintf(file, MAXPATHLEN, "%s/%s/%s", default_debugfs_path, \
- sys_dirent.d_name, evt_dirent.d_name) && \
+ if (snprintf(file, MAXPATHLEN, "%s/%s/%s", debugfs_path, \
+ sys_dirent.d_name, evt_dirent.d_name) && \
(!stat(file, &st)) && (S_ISDIR(st.st_mode)) && \
(strcmp(evt_dirent.d_name, ".")) && \
(strcmp(evt_dirent.d_name, "..")))
#define MAX_EVENT_LENGTH 30
-static int valid_debugfs_mount(void)
+int valid_debugfs_mount(const char *debugfs)
{
struct statfs st_fs;
- if (statfs(default_debugfs_path, &st_fs) < 0)
+ if (statfs(debugfs, &st_fs) < 0)
return -ENOENT;
else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
return -ENOENT;
@@ -152,10 +153,10 @@ static char *tracepoint_id_to_name(u64 config)
u64 id;
char evt_path[MAXPATHLEN];
- if (valid_debugfs_mount())
+ if (valid_debugfs_mount(debugfs_path))
return "unkown";
- sys_dir = opendir(default_debugfs_path);
+ sys_dir = opendir(debugfs_path);
if (!sys_dir)
goto cleanup;
@@ -166,7 +167,7 @@ static char *tracepoint_id_to_name(u64 config)
for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next,
evt_path, st) {
snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id",
- default_debugfs_path, sys_dirent.d_name,
+ debugfs_path, sys_dirent.d_name,
evt_dirent.d_name);
fd = open(evt_path, O_RDONLY);
if (fd < 0)
@@ -363,7 +364,7 @@ static int parse_tracepoint_event(const char **strp,
u64 id;
char evt_path[MAXPATHLEN];
- if (valid_debugfs_mount())
+ if (valid_debugfs_mount(debugfs_path))
return 0;
evt_name = strchr(*strp, ':');
@@ -381,8 +382,8 @@ static int parse_tracepoint_event(const char **strp,
if (evt_length >= MAX_EVENT_LENGTH)
return 0;
- snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", default_debugfs_path,
- sys_name, evt_name);
+ snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
+ sys_name, evt_name);
fd = open(evt_path, O_RDONLY);
if (fd < 0)
return 0;
@@ -568,10 +569,10 @@ static void print_tracepoint_events(void)
struct stat st;
char evt_path[MAXPATHLEN];
- if (valid_debugfs_mount())
+ if (valid_debugfs_mount(debugfs_path))
return;
- sys_dir = opendir(default_debugfs_path);
+ sys_dir = opendir(debugfs_path);
if (!sys_dir)
goto cleanup;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index e3d5529..1ea5d09 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -3,6 +3,8 @@
* Parse symbolic events/counts passed in as options:
*/
+struct option;
+
extern int nr_counters;
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);
extern void print_events(void);
+extern char debugfs_path[];
+extern int valid_debugfs_mount(const char *debugfs);
+
diff --git a/tools/perf/util/string.h b/tools/perf/util/string.h
index 3dca2f6..bf39dfa 100644
--- a/tools/perf/util/string.h
+++ b/tools/perf/util/string.h
@@ -5,4 +5,7 @@
int hex2u64(const char *ptr, u64 *val);
+#define _STR(x) #x
+#define STR(x) _STR(x)
+
#endif
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists