perf session: Try to read pipe data from file

Ian came with the idea of having support to read the pipe data also from
file. Currently pipe mode files fail like:

  $ perf record -o - sleep 1 > /tmp/perf.pipe.data
  $ perf report -i /tmp/perf.pipe.data
  incompatible file format (rerun with -v to learn more)

This patch adds the support to do that by trying the pipe header first,
and if its successfully detected, switching the perf data to pipe mode.

Committer testing:

  # ls
  # perf record -a -o - sleep 1 > /tmp/perf.pipe.data
  [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 0.000 MB - ]
  # ls
  # perf report -i /tmp/perf.pipe.data | head -25
  # To display the perf.data header info, please use --header/--header-only options.
  #
  #
  # Total Lost Samples: 0
  #
  # Samples: 511  of event 'cycles'
  # Event count (approx.): 178447276
  #
  # Overhead  Command   Shared Object      Symbol
  # ........  ........  .................  ...........................................................................................
  #
      65.49%  swapper   [kernel.kallsyms]  [k] native_safe_halt
       6.45%  chromium  libblink_core.so   [.] blink::SelectorChecker::CheckOne
       4.08%  chromium  libblink_core.so   [.] blink::SelectorQuery::ExecuteForTraverseRoot<blink::AllElementsSelectorQueryTrait>
       2.25%  chromium  libblink_core.so   [.] blink::SelectorQuery::FindTraverseRootsAndExecute<blink::AllElementsSelectorQueryTrait>
       2.11%  chromium  libblink_core.so   [.] blink::SelectorChecker::MatchSelector
       1.91%  chromium  libblink_core.so   [.] blink::Node::OwnerShadowHost
       1.31%  chromium  libblink_core.so   [.] blink::Node::parentNode@plt
       1.22%  chromium  libblink_core.so   [.] blink::Node::parentNode
       0.59%  chromium  libblink_core.so   [.] blink::AnyAttributeMatches
       0.58%  chromium  libv8.so           [.] v8::internal::GlobalHandles::Create
       0.58%  chromium  libblink_core.so   [.] blink::NodeTraversal::NextAncestorSibling
       0.55%  chromium  libv8.so           [.] v8::internal::RegExpGlobalCache::RegExpGlobalCache
       0.55%  chromium  libblink_core.so   [.] blink::Node::ContainingShadowRoot
       0.55%  chromium  libblink_core.so   [.] blink::NodeTraversal::NextAncestorSibling@plt
  #

Original-patch-by: Ian Rogers <irogers@google.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Michael Petlan <mpetlan@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Khuong <pvk@pvk.ca>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lore.kernel.org/lkml/20200507095024.2789147-4-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Jiri Olsa 2020-05-07 11:50:22 +02:00 committed by Arnaldo Carvalho de Melo
parent b491198db8
commit 14d3d54052

View File

@ -3574,7 +3574,7 @@ static int perf_header__read_pipe(struct perf_session *session)
return -EINVAL; return -EINVAL;
} }
return 0; return f_header.size == sizeof(f_header) ? 0 : -1;
} }
static int read_attr(int fd, struct perf_header *ph, static int read_attr(int fd, struct perf_header *ph,
@ -3676,7 +3676,7 @@ int perf_session__read_header(struct perf_session *session)
struct perf_file_header f_header; struct perf_file_header f_header;
struct perf_file_attr f_attr; struct perf_file_attr f_attr;
u64 f_id; u64 f_id;
int nr_attrs, nr_ids, i, j; int nr_attrs, nr_ids, i, j, err;
int fd = perf_data__fd(data); int fd = perf_data__fd(data);
session->evlist = evlist__new(); session->evlist = evlist__new();
@ -3685,8 +3685,16 @@ int perf_session__read_header(struct perf_session *session)
session->evlist->env = &header->env; session->evlist->env = &header->env;
session->machines.host.env = &header->env; session->machines.host.env = &header->env;
if (perf_data__is_pipe(data))
return perf_header__read_pipe(session); /*
* We can read 'pipe' data event from regular file,
* check for the pipe header regardless of source.
*/
err = perf_header__read_pipe(session);
if (!err || (err && perf_data__is_pipe(data))) {
data->is_pipe = true;
return err;
}
if (perf_file_header__read(&f_header, header, fd) < 0) if (perf_file_header__read(&f_header, header, fd) < 0)
return -EINVAL; return -EINVAL;