Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf evsel: Introduce perf_evsel__open_strerror method

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>

+68 -100
+6 -48
tools/perf/builtin-record.c
··· 224 224 225 225 static int perf_record__open(struct perf_record *rec) 226 226 { 227 - char msg[128]; 227 + char msg[512]; 228 228 struct perf_evsel *pos; 229 229 struct perf_evlist *evlist = rec->evlist; 230 230 struct perf_session *session = rec->session; ··· 234 234 perf_evlist__config(evlist, opts); 235 235 236 236 list_for_each_entry(pos, &evlist->entries, node) { 237 - struct perf_event_attr *attr = &pos->attr; 238 237 try_again: 239 238 if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { 240 - int err = errno; 241 - 242 - if (err == EPERM || err == EACCES) { 243 - ui__error_paranoid(); 244 - rc = -err; 245 - goto out; 246 - } else if (err == ENODEV && opts->target.cpu_list) { 247 - pr_err("No such device - did you specify" 248 - " an out-of-range profile CPU?\n"); 249 - rc = -err; 250 - goto out; 251 - } 252 - 253 - if (perf_evsel__fallback(pos, err, msg, sizeof(msg))) { 239 + if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 254 240 if (verbose) 255 241 ui__warning("%s\n", msg); 256 242 goto try_again; 257 243 } 258 244 259 - if (err == ENOENT) { 260 - ui__error("The %s event is not supported.\n", 261 - perf_evsel__name(pos)); 262 - rc = -err; 263 - goto out; 264 - } else if ((err == EOPNOTSUPP) && (attr->precise_ip)) { 265 - ui__error("\'precise\' request may not be supported. " 266 - "Try removing 'p' modifier\n"); 267 - rc = -err; 268 - goto out; 269 - } 270 - 271 - printf("\n"); 272 - error("sys_perf_event_open() syscall returned with %d " 273 - "(%s) for event %s. /bin/dmesg may provide " 274 - "additional information.\n", 275 - err, strerror(err), perf_evsel__name(pos)); 276 - 277 - #if defined(__i386__) || defined(__x86_64__) 278 - if (attr->type == PERF_TYPE_HARDWARE && 279 - err == EOPNOTSUPP) { 280 - pr_err("No hardware sampling interrupt available." 281 - " No APIC? If so then you can boot the kernel" 282 - " with the \"lapic\" boot parameter to" 283 - " force-enable it.\n"); 284 - rc = -err; 285 - goto out; 286 - } 287 - #endif 288 - 289 - pr_err("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 290 - rc = -err; 245 + rc = -errno; 246 + perf_evsel__open_strerror(pos, &opts->target, 247 + errno, msg, sizeof(msg)); 248 + ui__error("%s\n", msg); 291 249 goto out; 292 250 } 293 251 }
+5 -11
tools/perf/builtin-stat.c
··· 247 247 248 248 static int __run_perf_stat(int argc __maybe_unused, const char **argv) 249 249 { 250 + char msg[512]; 250 251 unsigned long long t0, t1; 251 252 struct perf_evsel *counter; 252 253 int status = 0; ··· 325 324 continue; 326 325 } 327 326 328 - if (errno == EPERM || errno == EACCES) { 329 - error("You may not have permission to collect %sstats.\n" 330 - "\t Consider tweaking" 331 - " /proc/sys/kernel/perf_event_paranoid or running as root.", 332 - target.system_wide ? "system-wide " : ""); 333 - } else { 334 - error("open_counter returned with %d (%s). " 335 - "/bin/dmesg may provide additional information.\n", 336 - errno, strerror(errno)); 337 - } 327 + perf_evsel__open_strerror(counter, &target, 328 + errno, msg, sizeof(msg)); 329 + ui__error("%s\n", msg); 330 + 338 331 if (child_pid != -1) 339 332 kill(child_pid, SIGTERM); 340 333 341 - pr_err("Not all events could be opened.\n"); 342 334 return -1; 343 335 } 344 336 counter->supported = true;
+5 -29
tools/perf/builtin-top.c
··· 892 892 893 893 static void perf_top__start_counters(struct perf_top *top) 894 894 { 895 - char msg[128]; 895 + char msg[512]; 896 896 struct perf_evsel *counter; 897 897 struct perf_evlist *evlist = top->evlist; 898 898 struct perf_record_opts *opts = &top->record_opts; ··· 900 900 perf_evlist__config(evlist, opts); 901 901 902 902 list_for_each_entry(counter, &evlist->entries, node) { 903 - struct perf_event_attr *attr = &counter->attr; 904 903 try_again: 905 904 if (perf_evsel__open(counter, top->evlist->cpus, 906 905 top->evlist->threads) < 0) { 907 - int err = errno; 908 - 909 - if (err == EPERM || err == EACCES) { 910 - ui__error_paranoid(); 911 - goto out_err; 912 - } 913 - 914 - if (perf_evsel__fallback(counter, err, msg, sizeof(msg))) { 906 + if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) { 915 907 if (verbose) 916 908 ui__warning("%s\n", msg); 917 909 goto try_again; 918 910 } 919 911 920 - if (err == ENOENT) { 921 - ui__error("The %s event is not supported.\n", 922 - perf_evsel__name(counter)); 923 - goto out_err; 924 - } else if (err == EMFILE) { 925 - ui__error("Too many events are opened.\n" 926 - "Try again after reducing the number of events\n"); 927 - goto out_err; 928 - } else if ((err == EOPNOTSUPP) && (attr->precise_ip)) { 929 - ui__error("\'precise\' request may not be supported. " 930 - "Try removing 'p' modifier\n"); 931 - goto out_err; 932 - } 933 - 934 - ui__error("The sys_perf_event_open() syscall " 935 - "returned with %d (%s). /bin/dmesg " 936 - "may provide additional information.\n" 937 - "No CONFIG_PERF_EVENTS=y kernel support " 938 - "configured?\n", err, strerror(err)); 912 + perf_evsel__open_strerror(counter, &opts->target, 913 + errno, msg, sizeof(msg)); 914 + ui__error("%s\n", msg); 939 915 goto out_err; 940 916 } 941 917 }
-11
tools/perf/ui/util.c
··· 52 52 return ret; 53 53 } 54 54 55 - int ui__error_paranoid(void) 56 - { 57 - return ui__error("Permission error - are you root?\n" 58 - "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n" 59 - " -1 - Not paranoid at all\n" 60 - " 0 - Disallow raw tracepoint access for unpriv\n" 61 - " 1 - Disallow cpu events for unpriv\n" 62 - " 2 - Disallow kernel profiling for unpriv\n"); 63 - } 64 - 65 - 66 55 /** 67 56 * perf_error__register - Register error logging functions 68 57 * @eops: The pointer to error logging function struct
-1
tools/perf/util/debug.h
··· 16 16 17 17 int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); 18 18 int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); 19 - int ui__error_paranoid(void); 20 19 21 20 #endif /* __PERF_DEBUG_H */
+49
tools/perf/util/evsel.c
··· 1406 1406 1407 1407 return false; 1408 1408 } 1409 + 1410 + int perf_evsel__open_strerror(struct perf_evsel *evsel, 1411 + struct perf_target *target, 1412 + int err, char *msg, size_t size) 1413 + { 1414 + switch (err) { 1415 + case EPERM: 1416 + case EACCES: 1417 + return scnprintf(msg, size, "%s", 1418 + "You may not have permission to collect %sstats.\n" 1419 + "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n" 1420 + " -1 - Not paranoid at all\n" 1421 + " 0 - Disallow raw tracepoint access for unpriv\n" 1422 + " 1 - Disallow cpu events for unpriv\n" 1423 + " 2 - Disallow kernel profiling for unpriv", 1424 + target->system_wide ? "system-wide " : ""); 1425 + case ENOENT: 1426 + return scnprintf(msg, size, "The %s event is not supported.", 1427 + perf_evsel__name(evsel)); 1428 + case EMFILE: 1429 + return scnprintf(msg, size, "%s", 1430 + "Too many events are opened.\n" 1431 + "Try again after reducing the number of events."); 1432 + case ENODEV: 1433 + if (target->cpu_list) 1434 + return scnprintf(msg, size, "%s", 1435 + "No such device - did you specify an out-of-range profile CPU?\n"); 1436 + break; 1437 + case EOPNOTSUPP: 1438 + if (evsel->attr.precise_ip) 1439 + return scnprintf(msg, size, "%s", 1440 + "\'precise\' request may not be supported. Try removing 'p' modifier."); 1441 + #if defined(__i386__) || defined(__x86_64__) 1442 + if (evsel->attr.type == PERF_TYPE_HARDWARE) 1443 + return scnprintf(msg, size, "%s", 1444 + "No hardware sampling interrupt available.\n" 1445 + "No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it."); 1446 + #endif 1447 + break; 1448 + default: 1449 + break; 1450 + } 1451 + 1452 + return scnprintf(msg, size, 1453 + "The sys_perf_event_open() syscall returned with %d (%s) for event (%s). \n" 1454 + "/bin/dmesg may provide additional information.\n" 1455 + "No CONFIG_PERF_EVENTS=y kernel support configured?\n", 1456 + err, strerror(err), perf_evsel__name(evsel)); 1457 + }
+3
tools/perf/util/evsel.h
··· 254 254 255 255 bool perf_evsel__fallback(struct perf_evsel *evsel, int err, 256 256 char *msg, size_t msgsize); 257 + int perf_evsel__open_strerror(struct perf_evsel *evsel, 258 + struct perf_target *target, 259 + int err, char *msg, size_t size); 257 260 #endif /* __PERF_EVSEL_H */