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

perf report: Accept fifos as input file

The default input file for perf report is not handled the same way as
perf record does it for its output file. This leads to unexpected
behavior of perf report, etc. E.g.:

# perf record -a -e cpu-cycles sleep 2 | perf report | cat
failed to open perf.data: No such file or directory (try 'perf record' first)

While perf record writes to a fifo, perf report expects perf.data to be
read. This patch changes this to accept fifos as input file.

Applies to the following commands:

perf annotate
perf buildid-list
perf evlist
perf kmem
perf lock
perf report
perf sched
perf script
perf timechart

Also fixes char const* -> const char* type declaration for filename
strings.

v2:
* Prevent potential null pointer access to input_name in
builtin-report.c. Needed due to removal of patch "perf report: Setup
browser if stdout is a pipe"

Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1323248577-11268-5-git-send-email-robert.richter@amd.com
Signed-off-by: Robert Richter <robert.richter@amd.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Robert Richter and committed by
Arnaldo Carvalho de Melo
efad1415 1b549504

+51 -33
+1 -1
tools/perf/Documentation/perf-annotate.txt
··· 22 22 ------- 23 23 -i:: 24 24 --input=:: 25 - Input file name. (default: perf.data) 25 + Input file name. (default: perf.data unless stdin is a fifo) 26 26 27 27 -d:: 28 28 --dsos=<dso[,dso...]>::
+1 -1
tools/perf/Documentation/perf-buildid-list.txt
··· 26 26 Show only DSOs with hits. 27 27 -i:: 28 28 --input=:: 29 - Input file name. (default: perf.data) 29 + Input file name. (default: perf.data unless stdin is a fifo) 30 30 -f:: 31 31 --force:: 32 32 Don't do ownership validation.
+1 -1
tools/perf/Documentation/perf-evlist.txt
··· 18 18 ------- 19 19 -i:: 20 20 --input=:: 21 - Input file name. (default: perf.data) 21 + Input file name. (default: perf.data unless stdin is a fifo) 22 22 23 23 SEE ALSO 24 24 --------
+1 -1
tools/perf/Documentation/perf-kmem.txt
··· 23 23 ------- 24 24 -i <file>:: 25 25 --input=<file>:: 26 - Select the input file (default: perf.data) 26 + Select the input file (default: perf.data unless stdin is a fifo) 27 27 28 28 --caller:: 29 29 Show per-callsite statistics
+1 -1
tools/perf/Documentation/perf-lock.txt
··· 29 29 30 30 -i:: 31 31 --input=<file>:: 32 - Input file name. 32 + Input file name. (default: perf.data unless stdin is a fifo) 33 33 34 34 -v:: 35 35 --verbose::
+1 -1
tools/perf/Documentation/perf-report.txt
··· 19 19 ------- 20 20 -i:: 21 21 --input=:: 22 - Input file name. (default: perf.data) 22 + Input file name. (default: perf.data unless stdin is a fifo) 23 23 24 24 -v:: 25 25 --verbose::
+1 -1
tools/perf/Documentation/perf-sched.txt
··· 40 40 ------- 41 41 -i:: 42 42 --input=<file>:: 43 - Input file name. (default: perf.data) 43 + Input file name. (default: perf.data unless stdin is a fifo) 44 44 45 45 -v:: 46 46 --verbose::
+1 -1
tools/perf/Documentation/perf-script.txt
··· 106 106 107 107 -i:: 108 108 --input=:: 109 - Input file name. 109 + Input file name. (default: perf.data unless stdin is a fifo) 110 110 111 111 -d:: 112 112 --debug-mode::
+1 -1
tools/perf/Documentation/perf-timechart.txt
··· 27 27 Select the output file (default: output.svg) 28 28 -i:: 29 29 --input=:: 30 - Select the input file (default: perf.data) 30 + Select the input file (default: perf.data unless stdin is a fifo) 31 31 -w:: 32 32 --width=:: 33 33 Select the width of the SVG file (default: 1000)
+1 -2
tools/perf/builtin-annotate.c
··· 215 215 } 216 216 217 217 if (total_nr_samples == 0) { 218 - ui__warning("The %s file has no samples!\n", ann->input_name); 218 + ui__warning("The %s file has no samples!\n", session->filename); 219 219 goto out_delete; 220 220 } 221 221 out_delete: ··· 250 250 .ordered_samples = true, 251 251 .ordering_requires_timestamps = true, 252 252 }, 253 - .input_name = "perf.data", 254 253 }; 255 254 const struct option options[] = { 256 255 OPT_STRING('i', "input", &annotate.input_name, "file",
+10 -9
tools/perf/builtin-buildid-list.c
··· 18 18 19 19 #include <libelf.h> 20 20 21 - static char const *input_name = "perf.data"; 21 + static const char *input_name; 22 22 static bool force; 23 23 static bool show_kernel; 24 24 static bool with_hits; ··· 71 71 { 72 72 struct perf_session *session; 73 73 74 + elf_version(EV_CURRENT); 75 + 74 76 session = perf_session__new(input_name, O_RDONLY, force, false, 75 77 &build_id__mark_dso_hit_ops); 76 78 if (session == NULL) 77 79 return -1; 78 80 81 + /* 82 + * See if this is an ELF file first: 83 + */ 84 + if (filename__fprintf_build_id(session->filename, stdout)) 85 + goto out; 86 + 79 87 if (with_hits) 80 88 perf_session__process_events(session, &build_id__mark_dso_hit_ops); 81 89 82 90 perf_session__fprintf_dsos_buildid(session, stdout, with_hits); 83 - 91 + out: 84 92 perf_session__delete(session); 85 93 return 0; 86 94 } ··· 97 89 { 98 90 if (show_kernel) 99 91 return sysfs__fprintf_build_id(stdout); 100 - 101 - elf_version(EV_CURRENT); 102 - /* 103 - * See if this is an ELF file first: 104 - */ 105 - if (filename__fprintf_build_id(input_name, stdout)) 106 - return 0; 107 92 108 93 return perf_session__list_build_ids(); 109 94 }
+1 -1
tools/perf/builtin-evlist.c
··· 15 15 #include "util/parse-options.h" 16 16 #include "util/session.h" 17 17 18 - static char const *input_name = "perf.data"; 18 + static const char *input_name; 19 19 20 20 static int __cmd_evlist(void) 21 21 {
+1 -1
tools/perf/builtin-kmem.c
··· 19 19 struct alloc_stat; 20 20 typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *); 21 21 22 - static char const *input_name = "perf.data"; 22 + static const char *input_name; 23 23 24 24 static int alloc_flag; 25 25 static int caller_flag;
+1 -1
tools/perf/builtin-lock.c
··· 326 326 die("memory allocation failed\n"); 327 327 } 328 328 329 - static char const *input_name = "perf.data"; 329 + static const char *input_name; 330 330 331 331 struct raw_event_sample { 332 332 u32 size;
+10 -3
tools/perf/builtin-report.c
··· 321 321 } 322 322 323 323 if (nr_samples == 0) { 324 - ui__warning("The %s file has no samples!\n", 325 - rep->input_name); 324 + ui__warning("The %s file has no samples!\n", session->filename); 326 325 goto out_delete; 327 326 } 328 327 ··· 429 430 430 431 int cmd_report(int argc, const char **argv, const char *prefix __used) 431 432 { 433 + struct stat st; 432 434 char callchain_default_opt[] = "fractal,0.5,callee"; 433 435 const char * const report_usage[] = { 434 436 "perf report [<options>]", ··· 451 451 .ordered_samples = true, 452 452 .ordering_requires_timestamps = true, 453 453 }, 454 - .input_name = "perf.data", 455 454 .pretty_printing_style = "normal", 456 455 }; 457 456 const struct option options[] = { ··· 530 531 if (report.inverted_callchain) 531 532 callchain_param.order = ORDER_CALLER; 532 533 534 + if (!report.input_name || !strlen(report.input_name)) { 535 + if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode)) 536 + report.input_name = "-"; 537 + else 538 + report.input_name = "perf.data"; 539 + } 540 + 533 541 if (strcmp(report.input_name, "-") != 0) 534 542 setup_browser(true); 535 543 else 536 544 use_browser = 0; 545 + 537 546 /* 538 547 * Only in the newt browser we are doing integrated annotation, 539 548 * so don't allocate extra space that won't be used in the stdio
+1 -1
tools/perf/builtin-sched.c
··· 22 22 #include <pthread.h> 23 23 #include <math.h> 24 24 25 - static char const *input_name = "perf.data"; 25 + static const char *input_name; 26 26 27 27 static char default_sort_order[] = "avg, max, switch, runtime"; 28 28 static const char *sort_order = default_sort_order;
+2 -2
tools/perf/builtin-script.c
··· 434 434 return scripting_ops->stop_script(); 435 435 } 436 436 437 - static char const *input_name = "perf.data"; 437 + static const char *input_name; 438 438 439 439 static int process_sample_event(struct perf_tool *tool __used, 440 440 union perf_event *event, ··· 1316 1316 return -1; 1317 1317 } 1318 1318 1319 - input = open(input_name, O_RDONLY); 1319 + input = open(session->filename, O_RDONLY); /* input_name */ 1320 1320 if (input < 0) { 1321 1321 perror("failed to open file"); 1322 1322 exit(-1);
+2 -2
tools/perf/builtin-timechart.c
··· 38 38 #define PWR_EVENT_EXIT -1 39 39 40 40 41 - static char const *input_name = "perf.data"; 42 - static char const *output_name = "output.svg"; 41 + static const char *input_name; 42 + static const char *output_name = "output.svg"; 43 43 44 44 static unsigned int numcpus; 45 45 static u64 min_freq; /* Lowest CPU frequency seen */
+13 -2
tools/perf/util/session.c
··· 107 107 bool force, bool repipe, 108 108 struct perf_tool *tool) 109 109 { 110 - size_t len = filename ? strlen(filename) : 0; 111 - struct perf_session *self = zalloc(sizeof(*self) + len); 110 + struct perf_session *self; 111 + struct stat st; 112 + size_t len; 113 + 114 + if (!filename || !strlen(filename)) { 115 + if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode)) 116 + filename = "-"; 117 + else 118 + filename = "perf.data"; 119 + } 120 + 121 + len = strlen(filename); 122 + self = zalloc(sizeof(*self) + len); 112 123 113 124 if (self == NULL) 114 125 goto out;