diff options
-rw-r--r-- | include/linux/ring_buffer.h | 5 | ||||
-rw-r--r-- | kernel/trace/ring_buffer.c | 44 | ||||
-rw-r--r-- | kernel/trace/trace_events.c | 38 |
3 files changed, 87 insertions, 0 deletions
diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h index f0aa486d131c..fac8f1ac6f49 100644 --- a/include/linux/ring_buffer.h +++ b/include/linux/ring_buffer.h | |||
@@ -166,6 +166,11 @@ void ring_buffer_free_read_page(struct ring_buffer *buffer, void *data); | |||
166 | int ring_buffer_read_page(struct ring_buffer *buffer, void **data_page, | 166 | int ring_buffer_read_page(struct ring_buffer *buffer, void **data_page, |
167 | size_t len, int cpu, int full); | 167 | size_t len, int cpu, int full); |
168 | 168 | ||
169 | struct trace_seq; | ||
170 | |||
171 | int ring_buffer_print_entry_header(struct trace_seq *s); | ||
172 | int ring_buffer_print_page_header(struct trace_seq *s); | ||
173 | |||
169 | enum ring_buffer_flags { | 174 | enum ring_buffer_flags { |
170 | RB_FL_OVERWRITE = 1 << 0, | 175 | RB_FL_OVERWRITE = 1 << 0, |
171 | }; | 176 | }; |
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index f935bd5ec3e8..84a6055f37c9 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
@@ -22,6 +22,28 @@ | |||
22 | #include "trace.h" | 22 | #include "trace.h" |
23 | 23 | ||
24 | /* | 24 | /* |
25 | * The ring buffer header is special. We must manually up keep it. | ||
26 | */ | ||
27 | int ring_buffer_print_entry_header(struct trace_seq *s) | ||
28 | { | ||
29 | int ret; | ||
30 | |||
31 | ret = trace_seq_printf(s, "\ttype : 2 bits\n"); | ||
32 | ret = trace_seq_printf(s, "\tlen : 3 bits\n"); | ||
33 | ret = trace_seq_printf(s, "\ttime_delta : 27 bits\n"); | ||
34 | ret = trace_seq_printf(s, "\tarray : 32 bits\n"); | ||
35 | ret = trace_seq_printf(s, "\n"); | ||
36 | ret = trace_seq_printf(s, "\tpadding : type == %d\n", | ||
37 | RINGBUF_TYPE_PADDING); | ||
38 | ret = trace_seq_printf(s, "\ttime_extend : type == %d\n", | ||
39 | RINGBUF_TYPE_TIME_EXTEND); | ||
40 | ret = trace_seq_printf(s, "\tdata : type == %d\n", | ||
41 | RINGBUF_TYPE_DATA); | ||
42 | |||
43 | return ret; | ||
44 | } | ||
45 | |||
46 | /* | ||
25 | * The ring buffer is made up of a list of pages. A separate list of pages is | 47 | * The ring buffer is made up of a list of pages. A separate list of pages is |
26 | * allocated for each CPU. A writer may only write to a buffer that is | 48 | * allocated for each CPU. A writer may only write to a buffer that is |
27 | * associated with the CPU it is currently executing on. A reader may read | 49 | * associated with the CPU it is currently executing on. A reader may read |
@@ -340,6 +362,28 @@ static inline int test_time_stamp(u64 delta) | |||
340 | 362 | ||
341 | #define BUF_PAGE_SIZE (PAGE_SIZE - BUF_PAGE_HDR_SIZE) | 363 | #define BUF_PAGE_SIZE (PAGE_SIZE - BUF_PAGE_HDR_SIZE) |
342 | 364 | ||
365 | int ring_buffer_print_page_header(struct trace_seq *s) | ||
366 | { | ||
367 | struct buffer_data_page field; | ||
368 | int ret; | ||
369 | |||
370 | ret = trace_seq_printf(s, "\tfield: u64 timestamp;\t" | ||
371 | "offset:0;\tsize:%u;\n", | ||
372 | (unsigned int)sizeof(field.time_stamp)); | ||
373 | |||
374 | ret = trace_seq_printf(s, "\tfield: local_t commit;\t" | ||
375 | "offset:%u;\tsize:%u;\n", | ||
376 | (unsigned int)offsetof(typeof(field), commit), | ||
377 | (unsigned int)sizeof(field.commit)); | ||
378 | |||
379 | ret = trace_seq_printf(s, "\tfield: char data;\t" | ||
380 | "offset:%u;\tsize:%u;\n", | ||
381 | (unsigned int)offsetof(typeof(field), data), | ||
382 | (unsigned int)BUF_PAGE_SIZE); | ||
383 | |||
384 | return ret; | ||
385 | } | ||
386 | |||
343 | /* | 387 | /* |
344 | * head_page == tail_page && head == tail then buffer is empty. | 388 | * head_page == tail_page && head == tail then buffer is empty. |
345 | */ | 389 | */ |
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index f81d6eec4e43..7163a2bb021a 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
@@ -610,6 +610,30 @@ subsystem_filter_write(struct file *filp, const char __user *ubuf, size_t cnt, | |||
610 | return cnt; | 610 | return cnt; |
611 | } | 611 | } |
612 | 612 | ||
613 | static ssize_t | ||
614 | show_header(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) | ||
615 | { | ||
616 | int (*func)(struct trace_seq *s) = filp->private_data; | ||
617 | struct trace_seq *s; | ||
618 | int r; | ||
619 | |||
620 | if (*ppos) | ||
621 | return 0; | ||
622 | |||
623 | s = kmalloc(sizeof(*s), GFP_KERNEL); | ||
624 | if (!s) | ||
625 | return -ENOMEM; | ||
626 | |||
627 | trace_seq_init(s); | ||
628 | |||
629 | func(s); | ||
630 | r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len); | ||
631 | |||
632 | kfree(s); | ||
633 | |||
634 | return r; | ||
635 | } | ||
636 | |||
613 | static const struct seq_operations show_event_seq_ops = { | 637 | static const struct seq_operations show_event_seq_ops = { |
614 | .start = t_start, | 638 | .start = t_start, |
615 | .next = t_next, | 639 | .next = t_next, |
@@ -667,6 +691,11 @@ static const struct file_operations ftrace_subsystem_filter_fops = { | |||
667 | .write = subsystem_filter_write, | 691 | .write = subsystem_filter_write, |
668 | }; | 692 | }; |
669 | 693 | ||
694 | static const struct file_operations ftrace_show_header_fops = { | ||
695 | .open = tracing_open_generic, | ||
696 | .read = show_header, | ||
697 | }; | ||
698 | |||
670 | static struct dentry *event_trace_events_dir(void) | 699 | static struct dentry *event_trace_events_dir(void) |
671 | { | 700 | { |
672 | static struct dentry *d_tracer; | 701 | static struct dentry *d_tracer; |
@@ -909,6 +938,15 @@ static __init int event_trace_init(void) | |||
909 | if (!d_events) | 938 | if (!d_events) |
910 | return 0; | 939 | return 0; |
911 | 940 | ||
941 | /* ring buffer internal formats */ | ||
942 | trace_create_file("header_page", 0444, d_events, | ||
943 | ring_buffer_print_page_header, | ||
944 | &ftrace_show_header_fops); | ||
945 | |||
946 | trace_create_file("header_event", 0444, d_events, | ||
947 | ring_buffer_print_entry_header, | ||
948 | &ftrace_show_header_fops); | ||
949 | |||
912 | for_each_event(call, __start_ftrace_events, __stop_ftrace_events) { | 950 | for_each_event(call, __start_ftrace_events, __stop_ftrace_events) { |
913 | /* The linker may leave blanks */ | 951 | /* The linker may leave blanks */ |
914 | if (!call->name) | 952 | if (!call->name) |