diff options
-rw-r--r-- | include/linux/ftrace.h | 25 | ||||
-rw-r--r-- | include/linux/kernel.h | 34 | ||||
-rw-r--r-- | include/linux/module.h | 2 | ||||
-rw-r--r-- | kernel/trace/Kconfig | 7 | ||||
-rw-r--r-- | kernel/trace/Makefile | 2 | ||||
-rw-r--r-- | kernel/trace/trace.c | 212 | ||||
-rw-r--r-- | kernel/trace/trace.h | 14 | ||||
-rw-r--r-- | kernel/trace/trace_functions_graph.c | 6 | ||||
-rw-r--r-- | kernel/trace/trace_mmiotrace.c | 9 | ||||
-rw-r--r-- | kernel/trace/trace_output.c | 70 | ||||
-rw-r--r-- | kernel/trace/trace_output.h | 2 | ||||
-rw-r--r-- | kernel/trace/trace_printk.c (renamed from kernel/trace/trace_bprintk.c) | 84 |
12 files changed, 158 insertions, 309 deletions
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 1cc8ca453a9b..e1583f2639b0 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h | |||
@@ -223,31 +223,6 @@ extern int ftrace_make_nop(struct module *mod, | |||
223 | */ | 223 | */ |
224 | extern int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr); | 224 | extern int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr); |
225 | 225 | ||
226 | #ifdef CONFIG_TRACE_BPRINTK | ||
227 | extern int trace_vbprintk(unsigned long ip, const char *fmt, va_list args); | ||
228 | extern int __trace_bprintk(unsigned long ip, const char *fmt, ...) | ||
229 | __attribute__ ((format (printf, 2, 3))); | ||
230 | |||
231 | static inline void ____trace_bprintk_check_format(const char *fmt, ...) | ||
232 | __attribute__ ((format (printf, 1, 2))); | ||
233 | static inline void ____trace_bprintk_check_format(const char *fmt, ...) {} | ||
234 | #define __trace_bprintk_check_format(fmt, args...) \ | ||
235 | do { \ | ||
236 | if (0) \ | ||
237 | ____trace_bprintk_check_format(fmt, ##args); \ | ||
238 | } while (0) | ||
239 | |||
240 | #define trace_bprintk(fmt, args...) \ | ||
241 | do { \ | ||
242 | static char *__attribute__((section("__trace_bprintk_fmt"))) \ | ||
243 | trace_bprintk_fmt = fmt; \ | ||
244 | __trace_bprintk_check_format(fmt, ##args); \ | ||
245 | __trace_bprintk(_THIS_IP_, trace_bprintk_fmt, ##args); \ | ||
246 | } while (0) | ||
247 | #else | ||
248 | #define trace_bprintk trace_printk | ||
249 | #endif | ||
250 | |||
251 | /* May be defined in arch */ | 226 | /* May be defined in arch */ |
252 | extern int ftrace_arch_read_dyn_info(char *buf, int size); | 227 | extern int ftrace_arch_read_dyn_info(char *buf, int size); |
253 | 228 | ||
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 7aef15c4645e..4e726b9a71ec 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
@@ -423,6 +423,16 @@ extern void ftrace_off_permanent(void); | |||
423 | extern void | 423 | extern void |
424 | ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3); | 424 | ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3); |
425 | 425 | ||
426 | static inline void __attribute__ ((format (printf, 1, 2))) | ||
427 | ____trace_printk_check_format(const char *fmt, ...) | ||
428 | { | ||
429 | } | ||
430 | #define __trace_printk_check_format(fmt, args...) \ | ||
431 | do { \ | ||
432 | if (0) \ | ||
433 | ____trace_printk_check_format(fmt, ##args); \ | ||
434 | } while (0) | ||
435 | |||
426 | /** | 436 | /** |
427 | * trace_printk - printf formatting in the ftrace buffer | 437 | * trace_printk - printf formatting in the ftrace buffer |
428 | * @fmt: the printf format for printing | 438 | * @fmt: the printf format for printing |
@@ -439,13 +449,31 @@ ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3); | |||
439 | * Please refrain from leaving trace_printks scattered around in | 449 | * Please refrain from leaving trace_printks scattered around in |
440 | * your code. | 450 | * your code. |
441 | */ | 451 | */ |
442 | # define trace_printk(fmt...) __trace_printk(_THIS_IP_, fmt) | 452 | |
453 | #define trace_printk(fmt, args...) \ | ||
454 | do { \ | ||
455 | static const char *trace_printk_fmt \ | ||
456 | __attribute__((section("__trace_printk_fmt"))); \ | ||
457 | trace_printk_fmt = fmt; \ | ||
458 | __trace_printk_check_format(fmt, ##args); \ | ||
459 | __trace_printk(_THIS_IP_, trace_printk_fmt, ##args); \ | ||
460 | } while (0) | ||
461 | |||
443 | extern int | 462 | extern int |
444 | __trace_printk(unsigned long ip, const char *fmt, ...) | 463 | __trace_printk(unsigned long ip, const char *fmt, ...) |
445 | __attribute__ ((format (printf, 2, 3))); | 464 | __attribute__ ((format (printf, 2, 3))); |
446 | # define ftrace_vprintk(fmt, ap) __trace_printk(_THIS_IP_, fmt, ap) | 465 | |
466 | #define ftrace_vprintk(fmt, vargs) \ | ||
467 | do { \ | ||
468 | static const char *trace_printk_fmt \ | ||
469 | __attribute__((section("__trace_printk_fmt"))); \ | ||
470 | trace_printk_fmt = fmt; \ | ||
471 | __ftrace_vprintk(_THIS_IP_, trace_printk_fmt, vargs); \ | ||
472 | } while (0) | ||
473 | |||
447 | extern int | 474 | extern int |
448 | __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap); | 475 | __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap); |
476 | |||
449 | extern void ftrace_dump(void); | 477 | extern void ftrace_dump(void); |
450 | #else | 478 | #else |
451 | static inline void | 479 | static inline void |
@@ -467,7 +495,7 @@ ftrace_vprintk(const char *fmt, va_list ap) | |||
467 | return 0; | 495 | return 0; |
468 | } | 496 | } |
469 | static inline void ftrace_dump(void) { } | 497 | static inline void ftrace_dump(void) { } |
470 | #endif | 498 | #endif /* CONFIG_TRACING */ |
471 | 499 | ||
472 | /* | 500 | /* |
473 | * Display an IP address in readable format. | 501 | * Display an IP address in readable format. |
diff --git a/include/linux/module.h b/include/linux/module.h index 8cbec972d8e7..22d9878e868c 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
@@ -329,7 +329,7 @@ struct module | |||
329 | unsigned int num_tracepoints; | 329 | unsigned int num_tracepoints; |
330 | #endif | 330 | #endif |
331 | 331 | ||
332 | #ifdef CONFIG_TRACE_BPRINTK | 332 | #ifdef CONFIG_TRACING |
333 | const char **trace_bprintk_fmt_start; | 333 | const char **trace_bprintk_fmt_start; |
334 | unsigned int num_trace_bprintk_fmt; | 334 | unsigned int num_trace_bprintk_fmt; |
335 | #endif | 335 | #endif |
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index ad8d3617d0a6..8e4a2a61cd75 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig | |||
@@ -52,6 +52,7 @@ config TRACING | |||
52 | select STACKTRACE if STACKTRACE_SUPPORT | 52 | select STACKTRACE if STACKTRACE_SUPPORT |
53 | select TRACEPOINTS | 53 | select TRACEPOINTS |
54 | select NOP_TRACER | 54 | select NOP_TRACER |
55 | select BINARY_PRINTF | ||
55 | 56 | ||
56 | # | 57 | # |
57 | # Minimum requirements an architecture has to meet for us to | 58 | # Minimum requirements an architecture has to meet for us to |
@@ -97,12 +98,6 @@ config FUNCTION_GRAPH_TRACER | |||
97 | This is done by setting the current return address on the current | 98 | This is done by setting the current return address on the current |
98 | task structure into a stack of calls. | 99 | task structure into a stack of calls. |
99 | 100 | ||
100 | config TRACE_BPRINTK | ||
101 | bool "Binary printk for tracing" | ||
102 | default y | ||
103 | depends on TRACING | ||
104 | select BINARY_PRINTF | ||
105 | |||
106 | config IRQSOFF_TRACER | 101 | config IRQSOFF_TRACER |
107 | bool "Interrupts-off Latency Tracer" | 102 | bool "Interrupts-off Latency Tracer" |
108 | default n | 103 | default n |
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile index 46557ef4c379..c7a2943796eb 100644 --- a/kernel/trace/Makefile +++ b/kernel/trace/Makefile | |||
@@ -22,7 +22,7 @@ obj-$(CONFIG_TRACING) += trace.o | |||
22 | obj-$(CONFIG_TRACING) += trace_clock.o | 22 | obj-$(CONFIG_TRACING) += trace_clock.o |
23 | obj-$(CONFIG_TRACING) += trace_output.o | 23 | obj-$(CONFIG_TRACING) += trace_output.o |
24 | obj-$(CONFIG_TRACING) += trace_stat.o | 24 | obj-$(CONFIG_TRACING) += trace_stat.o |
25 | obj-$(CONFIG_TRACE_BPRINTK) += trace_bprintk.o | 25 | obj-$(CONFIG_TRACING) += trace_printk.o |
26 | obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o | 26 | obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o |
27 | obj-$(CONFIG_SYSPROF_TRACER) += trace_sysprof.o | 27 | obj-$(CONFIG_SYSPROF_TRACER) += trace_sysprof.o |
28 | obj-$(CONFIG_FUNCTION_TRACER) += trace_functions.o | 28 | obj-$(CONFIG_FUNCTION_TRACER) += trace_functions.o |
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 46b3cd7a5752..cc94f8642485 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -1169,6 +1169,67 @@ void trace_graph_return(struct ftrace_graph_ret *trace) | |||
1169 | } | 1169 | } |
1170 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | 1170 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ |
1171 | 1171 | ||
1172 | |||
1173 | /** | ||
1174 | * trace_vprintk - write binary msg to tracing buffer | ||
1175 | * | ||
1176 | */ | ||
1177 | int trace_vprintk(unsigned long ip, int depth, const char *fmt, va_list args) | ||
1178 | { | ||
1179 | static DEFINE_SPINLOCK(trace_buf_lock); | ||
1180 | static u32 trace_buf[TRACE_BUF_SIZE]; | ||
1181 | |||
1182 | struct ring_buffer_event *event; | ||
1183 | struct trace_array *tr = &global_trace; | ||
1184 | struct trace_array_cpu *data; | ||
1185 | struct print_entry *entry; | ||
1186 | unsigned long flags; | ||
1187 | int resched; | ||
1188 | int cpu, len = 0, size, pc; | ||
1189 | |||
1190 | if (unlikely(tracing_selftest_running || tracing_disabled)) | ||
1191 | return 0; | ||
1192 | |||
1193 | /* Don't pollute graph traces with trace_vprintk internals */ | ||
1194 | pause_graph_tracing(); | ||
1195 | |||
1196 | pc = preempt_count(); | ||
1197 | resched = ftrace_preempt_disable(); | ||
1198 | cpu = raw_smp_processor_id(); | ||
1199 | data = tr->data[cpu]; | ||
1200 | |||
1201 | if (unlikely(atomic_read(&data->disabled))) | ||
1202 | goto out; | ||
1203 | |||
1204 | spin_lock_irqsave(&trace_buf_lock, flags); | ||
1205 | len = vbin_printf(trace_buf, TRACE_BUF_SIZE, fmt, args); | ||
1206 | |||
1207 | if (len > TRACE_BUF_SIZE || len < 0) | ||
1208 | goto out_unlock; | ||
1209 | |||
1210 | size = sizeof(*entry) + sizeof(u32) * len; | ||
1211 | event = trace_buffer_lock_reserve(tr, TRACE_PRINT, size, flags, pc); | ||
1212 | if (!event) | ||
1213 | goto out_unlock; | ||
1214 | entry = ring_buffer_event_data(event); | ||
1215 | entry->ip = ip; | ||
1216 | entry->depth = depth; | ||
1217 | entry->fmt = fmt; | ||
1218 | |||
1219 | memcpy(entry->buf, trace_buf, sizeof(u32) * len); | ||
1220 | ring_buffer_unlock_commit(tr->buffer, event); | ||
1221 | |||
1222 | out_unlock: | ||
1223 | spin_unlock_irqrestore(&trace_buf_lock, flags); | ||
1224 | |||
1225 | out: | ||
1226 | ftrace_preempt_enable(resched); | ||
1227 | unpause_graph_tracing(); | ||
1228 | |||
1229 | return len; | ||
1230 | } | ||
1231 | EXPORT_SYMBOL_GPL(trace_vprintk); | ||
1232 | |||
1172 | enum trace_file_type { | 1233 | enum trace_file_type { |
1173 | TRACE_FILE_LAT_FMT = 1, | 1234 | TRACE_FILE_LAT_FMT = 1, |
1174 | TRACE_FILE_ANNOTATE = 2, | 1235 | TRACE_FILE_ANNOTATE = 2, |
@@ -1564,7 +1625,7 @@ static enum print_line_t print_printk_msg_only(struct trace_iterator *iter) | |||
1564 | 1625 | ||
1565 | trace_assign_type(field, entry); | 1626 | trace_assign_type(field, entry); |
1566 | 1627 | ||
1567 | ret = trace_seq_printf(s, "%s", field->buf); | 1628 | ret = trace_seq_bprintf(s, field->fmt, field->buf); |
1568 | if (!ret) | 1629 | if (!ret) |
1569 | return TRACE_TYPE_PARTIAL_LINE; | 1630 | return TRACE_TYPE_PARTIAL_LINE; |
1570 | 1631 | ||
@@ -3714,155 +3775,6 @@ static __init int tracer_init_debugfs(void) | |||
3714 | return 0; | 3775 | return 0; |
3715 | } | 3776 | } |
3716 | 3777 | ||
3717 | int trace_vprintk(unsigned long ip, int depth, const char *fmt, va_list args) | ||
3718 | { | ||
3719 | static raw_spinlock_t trace_buf_lock = __RAW_SPIN_LOCK_UNLOCKED; | ||
3720 | static char trace_buf[TRACE_BUF_SIZE]; | ||
3721 | |||
3722 | struct ring_buffer_event *event; | ||
3723 | struct trace_array *tr = &global_trace; | ||
3724 | struct trace_array_cpu *data; | ||
3725 | int cpu, len = 0, size, pc; | ||
3726 | struct print_entry *entry; | ||
3727 | unsigned long irq_flags; | ||
3728 | |||
3729 | if (tracing_disabled || tracing_selftest_running) | ||
3730 | return 0; | ||
3731 | |||
3732 | pc = preempt_count(); | ||
3733 | preempt_disable_notrace(); | ||
3734 | cpu = raw_smp_processor_id(); | ||
3735 | data = tr->data[cpu]; | ||
3736 | |||
3737 | if (unlikely(atomic_read(&data->disabled))) | ||
3738 | goto out; | ||
3739 | |||
3740 | pause_graph_tracing(); | ||
3741 | raw_local_irq_save(irq_flags); | ||
3742 | __raw_spin_lock(&trace_buf_lock); | ||
3743 | len = vsnprintf(trace_buf, TRACE_BUF_SIZE, fmt, args); | ||
3744 | |||
3745 | len = min(len, TRACE_BUF_SIZE-1); | ||
3746 | trace_buf[len] = 0; | ||
3747 | |||
3748 | size = sizeof(*entry) + len + 1; | ||
3749 | event = trace_buffer_lock_reserve(tr, TRACE_PRINT, size, irq_flags, pc); | ||
3750 | if (!event) | ||
3751 | goto out_unlock; | ||
3752 | entry = ring_buffer_event_data(event); | ||
3753 | entry->ip = ip; | ||
3754 | entry->depth = depth; | ||
3755 | |||
3756 | memcpy(&entry->buf, trace_buf, len); | ||
3757 | entry->buf[len] = 0; | ||
3758 | ring_buffer_unlock_commit(tr->buffer, event); | ||
3759 | |||
3760 | out_unlock: | ||
3761 | __raw_spin_unlock(&trace_buf_lock); | ||
3762 | raw_local_irq_restore(irq_flags); | ||
3763 | unpause_graph_tracing(); | ||
3764 | out: | ||
3765 | preempt_enable_notrace(); | ||
3766 | |||
3767 | return len; | ||
3768 | } | ||
3769 | EXPORT_SYMBOL_GPL(trace_vprintk); | ||
3770 | |||
3771 | int __trace_printk(unsigned long ip, const char *fmt, ...) | ||
3772 | { | ||
3773 | int ret; | ||
3774 | va_list ap; | ||
3775 | |||
3776 | if (!(trace_flags & TRACE_ITER_PRINTK)) | ||
3777 | return 0; | ||
3778 | |||
3779 | va_start(ap, fmt); | ||
3780 | ret = trace_vprintk(ip, task_curr_ret_stack(current), fmt, ap); | ||
3781 | va_end(ap); | ||
3782 | return ret; | ||
3783 | } | ||
3784 | EXPORT_SYMBOL_GPL(__trace_printk); | ||
3785 | |||
3786 | int __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap) | ||
3787 | { | ||
3788 | if (!(trace_flags & TRACE_ITER_PRINTK)) | ||
3789 | return 0; | ||
3790 | |||
3791 | return trace_vprintk(ip, task_curr_ret_stack(current), fmt, ap); | ||
3792 | } | ||
3793 | EXPORT_SYMBOL_GPL(__ftrace_vprintk); | ||
3794 | |||
3795 | /** | ||
3796 | * trace_vbprintk - write binary msg to tracing buffer | ||
3797 | * | ||
3798 | * Caller must insure @fmt are valid when msg is in tracing buffer. | ||
3799 | */ | ||
3800 | int trace_vbprintk(unsigned long ip, const char *fmt, va_list args) | ||
3801 | { | ||
3802 | static DEFINE_SPINLOCK(trace_buf_lock); | ||
3803 | static u32 trace_buf[TRACE_BUF_SIZE]; | ||
3804 | |||
3805 | struct ring_buffer_event *event; | ||
3806 | struct trace_array *tr = &global_trace; | ||
3807 | struct trace_array_cpu *data; | ||
3808 | struct bprintk_entry *entry; | ||
3809 | unsigned long flags; | ||
3810 | int resched; | ||
3811 | int cpu, len = 0, size, pc; | ||
3812 | |||
3813 | if (tracing_disabled || !trace_bprintk_enable) | ||
3814 | return 0; | ||
3815 | |||
3816 | pc = preempt_count(); | ||
3817 | resched = ftrace_preempt_disable(); | ||
3818 | cpu = raw_smp_processor_id(); | ||
3819 | data = tr->data[cpu]; | ||
3820 | |||
3821 | if (unlikely(atomic_read(&data->disabled))) | ||
3822 | goto out; | ||
3823 | |||
3824 | spin_lock_irqsave(&trace_buf_lock, flags); | ||
3825 | len = vbin_printf(trace_buf, TRACE_BUF_SIZE, fmt, args); | ||
3826 | |||
3827 | if (len > TRACE_BUF_SIZE || len < 0) | ||
3828 | goto out_unlock; | ||
3829 | |||
3830 | size = sizeof(*entry) + sizeof(u32) * len; | ||
3831 | event = trace_buffer_lock_reserve(tr, TRACE_BPRINTK, size, flags, pc); | ||
3832 | if (!event) | ||
3833 | goto out_unlock; | ||
3834 | entry = ring_buffer_event_data(event); | ||
3835 | entry->ip = ip; | ||
3836 | entry->fmt = fmt; | ||
3837 | |||
3838 | memcpy(entry->buf, trace_buf, sizeof(u32) * len); | ||
3839 | ring_buffer_unlock_commit(tr->buffer, event); | ||
3840 | |||
3841 | out_unlock: | ||
3842 | spin_unlock_irqrestore(&trace_buf_lock, flags); | ||
3843 | |||
3844 | out: | ||
3845 | ftrace_preempt_enable(resched); | ||
3846 | |||
3847 | return len; | ||
3848 | } | ||
3849 | EXPORT_SYMBOL_GPL(trace_vbprintk); | ||
3850 | |||
3851 | int __trace_bprintk(unsigned long ip, const char *fmt, ...) | ||
3852 | { | ||
3853 | int ret; | ||
3854 | va_list ap; | ||
3855 | |||
3856 | if (!fmt) | ||
3857 | return 0; | ||
3858 | |||
3859 | va_start(ap, fmt); | ||
3860 | ret = trace_vbprintk(ip, fmt, ap); | ||
3861 | va_end(ap); | ||
3862 | return ret; | ||
3863 | } | ||
3864 | EXPORT_SYMBOL_GPL(__trace_bprintk); | ||
3865 | |||
3866 | static int trace_panic_handler(struct notifier_block *this, | 3778 | static int trace_panic_handler(struct notifier_block *this, |
3867 | unsigned long event, void *unused) | 3779 | unsigned long event, void *unused) |
3868 | { | 3780 | { |
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 0f5077f8f957..6140922392c8 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -20,7 +20,6 @@ enum trace_type { | |||
20 | TRACE_WAKE, | 20 | TRACE_WAKE, |
21 | TRACE_STACK, | 21 | TRACE_STACK, |
22 | TRACE_PRINT, | 22 | TRACE_PRINT, |
23 | TRACE_BPRINTK, | ||
24 | TRACE_SPECIAL, | 23 | TRACE_SPECIAL, |
25 | TRACE_MMIO_RW, | 24 | TRACE_MMIO_RW, |
26 | TRACE_MMIO_MAP, | 25 | TRACE_MMIO_MAP, |
@@ -120,16 +119,10 @@ struct userstack_entry { | |||
120 | */ | 119 | */ |
121 | struct print_entry { | 120 | struct print_entry { |
122 | struct trace_entry ent; | 121 | struct trace_entry ent; |
123 | unsigned long ip; | 122 | unsigned long ip; |
124 | int depth; | 123 | int depth; |
125 | char buf[]; | 124 | const char *fmt; |
126 | }; | 125 | u32 buf[]; |
127 | |||
128 | struct bprintk_entry { | ||
129 | struct trace_entry ent; | ||
130 | unsigned long ip; | ||
131 | const char *fmt; | ||
132 | u32 buf[]; | ||
133 | }; | 126 | }; |
134 | #ifdef CONFIG_TRACE_BPRINTK | 127 | #ifdef CONFIG_TRACE_BPRINTK |
135 | extern int trace_bprintk_enable; | 128 | extern int trace_bprintk_enable; |
@@ -296,7 +289,6 @@ extern void __ftrace_bad_type(void); | |||
296 | IF_ASSIGN(var, ent, struct stack_entry, TRACE_STACK); \ | 289 | IF_ASSIGN(var, ent, struct stack_entry, TRACE_STACK); \ |
297 | IF_ASSIGN(var, ent, struct userstack_entry, TRACE_USER_STACK);\ | 290 | IF_ASSIGN(var, ent, struct userstack_entry, TRACE_USER_STACK);\ |
298 | IF_ASSIGN(var, ent, struct print_entry, TRACE_PRINT); \ | 291 | IF_ASSIGN(var, ent, struct print_entry, TRACE_PRINT); \ |
299 | IF_ASSIGN(var, ent, struct bprintk_entry, TRACE_BPRINTK);\ | ||
300 | IF_ASSIGN(var, ent, struct special_entry, 0); \ | 292 | IF_ASSIGN(var, ent, struct special_entry, 0); \ |
301 | IF_ASSIGN(var, ent, struct trace_mmiotrace_rw, \ | 293 | IF_ASSIGN(var, ent, struct trace_mmiotrace_rw, \ |
302 | TRACE_MMIO_RW); \ | 294 | TRACE_MMIO_RW); \ |
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index e527f2f66c73..453ebd3b636e 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c | |||
@@ -742,7 +742,11 @@ print_graph_comment(struct print_entry *trace, struct trace_seq *s, | |||
742 | } | 742 | } |
743 | 743 | ||
744 | /* The comment */ | 744 | /* The comment */ |
745 | ret = trace_seq_printf(s, "/* %s", trace->buf); | 745 | ret = trace_seq_printf(s, "/* "); |
746 | if (!ret) | ||
747 | return TRACE_TYPE_PARTIAL_LINE; | ||
748 | |||
749 | ret = trace_seq_bprintf(s, trace->fmt, trace->buf); | ||
746 | if (!ret) | 750 | if (!ret) |
747 | return TRACE_TYPE_PARTIAL_LINE; | 751 | return TRACE_TYPE_PARTIAL_LINE; |
748 | 752 | ||
diff --git a/kernel/trace/trace_mmiotrace.c b/kernel/trace/trace_mmiotrace.c index c401b908e805..23e346a734ca 100644 --- a/kernel/trace/trace_mmiotrace.c +++ b/kernel/trace/trace_mmiotrace.c | |||
@@ -254,15 +254,18 @@ static enum print_line_t mmio_print_mark(struct trace_iterator *iter) | |||
254 | { | 254 | { |
255 | struct trace_entry *entry = iter->ent; | 255 | struct trace_entry *entry = iter->ent; |
256 | struct print_entry *print = (struct print_entry *)entry; | 256 | struct print_entry *print = (struct print_entry *)entry; |
257 | const char *msg = print->buf; | ||
258 | struct trace_seq *s = &iter->seq; | 257 | struct trace_seq *s = &iter->seq; |
259 | unsigned long long t = ns2usecs(iter->ts); | 258 | unsigned long long t = ns2usecs(iter->ts); |
260 | unsigned long usec_rem = do_div(t, 1000000ULL); | 259 | unsigned long usec_rem = do_div(t, USEC_PER_SEC); |
261 | unsigned secs = (unsigned long)t; | 260 | unsigned secs = (unsigned long)t; |
262 | int ret; | 261 | int ret; |
263 | 262 | ||
264 | /* The trailing newline must be in the message. */ | 263 | /* The trailing newline must be in the message. */ |
265 | ret = trace_seq_printf(s, "MARK %u.%06lu %s", secs, usec_rem, msg); | 264 | ret = trace_seq_printf(s, "MARK %u.%06lu ", secs, usec_rem); |
265 | if (!ret) | ||
266 | return TRACE_TYPE_PARTIAL_LINE; | ||
267 | |||
268 | ret = trace_seq_bprintf(s, print->fmt, print->buf); | ||
266 | if (!ret) | 269 | if (!ret) |
267 | return TRACE_TYPE_PARTIAL_LINE; | 270 | return TRACE_TYPE_PARTIAL_LINE; |
268 | 271 | ||
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c index 4ab71201862e..ef8fd661b217 100644 --- a/kernel/trace/trace_output.c +++ b/kernel/trace/trace_output.c | |||
@@ -53,8 +53,7 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...) | |||
53 | return len; | 53 | return len; |
54 | } | 54 | } |
55 | 55 | ||
56 | static int | 56 | int trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary) |
57 | trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary) | ||
58 | { | 57 | { |
59 | int len = (PAGE_SIZE - 1) - s->len; | 58 | int len = (PAGE_SIZE - 1) - s->len; |
60 | int ret; | 59 | int ret; |
@@ -834,54 +833,12 @@ static struct trace_event trace_user_stack_event = { | |||
834 | }; | 833 | }; |
835 | 834 | ||
836 | /* TRACE_PRINT */ | 835 | /* TRACE_PRINT */ |
837 | static enum print_line_t trace_print_print(struct trace_iterator *iter, | ||
838 | int flags) | ||
839 | { | ||
840 | struct print_entry *field; | ||
841 | struct trace_seq *s = &iter->seq; | ||
842 | |||
843 | trace_assign_type(field, iter->ent); | ||
844 | |||
845 | if (!seq_print_ip_sym(s, field->ip, flags)) | ||
846 | goto partial; | ||
847 | |||
848 | if (!trace_seq_printf(s, ": %s", field->buf)) | ||
849 | goto partial; | ||
850 | |||
851 | return TRACE_TYPE_HANDLED; | ||
852 | |||
853 | partial: | ||
854 | return TRACE_TYPE_PARTIAL_LINE; | ||
855 | } | ||
856 | |||
857 | static enum print_line_t trace_print_raw(struct trace_iterator *iter, int flags) | ||
858 | { | ||
859 | struct print_entry *field; | ||
860 | |||
861 | trace_assign_type(field, iter->ent); | ||
862 | |||
863 | if (!trace_seq_printf(&iter->seq, "# %lx %s", field->ip, field->buf)) | ||
864 | goto partial; | ||
865 | |||
866 | return TRACE_TYPE_HANDLED; | ||
867 | |||
868 | partial: | ||
869 | return TRACE_TYPE_PARTIAL_LINE; | ||
870 | } | ||
871 | |||
872 | static struct trace_event trace_print_event = { | ||
873 | .type = TRACE_PRINT, | ||
874 | .trace = trace_print_print, | ||
875 | .raw = trace_print_raw, | ||
876 | }; | ||
877 | |||
878 | /* TRACE_BPRINTK */ | ||
879 | static enum print_line_t | 836 | static enum print_line_t |
880 | trace_bprintk_print(struct trace_iterator *iter, int flags) | 837 | trace_print_print(struct trace_iterator *iter, int flags) |
881 | { | 838 | { |
882 | struct trace_entry *entry = iter->ent; | 839 | struct trace_entry *entry = iter->ent; |
883 | struct trace_seq *s = &iter->seq; | 840 | struct trace_seq *s = &iter->seq; |
884 | struct bprintk_entry *field; | 841 | struct print_entry *field; |
885 | 842 | ||
886 | trace_assign_type(field, entry); | 843 | trace_assign_type(field, entry); |
887 | 844 | ||
@@ -900,14 +857,13 @@ trace_bprintk_print(struct trace_iterator *iter, int flags) | |||
900 | return TRACE_TYPE_PARTIAL_LINE; | 857 | return TRACE_TYPE_PARTIAL_LINE; |
901 | } | 858 | } |
902 | 859 | ||
903 | static enum print_line_t | 860 | |
904 | trace_bprintk_raw(struct trace_iterator *iter, int flags) | 861 | static enum print_line_t trace_print_raw(struct trace_iterator *iter, int flags) |
905 | { | 862 | { |
906 | struct trace_entry *entry = iter->ent; | 863 | struct print_entry *field; |
907 | struct trace_seq *s = &iter->seq; | 864 | struct trace_seq *s = &iter->seq; |
908 | struct bprintk_entry *field; | ||
909 | 865 | ||
910 | trace_assign_type(field, entry); | 866 | trace_assign_type(field, iter->ent); |
911 | 867 | ||
912 | if (!trace_seq_printf(s, ": %lx : ", field->ip)) | 868 | if (!trace_seq_printf(s, ": %lx : ", field->ip)) |
913 | goto partial; | 869 | goto partial; |
@@ -921,12 +877,11 @@ trace_bprintk_raw(struct trace_iterator *iter, int flags) | |||
921 | return TRACE_TYPE_PARTIAL_LINE; | 877 | return TRACE_TYPE_PARTIAL_LINE; |
922 | } | 878 | } |
923 | 879 | ||
924 | static struct trace_event trace_bprintk_event = { | 880 | |
925 | .type = TRACE_BPRINTK, | 881 | static struct trace_event trace_print_event = { |
926 | .trace = trace_bprintk_print, | 882 | .type = TRACE_PRINT, |
927 | .raw = trace_bprintk_raw, | 883 | .trace = trace_print_print, |
928 | .hex = trace_nop_print, | 884 | .raw = trace_print_raw, |
929 | .binary = trace_nop_print, | ||
930 | }; | 885 | }; |
931 | 886 | ||
932 | static struct trace_event *events[] __initdata = { | 887 | static struct trace_event *events[] __initdata = { |
@@ -937,7 +892,6 @@ static struct trace_event *events[] __initdata = { | |||
937 | &trace_stack_event, | 892 | &trace_stack_event, |
938 | &trace_user_stack_event, | 893 | &trace_user_stack_event, |
939 | &trace_print_event, | 894 | &trace_print_event, |
940 | &trace_bprintk_event, | ||
941 | NULL | 895 | NULL |
942 | }; | 896 | }; |
943 | 897 | ||
diff --git a/kernel/trace/trace_output.h b/kernel/trace/trace_output.h index 8a34d688ed63..3b90e6ade1aa 100644 --- a/kernel/trace/trace_output.h +++ b/kernel/trace/trace_output.h | |||
@@ -18,6 +18,8 @@ struct trace_event { | |||
18 | extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...) | 18 | extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...) |
19 | __attribute__ ((format (printf, 2, 3))); | 19 | __attribute__ ((format (printf, 2, 3))); |
20 | extern int | 20 | extern int |
21 | trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary); | ||
22 | extern int | ||
21 | seq_print_ip_sym(struct trace_seq *s, unsigned long ip, | 23 | seq_print_ip_sym(struct trace_seq *s, unsigned long ip, |
22 | unsigned long sym_flags); | 24 | unsigned long sym_flags); |
23 | extern ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, | 25 | extern ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, |
diff --git a/kernel/trace/trace_bprintk.c b/kernel/trace/trace_printk.c index f4c245a5cd33..a50aea22e929 100644 --- a/kernel/trace/trace_bprintk.c +++ b/kernel/trace/trace_printk.c | |||
@@ -21,31 +21,20 @@ | |||
21 | 21 | ||
22 | #ifdef CONFIG_MODULES | 22 | #ifdef CONFIG_MODULES |
23 | 23 | ||
24 | /* binary printk basic */ | ||
25 | static DEFINE_MUTEX(btrace_mutex); | ||
26 | /* | 24 | /* |
27 | * modules trace_bprintk()'s formats are autosaved in struct trace_bprintk_fmt | 25 | * modules trace_printk()'s formats are autosaved in struct trace_bprintk_fmt |
28 | * which are queued on trace_bprintk_fmt_list. | 26 | * which are queued on trace_bprintk_fmt_list. |
29 | */ | 27 | */ |
30 | static LIST_HEAD(trace_bprintk_fmt_list); | 28 | static LIST_HEAD(trace_bprintk_fmt_list); |
31 | 29 | ||
30 | /* serialize accesses to trace_bprintk_fmt_list */ | ||
31 | static DEFINE_MUTEX(btrace_mutex); | ||
32 | |||
32 | struct trace_bprintk_fmt { | 33 | struct trace_bprintk_fmt { |
33 | struct list_head list; | 34 | struct list_head list; |
34 | char fmt[0]; | 35 | char fmt[0]; |
35 | }; | 36 | }; |
36 | 37 | ||
37 | |||
38 | static inline void lock_btrace(void) | ||
39 | { | ||
40 | mutex_lock(&btrace_mutex); | ||
41 | } | ||
42 | |||
43 | static inline void unlock_btrace(void) | ||
44 | { | ||
45 | mutex_unlock(&btrace_mutex); | ||
46 | } | ||
47 | |||
48 | |||
49 | static inline struct trace_bprintk_fmt *lookup_format(const char *fmt) | 38 | static inline struct trace_bprintk_fmt *lookup_format(const char *fmt) |
50 | { | 39 | { |
51 | struct trace_bprintk_fmt *pos; | 40 | struct trace_bprintk_fmt *pos; |
@@ -60,7 +49,8 @@ static | |||
60 | void hold_module_trace_bprintk_format(const char **start, const char **end) | 49 | void hold_module_trace_bprintk_format(const char **start, const char **end) |
61 | { | 50 | { |
62 | const char **iter; | 51 | const char **iter; |
63 | lock_btrace(); | 52 | |
53 | mutex_lock(&btrace_mutex); | ||
64 | for (iter = start; iter < end; iter++) { | 54 | for (iter = start; iter < end; iter++) { |
65 | struct trace_bprintk_fmt *tb_fmt = lookup_format(*iter); | 55 | struct trace_bprintk_fmt *tb_fmt = lookup_format(*iter); |
66 | if (tb_fmt) { | 56 | if (tb_fmt) { |
@@ -77,7 +67,7 @@ void hold_module_trace_bprintk_format(const char **start, const char **end) | |||
77 | } else | 67 | } else |
78 | *iter = NULL; | 68 | *iter = NULL; |
79 | } | 69 | } |
80 | unlock_btrace(); | 70 | mutex_unlock(&btrace_mutex); |
81 | } | 71 | } |
82 | 72 | ||
83 | static int module_trace_bprintk_format_notify(struct notifier_block *self, | 73 | static int module_trace_bprintk_format_notify(struct notifier_block *self, |
@@ -109,46 +99,40 @@ struct notifier_block module_trace_bprintk_format_nb = { | |||
109 | .notifier_call = module_trace_bprintk_format_notify, | 99 | .notifier_call = module_trace_bprintk_format_notify, |
110 | }; | 100 | }; |
111 | 101 | ||
112 | /* events tracer */ | 102 | int __trace_printk(unsigned long ip, const char *fmt, ...) |
113 | int trace_bprintk_enable; | 103 | { |
104 | int ret; | ||
105 | va_list ap; | ||
114 | 106 | ||
115 | static void start_bprintk_trace(struct trace_array *tr) | 107 | if (unlikely(!fmt)) |
116 | { | 108 | return 0; |
117 | tracing_reset_online_cpus(tr); | ||
118 | trace_bprintk_enable = 1; | ||
119 | } | ||
120 | 109 | ||
121 | static void stop_bprintk_trace(struct trace_array *tr) | 110 | if (!(trace_flags & TRACE_ITER_PRINTK)) |
122 | { | 111 | return 0; |
123 | trace_bprintk_enable = 0; | 112 | |
124 | tracing_reset_online_cpus(tr); | 113 | va_start(ap, fmt); |
114 | ret = trace_vprintk(ip, task_curr_ret_stack(current), fmt, ap); | ||
115 | va_end(ap); | ||
116 | return ret; | ||
125 | } | 117 | } |
118 | EXPORT_SYMBOL_GPL(__trace_printk); | ||
126 | 119 | ||
127 | static int init_bprintk_trace(struct trace_array *tr) | 120 | int __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap) |
128 | { | 121 | { |
129 | start_bprintk_trace(tr); | 122 | if (unlikely(!fmt)) |
130 | return 0; | 123 | return 0; |
124 | |||
125 | if (!(trace_flags & TRACE_ITER_PRINTK)) | ||
126 | return 0; | ||
127 | |||
128 | return trace_vprintk(ip, task_curr_ret_stack(current), fmt, ap); | ||
131 | } | 129 | } |
130 | EXPORT_SYMBOL_GPL(__ftrace_vprintk); | ||
132 | 131 | ||
133 | static struct tracer bprintk_trace __read_mostly = | ||
134 | { | ||
135 | .name = "events", | ||
136 | .init = init_bprintk_trace, | ||
137 | .reset = stop_bprintk_trace, | ||
138 | .start = start_bprintk_trace, | ||
139 | .stop = stop_bprintk_trace, | ||
140 | }; | ||
141 | 132 | ||
142 | static __init int init_bprintk(void) | 133 | static __init int init_trace_printk(void) |
143 | { | 134 | { |
144 | int ret = register_module_notifier(&module_trace_bprintk_format_nb); | 135 | return register_module_notifier(&module_trace_bprintk_format_nb); |
145 | if (ret) | ||
146 | return ret; | ||
147 | |||
148 | ret = register_tracer(&bprintk_trace); | ||
149 | if (ret) | ||
150 | unregister_module_notifier(&module_trace_bprintk_format_nb); | ||
151 | return ret; | ||
152 | } | 136 | } |
153 | 137 | ||
154 | device_initcall(init_bprintk); | 138 | early_initcall(init_trace_printk); |