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>
This commit is contained in:
committed by
Ingo Molnar
parent
c0a8865e32
commit
a044560c3a
@@ -369,6 +369,8 @@ enum perf_event_type {
|
|||||||
*
|
*
|
||||||
* { u64 nr,
|
* { u64 nr,
|
||||||
* u64 ips[nr]; } && PERF_SAMPLE_CALLCHAIN
|
* u64 ips[nr]; } && PERF_SAMPLE_CALLCHAIN
|
||||||
|
* { u32 size;
|
||||||
|
* char data[size];}&& PERF_SAMPLE_RAW
|
||||||
* };
|
* };
|
||||||
*/
|
*/
|
||||||
PERF_EVENT_SAMPLE = 9,
|
PERF_EVENT_SAMPLE = 9,
|
||||||
|
@@ -685,7 +685,8 @@ static void ftrace_profile_##call(proto) \
|
|||||||
pc = preempt_count(); \
|
pc = preempt_count(); \
|
||||||
\
|
\
|
||||||
__data_size = ftrace_get_offsets_##call(&__data_offsets, args); \
|
__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 { \
|
do { \
|
||||||
char raw_data[__entry_size]; \
|
char raw_data[__entry_size]; \
|
||||||
|
@@ -2646,7 +2646,6 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
|
|||||||
u64 counter;
|
u64 counter;
|
||||||
} group_entry;
|
} group_entry;
|
||||||
struct perf_callchain_entry *callchain = NULL;
|
struct perf_callchain_entry *callchain = NULL;
|
||||||
struct perf_raw_record *raw = NULL;
|
|
||||||
int callchain_size = 0;
|
int callchain_size = 0;
|
||||||
u64 time;
|
u64 time;
|
||||||
struct {
|
struct {
|
||||||
@@ -2716,9 +2715,15 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sample_type & PERF_SAMPLE_RAW) {
|
if (sample_type & PERF_SAMPLE_RAW) {
|
||||||
raw = data->raw;
|
int size = sizeof(u32);
|
||||||
if (raw)
|
|
||||||
header.size += raw->size;
|
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);
|
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)
|
if (sample_type & PERF_SAMPLE_RAW) {
|
||||||
perf_output_copy(&handle, raw->data, raw->size);
|
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);
|
perf_output_end(&handle);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user