diff options
Diffstat (limited to 'kernel/trace')
-rw-r--r-- | kernel/trace/trace.h | 1 | ||||
-rw-r--r-- | kernel/trace/trace_events.c | 56 | ||||
-rw-r--r-- | kernel/trace/trace_events_stage_2.h | 52 | ||||
-rw-r--r-- | kernel/trace/trace_events_stage_3.h | 2 |
4 files changed, 110 insertions, 1 deletions
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index cf6ba4181b14..e606633fb498 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -754,6 +754,7 @@ struct ftrace_event_call { | |||
754 | int (*raw_init)(void); | 754 | int (*raw_init)(void); |
755 | int (*raw_reg)(void); | 755 | int (*raw_reg)(void); |
756 | void (*raw_unreg)(void); | 756 | void (*raw_unreg)(void); |
757 | int (*show_format)(struct trace_seq *s); | ||
757 | }; | 758 | }; |
758 | 759 | ||
759 | void event_trace_printk(unsigned long ip, const char *fmt, ...); | 760 | void event_trace_printk(unsigned long ip, const char *fmt, ...); |
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 26069fa6b3b0..d57a772981c1 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
@@ -3,6 +3,9 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2008 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> | 4 | * Copyright (C) 2008 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> |
5 | * | 5 | * |
6 | * - Added format output of fields of the trace point. | ||
7 | * This was based off of work by Tom Zanussi <tzanussi@gmail.com>. | ||
8 | * | ||
6 | */ | 9 | */ |
7 | 10 | ||
8 | #include <linux/debugfs.h> | 11 | #include <linux/debugfs.h> |
@@ -444,6 +447,42 @@ event_available_types_read(struct file *filp, char __user *ubuf, size_t cnt, | |||
444 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); | 447 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); |
445 | } | 448 | } |
446 | 449 | ||
450 | static ssize_t | ||
451 | event_format_read(struct file *filp, char __user *ubuf, size_t cnt, | ||
452 | loff_t *ppos) | ||
453 | { | ||
454 | struct ftrace_event_call *call = filp->private_data; | ||
455 | struct trace_seq *s; | ||
456 | char *buf; | ||
457 | int r; | ||
458 | |||
459 | s = kmalloc(sizeof(*s), GFP_KERNEL); | ||
460 | if (!s) | ||
461 | return -ENOMEM; | ||
462 | |||
463 | trace_seq_init(s); | ||
464 | |||
465 | if (*ppos) | ||
466 | return 0; | ||
467 | |||
468 | r = call->show_format(s); | ||
469 | if (!r) { | ||
470 | /* | ||
471 | * ug! The format output is bigger than a PAGE!! | ||
472 | */ | ||
473 | buf = "FORMAT TOO BIG\n"; | ||
474 | r = simple_read_from_buffer(ubuf, cnt, ppos, | ||
475 | buf, strlen(buf)); | ||
476 | goto out; | ||
477 | } | ||
478 | |||
479 | r = simple_read_from_buffer(ubuf, cnt, ppos, | ||
480 | s->buffer, s->len); | ||
481 | out: | ||
482 | kfree(s); | ||
483 | return r; | ||
484 | } | ||
485 | |||
447 | static const struct seq_operations show_event_seq_ops = { | 486 | static const struct seq_operations show_event_seq_ops = { |
448 | .start = t_start, | 487 | .start = t_start, |
449 | .next = t_next, | 488 | .next = t_next, |
@@ -490,6 +529,11 @@ static const struct file_operations ftrace_available_types_fops = { | |||
490 | .read = event_available_types_read, | 529 | .read = event_available_types_read, |
491 | }; | 530 | }; |
492 | 531 | ||
532 | static const struct file_operations ftrace_event_format_fops = { | ||
533 | .open = tracing_open_generic, | ||
534 | .read = event_format_read, | ||
535 | }; | ||
536 | |||
493 | static struct dentry *event_trace_events_dir(void) | 537 | static struct dentry *event_trace_events_dir(void) |
494 | { | 538 | { |
495 | static struct dentry *d_tracer; | 539 | static struct dentry *d_tracer; |
@@ -602,7 +646,17 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events) | |||
602 | &ftrace_available_types_fops); | 646 | &ftrace_available_types_fops); |
603 | if (!entry) | 647 | if (!entry) |
604 | pr_warning("Could not create debugfs " | 648 | pr_warning("Could not create debugfs " |
605 | "'%s/type' available_types\n", call->name); | 649 | "'%s/available_types' entry\n", call->name); |
650 | |||
651 | /* A trace may not want to export its format */ | ||
652 | if (!call->show_format) | ||
653 | return 0; | ||
654 | |||
655 | entry = debugfs_create_file("format", 0444, call->dir, call, | ||
656 | &ftrace_event_format_fops); | ||
657 | if (!entry) | ||
658 | pr_warning("Could not create debugfs " | ||
659 | "'%s/format' entry\n", call->name); | ||
606 | 660 | ||
607 | return 0; | 661 | return 0; |
608 | } | 662 | } |
diff --git a/kernel/trace/trace_events_stage_2.h b/kernel/trace/trace_events_stage_2.h index dc79fe3a2ecb..3a80ea4e92cb 100644 --- a/kernel/trace/trace_events_stage_2.h +++ b/kernel/trace/trace_events_stage_2.h | |||
@@ -74,3 +74,55 @@ ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \ | |||
74 | } | 74 | } |
75 | 75 | ||
76 | #include <trace/trace_event_types.h> | 76 | #include <trace/trace_event_types.h> |
77 | |||
78 | /* | ||
79 | * Setup the showing format of trace point. | ||
80 | * | ||
81 | * int | ||
82 | * ftrace_format_##call(struct trace_seq *s) | ||
83 | * { | ||
84 | * struct ftrace_raw_##call field; | ||
85 | * int ret; | ||
86 | * | ||
87 | * ret = trace_seq_printf(s, #type " " #item ";" | ||
88 | * " size:%d; offset:%d;\n", | ||
89 | * sizeof(field.type), | ||
90 | * offsetof(struct ftrace_raw_##call, | ||
91 | * item)); | ||
92 | * | ||
93 | * } | ||
94 | */ | ||
95 | |||
96 | #undef TRACE_FIELD | ||
97 | #define TRACE_FIELD(type, item, assign) \ | ||
98 | ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \ | ||
99 | "offset:%lu;\tsize:%lu;\n", \ | ||
100 | offsetof(typeof(field), item), \ | ||
101 | sizeof(field.item)); \ | ||
102 | if (!ret) \ | ||
103 | return 0; | ||
104 | |||
105 | |||
106 | #undef TRACE_FIELD_SPECIAL | ||
107 | #define TRACE_FIELD_SPECIAL(type_item, item, cmd) \ | ||
108 | ret = trace_seq_printf(s, "\tfield special:" #type_item ";\t" \ | ||
109 | "offset:%lu;\tsize:%lu;\n", \ | ||
110 | offsetof(typeof(field), item), \ | ||
111 | sizeof(field.item)); \ | ||
112 | if (!ret) \ | ||
113 | return 0; | ||
114 | |||
115 | #undef TRACE_EVENT_FORMAT | ||
116 | #define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt) \ | ||
117 | int \ | ||
118 | ftrace_format_##call(struct trace_seq *s) \ | ||
119 | { \ | ||
120 | struct ftrace_raw_##call field; \ | ||
121 | int ret; \ | ||
122 | \ | ||
123 | tstruct; \ | ||
124 | \ | ||
125 | return ret; \ | ||
126 | } | ||
127 | |||
128 | #include <trace/trace_event_types.h> | ||
diff --git a/kernel/trace/trace_events_stage_3.h b/kernel/trace/trace_events_stage_3.h index 2ab65e958223..c62a4d2a5283 100644 --- a/kernel/trace/trace_events_stage_3.h +++ b/kernel/trace/trace_events_stage_3.h | |||
@@ -101,6 +101,7 @@ | |||
101 | * .raw_init = ftrace_raw_init_event_<call>, | 101 | * .raw_init = ftrace_raw_init_event_<call>, |
102 | * .raw_reg = ftrace_raw_reg_event_<call>, | 102 | * .raw_reg = ftrace_raw_reg_event_<call>, |
103 | * .raw_unreg = ftrace_raw_unreg_event_<call>, | 103 | * .raw_unreg = ftrace_raw_unreg_event_<call>, |
104 | * .show_format = ftrace_format_<call>, | ||
104 | * } | 105 | * } |
105 | * | 106 | * |
106 | */ | 107 | */ |
@@ -230,4 +231,5 @@ __attribute__((section("_ftrace_events"))) event_##call = { \ | |||
230 | .raw_init = ftrace_raw_init_event_##call, \ | 231 | .raw_init = ftrace_raw_init_event_##call, \ |
231 | .raw_reg = ftrace_raw_reg_event_##call, \ | 232 | .raw_reg = ftrace_raw_reg_event_##call, \ |
232 | .raw_unreg = ftrace_raw_unreg_event_##call, \ | 233 | .raw_unreg = ftrace_raw_unreg_event_##call, \ |
234 | .show_format = ftrace_format_##call, \ | ||
233 | } | 235 | } |