[tip:perfcounters/urgent] perf_counter: Correct PERF_SAMPLE_RAW output

From: tip-bot for Peter Zijlstra
Date: Mon Aug 10 2009 - 05:37:52 EST


Commit-ID: a044560c3a1f0ad75ce685c1ed7604820b9ed319
Gitweb: http://git.kernel.org/tip/a044560c3a1f0ad75ce685c1ed7604820b9ed319
Author: Peter Zijlstra <a.p.zijlstra@xxxxxxxxx>
AuthorDate: Mon, 10 Aug 2009 11:16:52 +0200
Committer: Ingo Molnar <mingo@xxxxxxx>
CommitDate: Mon, 10 Aug 2009 11:33:09 +0200

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@xxxxxxxxx>
Acked-by: Frederic Weisbecker <fweisbec@xxxxxxxxx>
Cc: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
Cc: Mike Galbraith <efault@xxxxxx>
Cc: Paul Mackerras <paulus@xxxxxxxxx>
LKML-Reference: <1249896447.17467.74.camel@twins>
Signed-off-by: Ingo Molnar <mingo@xxxxxxx>


---
include/linux/perf_counter.h | 2 ++
include/trace/ftrace.h | 3 ++-
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 2aabe43..a9d823a 100644
--- a/include/linux/perf_counter.h
+++ b/include/linux/perf_counter.h
@@ -369,6 +369,8 @@ enum perf_event_type {
*
* { u64 nr,
* u64 ips[nr]; } && PERF_SAMPLE_CALLCHAIN
+ * { u32 size;
+ * char data[size];}&& PERF_SAMPLE_RAW
* };
*/
PERF_EVENT_SAMPLE = 9,
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
index 7fb16d9..7167b9b 100644
--- a/include/trace/ftrace.h
+++ b/include/trace/ftrace.h
@@ -685,7 +685,8 @@ static void ftrace_profile_##call(proto) \
pc = preempt_count(); \
\
__data_size = ftrace_get_offsets_##call(&__data_offsets, args); \
- __entry_size = ALIGN(__data_size + sizeof(*entry), sizeof(u64));\
+ __entry_size = ALIGN(__data_size + sizeof(*entry) + sizeof(u32),\
+ sizeof(u64)); \
\
do { \
char raw_data[__entry_size]; \
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index 546e62d..5229d16 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,
u64 counter;
} group_entry;
struct perf_callchain_entry *callchain = NULL;
- struct perf_raw_record *raw = NULL;
int callchain_size = 0;
u64 time;
struct {
@@ -2716,9 +2715,15 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
}

if (sample_type & PERF_SAMPLE_RAW) {
- raw = data->raw;
- if (raw)
- header.size += raw->size;
+ int size = sizeof(u32);
+
+ if (data->raw)
+ size += data->raw->size;
+ else
+ size += sizeof(u32);
+
+ WARN_ON_ONCE(size & (sizeof(u64)-1));
+ header.size += size;
}

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,
}
}

- if ((sample_type & PERF_SAMPLE_RAW) && raw)
- perf_output_copy(&handle, raw->data, raw->size);
+ if (sample_type & PERF_SAMPLE_RAW) {
+ if (data->raw) {
+ perf_output_put(&handle, data->raw->size);
+ perf_output_copy(&handle, data->raw->data, data->raw->size);
+ } else {
+ struct {
+ u32 size;
+ u32 data;
+ } raw = {
+ .size = sizeof(u32),
+ .data = 0,
+ };
+ perf_output_put(&handle, raw);
+ }
+ }

perf_output_end(&handle);
}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/