diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2009-08-10 05:16:52 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-08-10 05:33:09 -0400 |
commit | a044560c3a1f0ad75ce685c1ed7604820b9ed319 (patch) | |
tree | 51fa4979ad02d388b35e1a56020bfbd8c2e5329d | |
parent | c0a8865e32c8d1a562db38e06ef31ef23282f646 (diff) |
perf_counter: Correct PERF_SAMPLE_RAW output
PERF_SAMPLE_* output switches should unconditionally output the
correct format, as they are the only way to unambiguously parse
the PERF_EVENT_SAMPLE data.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Acked-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1249896447.17467.74.camel@twins>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | include/linux/perf_counter.h | 2 | ||||
-rw-r--r-- | include/trace/ftrace.h | 3 | ||||
-rw-r--r-- | kernel/perf_counter.c | 30 |
3 files changed, 28 insertions, 7 deletions
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h index 2aabe43c1d04..a9d823a93fe8 100644 --- a/include/linux/perf_counter.h +++ b/include/linux/perf_counter.h | |||
@@ -369,6 +369,8 @@ enum perf_event_type { | |||
369 | * | 369 | * |
370 | * { u64 nr, | 370 | * { u64 nr, |
371 | * u64 ips[nr]; } && PERF_SAMPLE_CALLCHAIN | 371 | * u64 ips[nr]; } && PERF_SAMPLE_CALLCHAIN |
372 | * { u32 size; | ||
373 | * char data[size];}&& PERF_SAMPLE_RAW | ||
372 | * }; | 374 | * }; |
373 | */ | 375 | */ |
374 | PERF_EVENT_SAMPLE = 9, | 376 | PERF_EVENT_SAMPLE = 9, |
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h index 7fb16d90e7b1..7167b9b97da2 100644 --- a/include/trace/ftrace.h +++ b/include/trace/ftrace.h | |||
@@ -685,7 +685,8 @@ static void ftrace_profile_##call(proto) \ | |||
685 | pc = preempt_count(); \ | 685 | pc = preempt_count(); \ |
686 | \ | 686 | \ |
687 | __data_size = ftrace_get_offsets_##call(&__data_offsets, args); \ | 687 | __data_size = ftrace_get_offsets_##call(&__data_offsets, args); \ |
688 | __entry_size = ALIGN(__data_size + sizeof(*entry), sizeof(u64));\ | 688 | __entry_size = ALIGN(__data_size + sizeof(*entry) + sizeof(u32),\ |
689 | sizeof(u64)); \ | ||
689 | \ | 690 | \ |
690 | do { \ | 691 | do { \ |
691 | char raw_data[__entry_size]; \ | 692 | char raw_data[__entry_size]; \ |
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index 546e62d62941..5229d1666fa5 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c | |||
@@ -2646,7 +2646,6 @@ static void perf_counter_output(struct perf_counter *counter, int nmi, | |||
2646 | u64 counter; | 2646 | u64 counter; |
2647 | } group_entry; | 2647 | } group_entry; |
2648 | struct perf_callchain_entry *callchain = NULL; | 2648 | struct perf_callchain_entry *callchain = NULL; |
2649 | struct perf_raw_record *raw = NULL; | ||
2650 | int callchain_size = 0; | 2649 | int callchain_size = 0; |
2651 | u64 time; | 2650 | u64 time; |
2652 | struct { | 2651 | struct { |
@@ -2716,9 +2715,15 @@ static void perf_counter_output(struct perf_counter *counter, int nmi, | |||
2716 | } | 2715 | } |
2717 | 2716 | ||
2718 | if (sample_type & PERF_SAMPLE_RAW) { | 2717 | if (sample_type & PERF_SAMPLE_RAW) { |
2719 | raw = data->raw; | 2718 | int size = sizeof(u32); |
2720 | if (raw) | 2719 | |
2721 | header.size += raw->size; | 2720 | if (data->raw) |
2721 | size += data->raw->size; | ||
2722 | else | ||
2723 | size += sizeof(u32); | ||
2724 | |||
2725 | WARN_ON_ONCE(size & (sizeof(u64)-1)); | ||
2726 | header.size += size; | ||
2722 | } | 2727 | } |
2723 | 2728 | ||
2724 | ret = perf_output_begin(&handle, counter, header.size, nmi, 1); | 2729 | ret = perf_output_begin(&handle, counter, header.size, nmi, 1); |
@@ -2784,8 +2789,21 @@ static void perf_counter_output(struct perf_counter *counter, int nmi, | |||
2784 | } | 2789 | } |
2785 | } | 2790 | } |
2786 | 2791 | ||
2787 | if ((sample_type & PERF_SAMPLE_RAW) && raw) | 2792 | if (sample_type & PERF_SAMPLE_RAW) { |
2788 | perf_output_copy(&handle, raw->data, raw->size); | 2793 | if (data->raw) { |
2794 | perf_output_put(&handle, data->raw->size); | ||
2795 | perf_output_copy(&handle, data->raw->data, data->raw->size); | ||
2796 | } else { | ||
2797 | struct { | ||
2798 | u32 size; | ||
2799 | u32 data; | ||
2800 | } raw = { | ||
2801 | .size = sizeof(u32), | ||
2802 | .data = 0, | ||
2803 | }; | ||
2804 | perf_output_put(&handle, raw); | ||
2805 | } | ||
2806 | } | ||
2789 | 2807 | ||
2790 | perf_output_end(&handle); | 2808 | perf_output_end(&handle); |
2791 | } | 2809 | } |