Merge master.kernel.org:/home/rmk/linux-2.6-arm
[safe/jmp/linux-2.6] / tools / perf / builtin-probe.c
index bfc47ff..e4a4da3 100644 (file)
@@ -40,7 +40,6 @@
 #include "util/debug.h"
 #include "util/debugfs.h"
 #include "util/parse-options.h"
-#include "util/parse-events.h" /* For debugfs_path */
 #include "util/probe-finder.h"
 #include "util/probe-event.h"
 
@@ -55,47 +54,56 @@ static struct {
        struct perf_probe_event events[MAX_PROBES];
        struct strlist *dellist;
        struct line_range line_range;
+       int max_probe_points;
 } params;
 
 
 /* Parse an event definition. Note that any error must die. */
-static void parse_probe_event(const char *str)
+static int parse_probe_event(const char *str)
 {
        struct perf_probe_event *pev = &params.events[params.nevents];
+       int ret;
 
        pr_debug("probe-definition(%d): %s\n", params.nevents, str);
-       if (++params.nevents == MAX_PROBES)
-               die("Too many probes (> %d) are specified.", MAX_PROBES);
+       if (++params.nevents == MAX_PROBES) {
+               pr_err("Too many probes (> %d) were specified.", MAX_PROBES);
+               return -1;
+       }
 
        /* Parse a perf-probe command into event */
-       parse_perf_probe_command(str, pev);
-
+       ret = parse_perf_probe_command(str, pev);
        pr_debug("%d arguments\n", pev->nargs);
+
+       return ret;
 }
 
-static void parse_probe_event_argv(int argc, const char **argv)
+static int parse_probe_event_argv(int argc, const char **argv)
 {
-       int i, len;
+       int i, len, ret;
        char *buf;
 
        /* Bind up rest arguments */
        len = 0;
        for (i = 0; i < argc; i++)
                len += strlen(argv[i]) + 1;
-       buf = xzalloc(len + 1);
+       buf = zalloc(len + 1);
+       if (buf == NULL)
+               return -ENOMEM;
        len = 0;
        for (i = 0; i < argc; i++)
                len += sprintf(&buf[len], "%s ", argv[i]);
-       parse_probe_event(buf);
+       ret = parse_probe_event(buf);
        free(buf);
+       return ret;
 }
 
 static int opt_add_probe_event(const struct option *opt __used,
                              const char *str, int unset __used)
 {
        if (str)
-               parse_probe_event(str);
-       return 0;
+               return parse_probe_event(str);
+       else
+               return 0;
 }
 
 static int opt_del_probe_event(const struct option *opt __used,
@@ -113,11 +121,14 @@ static int opt_del_probe_event(const struct option *opt __used,
 static int opt_show_lines(const struct option *opt __used,
                          const char *str, int unset __used)
 {
+       int ret = 0;
+
        if (str)
-               parse_line_range_desc(str, &params.line_range);
+               ret = parse_line_range_desc(str, &params.line_range);
        INIT_LIST_HEAD(&params.line_range.line_list);
        params.show_lines = true;
-       return 0;
+
+       return ret;
 }
 #endif
 
@@ -142,9 +153,9 @@ static const struct option options[] = {
        OPT_CALLBACK('a', "add", NULL,
 #ifdef DWARF_SUPPORT
                "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT"
-               " [ARG ...]",
+               " [[NAME=]ARG ...]",
 #else
-               "[EVENT=]FUNC[+OFF|%return] [ARG ...]",
+               "[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]",
 #endif
                "probe point definition, where\n"
                "\t\tGROUP:\tGroup name (optional)\n"
@@ -173,11 +184,15 @@ static const struct option options[] = {
                   "file", "vmlinux pathname"),
 #endif
        OPT__DRY_RUN(&probe_event_dry_run),
+       OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
+                "Set how many probe points can be found for a probe."),
        OPT_END()
 };
 
 int cmd_probe(int argc, const char **argv, const char *prefix __used)
 {
+       int ret;
+
        argc = parse_options(argc, argv, options, probe_usage,
                             PARSE_OPT_STOP_AT_NON_OPTION);
        if (argc > 0) {
@@ -185,28 +200,34 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
                        pr_warning("  Error: '-' is not supported.\n");
                        usage_with_options(probe_usage, options);
                }
-               parse_probe_event_argv(argc, argv);
+               ret = parse_probe_event_argv(argc, argv);
+               if (ret < 0) {
+                       pr_err("  Error: Parse Error.  (%d)\n", ret);
+                       return ret;
+               }
        }
 
+       if (params.max_probe_points == 0)
+               params.max_probe_points = MAX_PROBES;
+
        if ((!params.nevents && !params.dellist && !params.list_events &&
             !params.show_lines))
                usage_with_options(probe_usage, options);
 
-       if (debugfs_valid_mountpoint(debugfs_path) < 0)
-               die("Failed to find debugfs path.");
-
        if (params.list_events) {
                if (params.nevents != 0 || params.dellist) {
-                       pr_warning("  Error: Don't use --list with"
-                                  " --add/--del.\n");
+                       pr_err("  Error: Don't use --list with --add/--del.\n");
                        usage_with_options(probe_usage, options);
                }
                if (params.show_lines) {
-                       pr_warning("  Error: Don't use --list with --line.\n");
+                       pr_err("  Error: Don't use --list with --line.\n");
                        usage_with_options(probe_usage, options);
                }
-               show_perf_probe_events();
-               return 0;
+               ret = show_perf_probe_events();
+               if (ret < 0)
+                       pr_err("  Error: Failed to show event list. (%d)\n",
+                              ret);
+               return ret;
        }
 
 #ifdef DWARF_SUPPORT
@@ -217,19 +238,31 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
                        usage_with_options(probe_usage, options);
                }
 
-               show_line_range(&params.line_range);
-               return 0;
+               ret = show_line_range(&params.line_range);
+               if (ret < 0)
+                       pr_err("  Error: Failed to show lines. (%d)\n", ret);
+               return ret;
        }
 #endif
 
        if (params.dellist) {
-               del_perf_probe_events(params.dellist);
+               ret = del_perf_probe_events(params.dellist);
                strlist__delete(params.dellist);
-               if (params.nevents == 0)
-                       return 0;
+               if (ret < 0) {
+                       pr_err("  Error: Failed to delete events. (%d)\n", ret);
+                       return ret;
+               }
        }
 
-       add_perf_probe_events(params.events, params.nevents, params.force_add);
+       if (params.nevents) {
+               ret = add_perf_probe_events(params.events, params.nevents,
+                                           params.force_add,
+                                           params.max_probe_points);
+               if (ret < 0) {
+                       pr_err("  Error: Failed to add events. (%d)\n", ret);
+                       return ret;
+               }
+       }
        return 0;
 }