diff options
author | Namhyung Kim <namhyung.kim@lge.com> | 2013-09-30 04:19:48 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-10-04 14:17:46 -0400 |
commit | b314e5cfd11fd78545ce6c2be42646254390c1aa (patch) | |
tree | 9316fed404c26d55ae87ae6b68b4842e78c820b9 | |
parent | 027a7e86a17fb2d172f4eb17cd6b0e9f139224fd (diff) |
perf session: Fix infinite loop on invalid perf.data file
perf-record updates the header in the perf.data file at termination.
Without this update perf-report (and other processing built-ins) it
caused an infinite loop when perf report (or something like) called.
This is because the algorithm in __perf_session__process_events()
depends on the data_size which is read from file header. Use file size
directly instead in this case to do the best-effort processing.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: David Ahern <dsahern@gmail.com>
Tested-by: Sonny Rao <sonnyrao@chromium.org>
Acked-by: Ingo Molnar <mingo@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Sonny Rao <sonnyrao@chromium.org>
Link: http://lkml.kernel.org/r/1380529188-27193-1-git-send-email-namhyung@kernel.org
Signed-off-by: David Ahern <dsahern@gmail.com>
[ Reworded warning as per Ingo Molnar suggestion, replaces 'perf.data'
with session->filename, to precisely identify the data file involved ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | tools/perf/util/header.c | 12 | ||||
-rw-r--r-- | tools/perf/util/session.c | 2 |
2 files changed, 13 insertions, 1 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index ce69901176d8..c3e5a3b817ab 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -2768,6 +2768,18 @@ int perf_session__read_header(struct perf_session *session) | |||
2768 | if (perf_file_header__read(&f_header, header, fd) < 0) | 2768 | if (perf_file_header__read(&f_header, header, fd) < 0) |
2769 | return -EINVAL; | 2769 | return -EINVAL; |
2770 | 2770 | ||
2771 | /* | ||
2772 | * Sanity check that perf.data was written cleanly; data size is | ||
2773 | * initialized to 0 and updated only if the on_exit function is run. | ||
2774 | * If data size is still 0 then the file contains only partial | ||
2775 | * information. Just warn user and process it as much as it can. | ||
2776 | */ | ||
2777 | if (f_header.data.size == 0) { | ||
2778 | pr_warning("WARNING: The %s file's data size field is 0 which is unexpected.\n" | ||
2779 | "Was the 'perf record' command properly terminated?\n", | ||
2780 | session->filename); | ||
2781 | } | ||
2782 | |||
2771 | nr_attrs = f_header.attrs.size / f_header.attr_size; | 2783 | nr_attrs = f_header.attrs.size / f_header.attr_size; |
2772 | lseek(fd, f_header.attrs.offset, SEEK_SET); | 2784 | lseek(fd, f_header.attrs.offset, SEEK_SET); |
2773 | 2785 | ||
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 37c4718f6be1..568b750c01f6 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -1312,7 +1312,7 @@ int __perf_session__process_events(struct perf_session *session, | |||
1312 | file_offset = page_offset; | 1312 | file_offset = page_offset; |
1313 | head = data_offset - page_offset; | 1313 | head = data_offset - page_offset; |
1314 | 1314 | ||
1315 | if (data_offset + data_size < file_size) | 1315 | if (data_size && (data_offset + data_size < file_size)) |
1316 | file_size = data_offset + data_size; | 1316 | file_size = data_offset + data_size; |
1317 | 1317 | ||
1318 | progress_next = file_size / 16; | 1318 | progress_next = file_size / 16; |