aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/session.c
diff options
context:
space:
mode:
authorDavid Miller <davem@davemloft.net>2012-11-10 14:12:19 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-12-09 06:46:05 -0500
commit35d48ddfc0627443bd7ad2750a3f65d42cb742a0 (patch)
tree3ac86ffb8e5ee95dda5bce17814fb53c550e944a /tools/perf/util/session.c
parentee8d7787e197a0b1829c3f17dc1287224f14f35e (diff)
perf tools: Fix mmap limitations on 32-bit
This is a suggested patch to fix the bug I reported at: http://marc.info/?l=linux-kernel&m=135033028924652&w=2 Essentially, there is a hard requirement that when perf analyzes a trace, it must have the entire thing mmap()'d. Therefore the scheme used on 32-bit where we have a fixed (8) number of 32MB mmaps, and cycle through them, simply does not work. One of the reasons this requirement exists is because the iterators maintain references to perf entry objects and those references don't just simply go away when this mmap code decides to cycle an old mmap area out and reuse it. At this point, those entry pointers now point to garbage resulting in unpredictable behavior and crashes. It is better to try to mmap() as much as we can and if we do actually run into address space limitations, the failure of the mmap() call will indicate that and stop processing. I noticed that perf_session->mmap_window is set to a constant in one location, and only used in one other location. So I got rid of it altogether. So we adjust the size of the mmaps[] array to the maximum we could need. On 64-bit we only need one slot. On 32-bit we could need up to 128 (128 * 32MB == 4GB). I've verified that this allows a large (~600MB) perf.data file to be analyzed properly with a 32-bit perf binary, which previously was not possible. Signed-off-by: David S. Miller <davem@davemloft.net> Cc: Ingo Molnar <mingo@redhat.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/20121110.141219.582924082787523608.davem@davemloft.net Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/session.c')
-rw-r--r--tools/perf/util/session.c25
1 files changed, 14 insertions, 11 deletions
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index d5fb60760bac..aa5e58255cba 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -128,15 +128,6 @@ struct perf_session *perf_session__new(const char *filename, int mode,
128 goto out; 128 goto out;
129 129
130 memcpy(self->filename, filename, len); 130 memcpy(self->filename, filename, len);
131 /*
132 * On 64bit we can mmap the data file in one go. No need for tiny mmap
133 * slices. On 32bit we use 32MB.
134 */
135#if BITS_PER_LONG == 64
136 self->mmap_window = ULLONG_MAX;
137#else
138 self->mmap_window = 32 * 1024 * 1024ULL;
139#endif
140 self->machines = RB_ROOT; 131 self->machines = RB_ROOT;
141 self->repipe = repipe; 132 self->repipe = repipe;
142 INIT_LIST_HEAD(&self->ordered_samples.samples); 133 INIT_LIST_HEAD(&self->ordered_samples.samples);
@@ -1386,6 +1377,18 @@ fetch_mmaped_event(struct perf_session *session,
1386 return event; 1377 return event;
1387} 1378}
1388 1379
1380/*
1381 * On 64bit we can mmap the data file in one go. No need for tiny mmap
1382 * slices. On 32bit we use 32MB.
1383 */
1384#if BITS_PER_LONG == 64
1385#define MMAP_SIZE ULLONG_MAX
1386#define NUM_MMAPS 1
1387#else
1388#define MMAP_SIZE (32 * 1024 * 1024ULL)
1389#define NUM_MMAPS 128
1390#endif
1391
1389int __perf_session__process_events(struct perf_session *session, 1392int __perf_session__process_events(struct perf_session *session,
1390 u64 data_offset, u64 data_size, 1393 u64 data_offset, u64 data_size,
1391 u64 file_size, struct perf_tool *tool) 1394 u64 file_size, struct perf_tool *tool)
@@ -1393,7 +1396,7 @@ int __perf_session__process_events(struct perf_session *session,
1393 u64 head, page_offset, file_offset, file_pos, progress_next; 1396 u64 head, page_offset, file_offset, file_pos, progress_next;
1394 int err, mmap_prot, mmap_flags, map_idx = 0; 1397 int err, mmap_prot, mmap_flags, map_idx = 0;
1395 size_t mmap_size; 1398 size_t mmap_size;
1396 char *buf, *mmaps[8]; 1399 char *buf, *mmaps[NUM_MMAPS];
1397 union perf_event *event; 1400 union perf_event *event;
1398 uint32_t size; 1401 uint32_t size;
1399 1402
@@ -1408,7 +1411,7 @@ int __perf_session__process_events(struct perf_session *session,
1408 1411
1409 progress_next = file_size / 16; 1412 progress_next = file_size / 16;
1410 1413
1411 mmap_size = session->mmap_window; 1414 mmap_size = MMAP_SIZE;
1412 if (mmap_size > file_size) 1415 if (mmap_size > file_size)
1413 mmap_size = file_size; 1416 mmap_size = file_size;
1414 1417