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

perf inject: Fix output from a pipe to a file

Sometimes it needs to save the perf inject data to a file for debugging.
But normally it assumes the same format for input and output, so the end
result cannot be used due to a broken format.

# perf record -a -o - sleep 1 | perf inject -b -o my.data

# perf report -i my.data --stdio
0x208 [0]: failed to process type: 0 [Invalid argument]
Error:
failed to process sample
# To display the perf.data header info, please use --header/--header-only options.
#

In this case, it thought the data has a regular file header since the
output is not a pipe. But actually it doesn't have one and has a pipe
file header. At the end of the session, it tries to rewrite the regular
file header with updated features and it overwrites the data just
follows the pipe header.

Fix it by checking either the input and the output is a pipe.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lore.kernel.org/lkml/20210719223153.1618812-4-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Namhyung Kim and committed by
Arnaldo Carvalho de Melo
fea20d66 0ae03893

+10 -5
+10 -5
tools/perf/builtin-inject.c
··· 46 46 bool jit_mode; 47 47 bool in_place_update; 48 48 bool in_place_update_dry_run; 49 + bool is_pipe; 49 50 const char *input_name; 50 51 struct perf_data output; 51 52 u64 bytes_written; ··· 127 126 if (ret) 128 127 return ret; 129 128 130 - if (!inject->output.is_pipe) 129 + if (!inject->is_pipe) 131 130 return 0; 132 131 133 132 return perf_event__repipe_synth(tool, event); ··· 827 826 if (!inject->itrace_synth_opts.set) 828 827 auxtrace_index__free(&session->auxtrace_index); 829 828 830 - if (!data_out->is_pipe && !inject->in_place_update) 829 + if (!inject->is_pipe && !inject->in_place_update) 831 830 lseek(fd, output_data_offset, SEEK_SET); 832 831 833 832 ret = perf_session__process_events(session); 834 833 if (ret) 835 834 return ret; 836 835 837 - if (!data_out->is_pipe && !inject->in_place_update) { 836 + if (!inject->is_pipe && !inject->in_place_update) { 838 837 if (inject->build_ids) 839 838 perf_header__set_feat(&session->header, 840 839 HEADER_BUILD_ID); ··· 993 992 } 994 993 995 994 data.path = inject.input_name; 996 - inject.session = __perf_session__new(&data, inject.output.is_pipe, 997 - perf_data__fd(&inject.output), &inject.tool); 995 + if (!strcmp(inject.input_name, "-") || inject.output.is_pipe) 996 + inject.is_pipe = true; 997 + 998 + inject.session = __perf_session__new(&data, inject.is_pipe, 999 + perf_data__fd(&inject.output), 1000 + &inject.tool); 998 1001 if (IS_ERR(inject.session)) { 999 1002 ret = PTR_ERR(inject.session); 1000 1003 goto out_close_output;