perf evsel: Introduce perf_evsel__open_strerror method
authorArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 13 Dec 2012 18:10:58 +0000 (15:10 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 24 Jan 2013 19:40:09 +0000 (16:40 -0300)
That consolidates the error messages in 'record', 'stat' and 'top', that
now get a consistent set of messages and allow other tools to use the
new method to report problems using whatever UI toolkit.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1cudb7wl996kz7ilz83ctvhr@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-record.c
tools/perf/builtin-stat.c
tools/perf/builtin-top.c
tools/perf/ui/util.c
tools/perf/util/debug.h
tools/perf/util/evsel.c
tools/perf/util/evsel.h

index b8d0a39..de60dd4 100644 (file)
@@ -224,7 +224,7 @@ static bool perf_evlist__equal(struct perf_evlist *evlist,
 
 static int perf_record__open(struct perf_record *rec)
 {
-       char msg[128];
+       char msg[512];
        struct perf_evsel *pos;
        struct perf_evlist *evlist = rec->evlist;
        struct perf_session *session = rec->session;
@@ -234,60 +234,18 @@ static int perf_record__open(struct perf_record *rec)
        perf_evlist__config(evlist, opts);
 
        list_for_each_entry(pos, &evlist->entries, node) {
-               struct perf_event_attr *attr = &pos->attr;
 try_again:
                if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) {
-                       int err = errno;
-
-                       if (err == EPERM || err == EACCES) {
-                               ui__error_paranoid();
-                               rc = -err;
-                               goto out;
-                       } else if (err ==  ENODEV && opts->target.cpu_list) {
-                               pr_err("No such device - did you specify"
-                                      " an out-of-range profile CPU?\n");
-                               rc = -err;
-                               goto out;
-                       }
-
-                       if (perf_evsel__fallback(pos, err, msg, sizeof(msg))) {
+                       if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
                                if (verbose)
                                        ui__warning("%s\n", msg);
                                goto try_again;
                        }
 
-                       if (err == ENOENT) {
-                               ui__error("The %s event is not supported.\n",
-                                         perf_evsel__name(pos));
-                               rc = -err;
-                               goto out;
-                       } else if ((err == EOPNOTSUPP) && (attr->precise_ip)) {
-                               ui__error("\'precise\' request may not be supported. "
-                                         "Try removing 'p' modifier\n");
-                               rc = -err;
-                               goto out;
-                       }
-
-                       printf("\n");
-                       error("sys_perf_event_open() syscall returned with %d "
-                             "(%s) for event %s. /bin/dmesg may provide "
-                             "additional information.\n",
-                             err, strerror(err), perf_evsel__name(pos));
-
-#if defined(__i386__) || defined(__x86_64__)
-                       if (attr->type == PERF_TYPE_HARDWARE &&
-                           err == EOPNOTSUPP) {
-                               pr_err("No hardware sampling interrupt available."
-                                      " No APIC? If so then you can boot the kernel"
-                                      " with the \"lapic\" boot parameter to"
-                                      " force-enable it.\n");
-                               rc = -err;
-                               goto out;
-                       }
-#endif
-
-                       pr_err("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
-                       rc = -err;
+                       rc = -errno;
+                       perf_evsel__open_strerror(pos, &opts->target,
+                                                 errno, msg, sizeof(msg));
+                       ui__error("%s\n", msg);
                        goto out;
                }
        }
index ef067c1..1c2ac14 100644 (file)
@@ -247,6 +247,7 @@ static int read_counter(struct perf_evsel *counter)
 
 static int __run_perf_stat(int argc __maybe_unused, const char **argv)
 {
+       char msg[512];
        unsigned long long t0, t1;
        struct perf_evsel *counter;
        int status = 0;
@@ -324,20 +325,13 @@ static int __run_perf_stat(int argc __maybe_unused, const char **argv)
                                continue;
                        }
 
-                       if (errno == EPERM || errno == EACCES) {
-                               error("You may not have permission to collect %sstats.\n"
-                                     "\t Consider tweaking"
-                                     " /proc/sys/kernel/perf_event_paranoid or running as root.",
-                                     target.system_wide ? "system-wide " : "");
-                       } else {
-                               error("open_counter returned with %d (%s). "
-                                     "/bin/dmesg may provide additional information.\n",
-                                      errno, strerror(errno));
-                       }
+                       perf_evsel__open_strerror(counter, &target,
+                                                 errno, msg, sizeof(msg));
+                       ui__error("%s\n", msg);
+
                        if (child_pid != -1)
                                kill(child_pid, SIGTERM);
 
-                       pr_err("Not all events could be opened.\n");
                        return -1;
                }
                counter->supported = true;
index 8d41d0b..f5fd260 100644 (file)
@@ -892,7 +892,7 @@ static void perf_top__mmap_read(struct perf_top *top)
 
 static void perf_top__start_counters(struct perf_top *top)
 {
-       char msg[128];
+       char msg[512];
        struct perf_evsel *counter;
        struct perf_evlist *evlist = top->evlist;
        struct perf_record_opts *opts = &top->record_opts;
@@ -900,42 +900,18 @@ static void perf_top__start_counters(struct perf_top *top)
        perf_evlist__config(evlist, opts);
 
        list_for_each_entry(counter, &evlist->entries, node) {
-               struct perf_event_attr *attr = &counter->attr;
 try_again:
                if (perf_evsel__open(counter, top->evlist->cpus,
                                     top->evlist->threads) < 0) {
-                       int err = errno;
-
-                       if (err == EPERM || err == EACCES) {
-                               ui__error_paranoid();
-                               goto out_err;
-                       }
-
-                       if (perf_evsel__fallback(counter, err, msg, sizeof(msg))) {
+                       if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) {
                                if (verbose)
                                        ui__warning("%s\n", msg);
                                goto try_again;
                        }
 
-                       if (err == ENOENT) {
-                               ui__error("The %s event is not supported.\n",
-                                         perf_evsel__name(counter));
-                               goto out_err;
-                       } else if (err == EMFILE) {
-                               ui__error("Too many events are opened.\n"
-                                           "Try again after reducing the number of events\n");
-                               goto out_err;
-                       } else if ((err == EOPNOTSUPP) && (attr->precise_ip)) {
-                               ui__error("\'precise\' request may not be supported. "
-                                         "Try removing 'p' modifier\n");
-                               goto out_err;
-                       }
-
-                       ui__error("The sys_perf_event_open() syscall "
-                                   "returned with %d (%s).  /bin/dmesg "
-                                   "may provide additional information.\n"
-                                   "No CONFIG_PERF_EVENTS=y kernel support "
-                                   "configured?\n", err, strerror(err));
+                       perf_evsel__open_strerror(counter, &opts->target,
+                                                 errno, msg, sizeof(msg));
+                       ui__error("%s\n", msg);
                        goto out_err;
                }
        }
index 3014a7c..e3e0a96 100644 (file)
@@ -52,17 +52,6 @@ int ui__warning(const char *format, ...)
        return ret;
 }
 
-int ui__error_paranoid(void)
-{
-       return ui__error("Permission error - are you root?\n"
-                   "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n"
-                   " -1 - Not paranoid at all\n"
-                   "  0 - Disallow raw tracepoint access for unpriv\n"
-                   "  1 - Disallow cpu events for unpriv\n"
-                   "  2 - Disallow kernel profiling for unpriv\n");
-}
-
-
 /**
  * perf_error__register - Register error logging functions
  * @eops: The pointer to error logging function struct
index 6e2667f..efbd988 100644 (file)
@@ -16,6 +16,5 @@ void trace_event(union perf_event *event);
 
 int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
 int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
-int ui__error_paranoid(void);
 
 #endif /* __PERF_DEBUG_H */
index 0c88e5c..e45332d 100644 (file)
@@ -1406,3 +1406,52 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
 
        return false;
 }
+
+int perf_evsel__open_strerror(struct perf_evsel *evsel,
+                             struct perf_target *target,
+                             int err, char *msg, size_t size)
+{
+       switch (err) {
+       case EPERM:
+       case EACCES:
+               return scnprintf(msg, size, "%s",
+                "You may not have permission to collect %sstats.\n"
+                "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n"
+                " -1 - Not paranoid at all\n"
+                "  0 - Disallow raw tracepoint access for unpriv\n"
+                "  1 - Disallow cpu events for unpriv\n"
+                "  2 - Disallow kernel profiling for unpriv",
+                                target->system_wide ? "system-wide " : "");
+       case ENOENT:
+               return scnprintf(msg, size, "The %s event is not supported.",
+                                perf_evsel__name(evsel));
+       case EMFILE:
+               return scnprintf(msg, size, "%s",
+                        "Too many events are opened.\n"
+                        "Try again after reducing the number of events.");
+       case ENODEV:
+               if (target->cpu_list)
+                       return scnprintf(msg, size, "%s",
+        "No such device - did you specify an out-of-range profile CPU?\n");
+               break;
+       case EOPNOTSUPP:
+               if (evsel->attr.precise_ip)
+                       return scnprintf(msg, size, "%s",
+       "\'precise\' request may not be supported. Try removing 'p' modifier.");
+#if defined(__i386__) || defined(__x86_64__)
+               if (evsel->attr.type == PERF_TYPE_HARDWARE)
+                       return scnprintf(msg, size, "%s",
+       "No hardware sampling interrupt available.\n"
+       "No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it.");
+#endif
+               break;
+       default:
+               break;
+       }
+
+       return scnprintf(msg, size,
+       "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).  \n"
+       "/bin/dmesg may provide additional information.\n"
+       "No CONFIG_PERF_EVENTS=y kernel support configured?\n",
+                        err, strerror(err), perf_evsel__name(evsel));
+}
index 26d8cfd..c68d1b8 100644 (file)
@@ -254,4 +254,7 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
 
 bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
                          char *msg, size_t msgsize);
+int perf_evsel__open_strerror(struct perf_evsel *evsel,
+                             struct perf_target *target,
+                             int err, char *msg, size_t size);
 #endif /* __PERF_EVSEL_H */