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; |
