diff options
-rw-r--r-- | include/trace/sched_event_types.h | 7 | ||||
-rw-r--r-- | kernel/trace/trace.c | 17 | ||||
-rw-r--r-- | kernel/trace/trace.h | 9 | ||||
-rw-r--r-- | kernel/trace/trace_events.c | 94 | ||||
-rw-r--r-- | kernel/trace/trace_events_stage_1.h | 2 | ||||
-rw-r--r-- | kernel/trace/trace_events_stage_2.h | 58 | ||||
-rw-r--r-- | kernel/trace/trace_events_stage_3.h | 16 |
7 files changed, 188 insertions, 15 deletions
diff --git a/include/trace/sched_event_types.h b/include/trace/sched_event_types.h index ba059c10b58a..a6de5c1601a0 100644 --- a/include/trace/sched_event_types.h +++ b/include/trace/sched_event_types.h | |||
@@ -71,10 +71,15 @@ TRACE_EVENT_FORMAT(sched_switch, | |||
71 | TRACE_STRUCT( | 71 | TRACE_STRUCT( |
72 | TRACE_FIELD(pid_t, prev_pid, prev->pid) | 72 | TRACE_FIELD(pid_t, prev_pid, prev->pid) |
73 | TRACE_FIELD(int, prev_prio, prev->prio) | 73 | TRACE_FIELD(int, prev_prio, prev->prio) |
74 | TRACE_FIELD_SPECIAL(char next_comm[TASK_COMM_LEN], | ||
75 | next_comm, | ||
76 | TPCMD(memcpy(TRACE_ENTRY->next_comm, | ||
77 | next->comm, | ||
78 | TASK_COMM_LEN))) | ||
74 | TRACE_FIELD(pid_t, next_pid, next->pid) | 79 | TRACE_FIELD(pid_t, next_pid, next->pid) |
75 | TRACE_FIELD(int, next_prio, next->prio) | 80 | TRACE_FIELD(int, next_prio, next->prio) |
76 | ), | 81 | ), |
77 | TPRAWFMT("prev %d:%d ==> next %d:%d") | 82 | TPRAWFMT("prev %d:%d ==> next %s:%d:%d") |
78 | ); | 83 | ); |
79 | 84 | ||
80 | TRACE_EVENT_FORMAT(sched_migrate_task, | 85 | TRACE_EVENT_FORMAT(sched_migrate_task, |
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index c5e39cd7310d..ea055aa21cd9 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -342,13 +342,6 @@ __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu) | |||
342 | tracing_record_cmdline(tsk); | 342 | tracing_record_cmdline(tsk); |
343 | } | 343 | } |
344 | 344 | ||
345 | static void | ||
346 | trace_seq_reset(struct trace_seq *s) | ||
347 | { | ||
348 | s->len = 0; | ||
349 | s->readpos = 0; | ||
350 | } | ||
351 | |||
352 | ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, size_t cnt) | 345 | ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, size_t cnt) |
353 | { | 346 | { |
354 | int len; | 347 | int len; |
@@ -395,7 +388,7 @@ trace_print_seq(struct seq_file *m, struct trace_seq *s) | |||
395 | s->buffer[len] = 0; | 388 | s->buffer[len] = 0; |
396 | seq_puts(m, s->buffer); | 389 | seq_puts(m, s->buffer); |
397 | 390 | ||
398 | trace_seq_reset(s); | 391 | trace_seq_init(s); |
399 | } | 392 | } |
400 | 393 | ||
401 | /** | 394 | /** |
@@ -2620,7 +2613,7 @@ tracing_read_pipe(struct file *filp, char __user *ubuf, | |||
2620 | if (sret != -EBUSY) | 2613 | if (sret != -EBUSY) |
2621 | return sret; | 2614 | return sret; |
2622 | 2615 | ||
2623 | trace_seq_reset(&iter->seq); | 2616 | trace_seq_init(&iter->seq); |
2624 | 2617 | ||
2625 | /* copy the tracer to avoid using a global lock all around */ | 2618 | /* copy the tracer to avoid using a global lock all around */ |
2626 | mutex_lock(&trace_types_lock); | 2619 | mutex_lock(&trace_types_lock); |
@@ -2682,7 +2675,7 @@ waitagain: | |||
2682 | /* Now copy what we have to the user */ | 2675 | /* Now copy what we have to the user */ |
2683 | sret = trace_seq_to_user(&iter->seq, ubuf, cnt); | 2676 | sret = trace_seq_to_user(&iter->seq, ubuf, cnt); |
2684 | if (iter->seq.readpos >= iter->seq.len) | 2677 | if (iter->seq.readpos >= iter->seq.len) |
2685 | trace_seq_reset(&iter->seq); | 2678 | trace_seq_init(&iter->seq); |
2686 | 2679 | ||
2687 | /* | 2680 | /* |
2688 | * If there was nothing to send to user, inspite of consuming trace | 2681 | * If there was nothing to send to user, inspite of consuming trace |
@@ -2819,7 +2812,7 @@ static ssize_t tracing_splice_read_pipe(struct file *filp, | |||
2819 | partial[i].offset = 0; | 2812 | partial[i].offset = 0; |
2820 | partial[i].len = iter->seq.len; | 2813 | partial[i].len = iter->seq.len; |
2821 | 2814 | ||
2822 | trace_seq_reset(&iter->seq); | 2815 | trace_seq_init(&iter->seq); |
2823 | } | 2816 | } |
2824 | 2817 | ||
2825 | mutex_unlock(&iter->mutex); | 2818 | mutex_unlock(&iter->mutex); |
@@ -3631,7 +3624,7 @@ trace_printk_seq(struct trace_seq *s) | |||
3631 | 3624 | ||
3632 | printk(KERN_TRACE "%s", s->buffer); | 3625 | printk(KERN_TRACE "%s", s->buffer); |
3633 | 3626 | ||
3634 | trace_seq_reset(s); | 3627 | trace_seq_init(s); |
3635 | } | 3628 | } |
3636 | 3629 | ||
3637 | void ftrace_dump(void) | 3630 | void ftrace_dump(void) |
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index f6fa0b9f83a8..e606633fb498 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -395,6 +395,14 @@ struct trace_seq { | |||
395 | unsigned int readpos; | 395 | unsigned int readpos; |
396 | }; | 396 | }; |
397 | 397 | ||
398 | static inline void | ||
399 | trace_seq_init(struct trace_seq *s) | ||
400 | { | ||
401 | s->len = 0; | ||
402 | s->readpos = 0; | ||
403 | } | ||
404 | |||
405 | |||
398 | #define TRACE_PIPE_ALL_CPU -1 | 406 | #define TRACE_PIPE_ALL_CPU -1 |
399 | 407 | ||
400 | /* | 408 | /* |
@@ -746,6 +754,7 @@ struct ftrace_event_call { | |||
746 | int (*raw_init)(void); | 754 | int (*raw_init)(void); |
747 | int (*raw_reg)(void); | 755 | int (*raw_reg)(void); |
748 | void (*raw_unreg)(void); | 756 | void (*raw_unreg)(void); |
757 | int (*show_format)(struct trace_seq *s); | ||
749 | }; | 758 | }; |
750 | 759 | ||
751 | 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 1d07f800a9ce..210e71ff82db 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> |
@@ -10,10 +13,12 @@ | |||
10 | #include <linux/module.h> | 13 | #include <linux/module.h> |
11 | #include <linux/ctype.h> | 14 | #include <linux/ctype.h> |
12 | 15 | ||
13 | #include "trace.h" | 16 | #include "trace_output.h" |
14 | 17 | ||
15 | #define TRACE_SYSTEM "TRACE_SYSTEM" | 18 | #define TRACE_SYSTEM "TRACE_SYSTEM" |
16 | 19 | ||
20 | static DEFINE_MUTEX(event_mutex); | ||
21 | |||
17 | #define events_for_each(event) \ | 22 | #define events_for_each(event) \ |
18 | for (event = __start_ftrace_events; \ | 23 | for (event = __start_ftrace_events; \ |
19 | (unsigned long)event < (unsigned long)__stop_ftrace_events; \ | 24 | (unsigned long)event < (unsigned long)__stop_ftrace_events; \ |
@@ -104,6 +109,7 @@ static int ftrace_set_clr_event(char *buf, int set) | |||
104 | event = NULL; | 109 | event = NULL; |
105 | } | 110 | } |
106 | 111 | ||
112 | mutex_lock(&event_mutex); | ||
107 | events_for_each(call) { | 113 | events_for_each(call) { |
108 | 114 | ||
109 | if (!call->name) | 115 | if (!call->name) |
@@ -124,6 +130,8 @@ static int ftrace_set_clr_event(char *buf, int set) | |||
124 | 130 | ||
125 | ret = 0; | 131 | ret = 0; |
126 | } | 132 | } |
133 | mutex_unlock(&event_mutex); | ||
134 | |||
127 | return ret; | 135 | return ret; |
128 | } | 136 | } |
129 | 137 | ||
@@ -324,7 +332,9 @@ event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt, | |||
324 | switch (val) { | 332 | switch (val) { |
325 | case 0: | 333 | case 0: |
326 | case 1: | 334 | case 1: |
335 | mutex_lock(&event_mutex); | ||
327 | ftrace_event_enable_disable(call, val); | 336 | ftrace_event_enable_disable(call, val); |
337 | mutex_unlock(&event_mutex); | ||
328 | break; | 338 | break; |
329 | 339 | ||
330 | default: | 340 | default: |
@@ -437,6 +447,71 @@ event_available_types_read(struct file *filp, char __user *ubuf, size_t cnt, | |||
437 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); | 447 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); |
438 | } | 448 | } |
439 | 449 | ||
450 | #undef FIELD | ||
451 | #define FIELD(type, name) \ | ||
452 | #type, #name, offsetof(typeof(field), name), sizeof(field.name) | ||
453 | |||
454 | static int trace_write_header(struct trace_seq *s) | ||
455 | { | ||
456 | struct trace_entry field; | ||
457 | |||
458 | /* struct trace_entry */ | ||
459 | return trace_seq_printf(s, | ||
460 | "\tfield:%s %s;\toffset:%lu;\tsize:%lu;\n" | ||
461 | "\tfield:%s %s;\toffset:%lu;\tsize:%lu;\n" | ||
462 | "\tfield:%s %s;\toffset:%lu;\tsize:%lu;\n" | ||
463 | "\tfield:%s %s;\toffset:%lu;\tsize:%lu;\n" | ||
464 | "\tfield:%s %s;\toffset:%lu;\tsize:%lu;\n" | ||
465 | "\n", | ||
466 | FIELD(unsigned char, type), | ||
467 | FIELD(unsigned char, flags), | ||
468 | FIELD(unsigned char, preempt_count), | ||
469 | FIELD(int, pid), | ||
470 | FIELD(int, tgid)); | ||
471 | } | ||
472 | static ssize_t | ||
473 | event_format_read(struct file *filp, char __user *ubuf, size_t cnt, | ||
474 | loff_t *ppos) | ||
475 | { | ||
476 | struct ftrace_event_call *call = filp->private_data; | ||
477 | struct trace_seq *s; | ||
478 | char *buf; | ||
479 | int r; | ||
480 | |||
481 | s = kmalloc(sizeof(*s), GFP_KERNEL); | ||
482 | if (!s) | ||
483 | return -ENOMEM; | ||
484 | |||
485 | trace_seq_init(s); | ||
486 | |||
487 | if (*ppos) | ||
488 | return 0; | ||
489 | |||
490 | /* If any of the first writes fail, so will the show_format. */ | ||
491 | |||
492 | trace_seq_printf(s, "name: %s\n", call->name); | ||
493 | trace_seq_printf(s, "ID: %d\n", call->id); | ||
494 | trace_seq_printf(s, "format:\n"); | ||
495 | trace_write_header(s); | ||
496 | |||
497 | r = call->show_format(s); | ||
498 | if (!r) { | ||
499 | /* | ||
500 | * ug! The format output is bigger than a PAGE!! | ||
501 | */ | ||
502 | buf = "FORMAT TOO BIG\n"; | ||
503 | r = simple_read_from_buffer(ubuf, cnt, ppos, | ||
504 | buf, strlen(buf)); | ||
505 | goto out; | ||
506 | } | ||
507 | |||
508 | r = simple_read_from_buffer(ubuf, cnt, ppos, | ||
509 | s->buffer, s->len); | ||
510 | out: | ||
511 | kfree(s); | ||
512 | return r; | ||
513 | } | ||
514 | |||
440 | static const struct seq_operations show_event_seq_ops = { | 515 | static const struct seq_operations show_event_seq_ops = { |
441 | .start = t_start, | 516 | .start = t_start, |
442 | .next = t_next, | 517 | .next = t_next, |
@@ -483,6 +558,11 @@ static const struct file_operations ftrace_available_types_fops = { | |||
483 | .read = event_available_types_read, | 558 | .read = event_available_types_read, |
484 | }; | 559 | }; |
485 | 560 | ||
561 | static const struct file_operations ftrace_event_format_fops = { | ||
562 | .open = tracing_open_generic, | ||
563 | .read = event_format_read, | ||
564 | }; | ||
565 | |||
486 | static struct dentry *event_trace_events_dir(void) | 566 | static struct dentry *event_trace_events_dir(void) |
487 | { | 567 | { |
488 | static struct dentry *d_tracer; | 568 | static struct dentry *d_tracer; |
@@ -595,7 +675,17 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events) | |||
595 | &ftrace_available_types_fops); | 675 | &ftrace_available_types_fops); |
596 | if (!entry) | 676 | if (!entry) |
597 | pr_warning("Could not create debugfs " | 677 | pr_warning("Could not create debugfs " |
598 | "'%s/type' available_types\n", call->name); | 678 | "'%s/available_types' entry\n", call->name); |
679 | |||
680 | /* A trace may not want to export its format */ | ||
681 | if (!call->show_format) | ||
682 | return 0; | ||
683 | |||
684 | entry = debugfs_create_file("format", 0444, call->dir, call, | ||
685 | &ftrace_event_format_fops); | ||
686 | if (!entry) | ||
687 | pr_warning("Could not create debugfs " | ||
688 | "'%s/format' entry\n", call->name); | ||
599 | 689 | ||
600 | return 0; | 690 | return 0; |
601 | } | 691 | } |
diff --git a/kernel/trace/trace_events_stage_1.h b/kernel/trace/trace_events_stage_1.h index fd3bf9382d37..3830a731424c 100644 --- a/kernel/trace/trace_events_stage_1.h +++ b/kernel/trace/trace_events_stage_1.h | |||
@@ -30,5 +30,7 @@ | |||
30 | 30 | ||
31 | #define TRACE_FIELD(type, item, assign) \ | 31 | #define TRACE_FIELD(type, item, assign) \ |
32 | type item; | 32 | type item; |
33 | #define TRACE_FIELD_SPECIAL(type_item, item, cmd) \ | ||
34 | type_item; | ||
33 | 35 | ||
34 | #include <trace/trace_event_types.h> | 36 | #include <trace/trace_event_types.h> |
diff --git a/kernel/trace/trace_events_stage_2.h b/kernel/trace/trace_events_stage_2.h index 3eaaef5f19e1..b1cebba1d9b4 100644 --- a/kernel/trace/trace_events_stage_2.h +++ b/kernel/trace/trace_events_stage_2.h | |||
@@ -39,6 +39,10 @@ | |||
39 | #define TRACE_FIELD(type, item, assign) \ | 39 | #define TRACE_FIELD(type, item, assign) \ |
40 | field->item, | 40 | field->item, |
41 | 41 | ||
42 | #undef TRACE_FIELD_SPECIAL | ||
43 | #define TRACE_FIELD_SPECIAL(type_item, item, cmd) \ | ||
44 | field->item, | ||
45 | |||
42 | 46 | ||
43 | #undef TPRAWFMT | 47 | #undef TPRAWFMT |
44 | #define TPRAWFMT(args...) args | 48 | #define TPRAWFMT(args...) args |
@@ -70,3 +74,57 @@ ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \ | |||
70 | } | 74 | } |
71 | 75 | ||
72 | #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 | trace_seq_printf(s, "\nprint fmt: \"%s\"\n", tpfmt); \ | ||
126 | \ | ||
127 | return ret; \ | ||
128 | } | ||
129 | |||
130 | #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 7a161c49deb4..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 | */ |
@@ -147,6 +148,20 @@ __attribute__((section("_ftrace_events"))) event_##call = { \ | |||
147 | #define TRACE_FIELD(type, item, assign)\ | 148 | #define TRACE_FIELD(type, item, assign)\ |
148 | entry->item = assign; | 149 | entry->item = assign; |
149 | 150 | ||
151 | #undef TRACE_FIELD | ||
152 | #define TRACE_FIELD(type, item, assign)\ | ||
153 | entry->item = assign; | ||
154 | |||
155 | #undef TPCMD | ||
156 | #define TPCMD(cmd...) cmd | ||
157 | |||
158 | #undef TRACE_ENTRY | ||
159 | #define TRACE_ENTRY entry | ||
160 | |||
161 | #undef TRACE_FIELD_SPECIAL | ||
162 | #define TRACE_FIELD_SPECIAL(type_item, item, cmd) \ | ||
163 | cmd; | ||
164 | |||
150 | #undef TRACE_EVENT_FORMAT | 165 | #undef TRACE_EVENT_FORMAT |
151 | #define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt) \ | 166 | #define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt) \ |
152 | _TRACE_FORMAT(call, PARAMS(proto), PARAMS(args), PARAMS(fmt)) \ | 167 | _TRACE_FORMAT(call, PARAMS(proto), PARAMS(args), PARAMS(fmt)) \ |
@@ -216,4 +231,5 @@ __attribute__((section("_ftrace_events"))) event_##call = { \ | |||
216 | .raw_init = ftrace_raw_init_event_##call, \ | 231 | .raw_init = ftrace_raw_init_event_##call, \ |
217 | .raw_reg = ftrace_raw_reg_event_##call, \ | 232 | .raw_reg = ftrace_raw_reg_event_##call, \ |
218 | .raw_unreg = ftrace_raw_unreg_event_##call, \ | 233 | .raw_unreg = ftrace_raw_unreg_event_##call, \ |
234 | .show_format = ftrace_format_##call, \ | ||
219 | } | 235 | } |