aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/Kconfig2
-rw-r--r--kernel/trace/Makefile2
-rw-r--r--kernel/trace/ftrace.c17
-rw-r--r--kernel/trace/ring_buffer.c2
-rw-r--r--kernel/trace/trace.c165
-rw-r--r--kernel/trace/trace.h15
-rw-r--r--kernel/trace/trace_event_types.h165
-rw-r--r--kernel/trace/trace_events.c12
-rw-r--r--kernel/trace/trace_events_stage_2.h53
-rw-r--r--kernel/trace/trace_export.c81
-rw-r--r--kernel/trace/trace_format.h55
-rw-r--r--kernel/trace/trace_functions_graph.c6
-rw-r--r--kernel/trace/trace_mmiotrace.c9
-rw-r--r--kernel/trace/trace_output.c41
-rw-r--r--kernel/trace/trace_output.h2
-rw-r--r--kernel/trace/trace_printk.c138
-rw-r--r--kernel/trace/trace_sysprof.c2
17 files changed, 589 insertions, 178 deletions
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index 5d733da5345a..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
@@ -61,6 +62,7 @@ config TRACING_SUPPORT
61 bool 62 bool
62 depends on TRACE_IRQFLAGS_SUPPORT 63 depends on TRACE_IRQFLAGS_SUPPORT
63 depends on STACKTRACE_SUPPORT 64 depends on STACKTRACE_SUPPORT
65 default y
64 66
65if TRACING_SUPPORT 67if TRACING_SUPPORT
66 68
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index c931fe0560cb..c7a2943796eb 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_TRACING) += trace.o
22obj-$(CONFIG_TRACING) += trace_clock.o 22obj-$(CONFIG_TRACING) += trace_clock.o
23obj-$(CONFIG_TRACING) += trace_output.o 23obj-$(CONFIG_TRACING) += trace_output.o
24obj-$(CONFIG_TRACING) += trace_stat.o 24obj-$(CONFIG_TRACING) += trace_stat.o
25obj-$(CONFIG_TRACING) += trace_printk.o
25obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o 26obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o
26obj-$(CONFIG_SYSPROF_TRACER) += trace_sysprof.o 27obj-$(CONFIG_SYSPROF_TRACER) += trace_sysprof.o
27obj-$(CONFIG_FUNCTION_TRACER) += trace_functions.o 28obj-$(CONFIG_FUNCTION_TRACER) += trace_functions.o
@@ -41,5 +42,6 @@ obj-$(CONFIG_WORKQUEUE_TRACER) += trace_workqueue.o
41obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o 42obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o
42obj-$(CONFIG_EVENT_TRACER) += trace_events.o 43obj-$(CONFIG_EVENT_TRACER) += trace_events.o
43obj-$(CONFIG_EVENT_TRACER) += events.o 44obj-$(CONFIG_EVENT_TRACER) += events.o
45obj-$(CONFIG_EVENT_TRACER) += trace_export.o
44 46
45libftrace-y := ftrace.o 47libftrace-y := ftrace.o
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 5a3a06b21eee..d33d306bdcf4 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -218,10 +218,8 @@ static void ftrace_update_pid_func(void)
218{ 218{
219 ftrace_func_t func; 219 ftrace_func_t func;
220 220
221 mutex_lock(&ftrace_lock);
222
223 if (ftrace_trace_function == ftrace_stub) 221 if (ftrace_trace_function == ftrace_stub)
224 goto out; 222 return;
225 223
226 func = ftrace_trace_function; 224 func = ftrace_trace_function;
227 225
@@ -238,9 +236,6 @@ static void ftrace_update_pid_func(void)
238#else 236#else
239 __ftrace_trace_function = func; 237 __ftrace_trace_function = func;
240#endif 238#endif
241
242 out:
243 mutex_unlock(&ftrace_lock);
244} 239}
245 240
246/* set when tracing only a pid */ 241/* set when tracing only a pid */
@@ -1869,21 +1864,21 @@ ftrace_notrace_release(struct inode *inode, struct file *file)
1869 return ftrace_regex_release(inode, file, 0); 1864 return ftrace_regex_release(inode, file, 0);
1870} 1865}
1871 1866
1872static struct file_operations ftrace_avail_fops = { 1867static const struct file_operations ftrace_avail_fops = {
1873 .open = ftrace_avail_open, 1868 .open = ftrace_avail_open,
1874 .read = seq_read, 1869 .read = seq_read,
1875 .llseek = seq_lseek, 1870 .llseek = seq_lseek,
1876 .release = ftrace_avail_release, 1871 .release = ftrace_avail_release,
1877}; 1872};
1878 1873
1879static struct file_operations ftrace_failures_fops = { 1874static const struct file_operations ftrace_failures_fops = {
1880 .open = ftrace_failures_open, 1875 .open = ftrace_failures_open,
1881 .read = seq_read, 1876 .read = seq_read,
1882 .llseek = seq_lseek, 1877 .llseek = seq_lseek,
1883 .release = ftrace_avail_release, 1878 .release = ftrace_avail_release,
1884}; 1879};
1885 1880
1886static struct file_operations ftrace_filter_fops = { 1881static const struct file_operations ftrace_filter_fops = {
1887 .open = ftrace_filter_open, 1882 .open = ftrace_filter_open,
1888 .read = ftrace_regex_read, 1883 .read = ftrace_regex_read,
1889 .write = ftrace_filter_write, 1884 .write = ftrace_filter_write,
@@ -1891,7 +1886,7 @@ static struct file_operations ftrace_filter_fops = {
1891 .release = ftrace_filter_release, 1886 .release = ftrace_filter_release,
1892}; 1887};
1893 1888
1894static struct file_operations ftrace_notrace_fops = { 1889static const struct file_operations ftrace_notrace_fops = {
1895 .open = ftrace_notrace_open, 1890 .open = ftrace_notrace_open,
1896 .read = ftrace_regex_read, 1891 .read = ftrace_regex_read,
1897 .write = ftrace_notrace_write, 1892 .write = ftrace_notrace_write,
@@ -2423,7 +2418,7 @@ ftrace_pid_write(struct file *filp, const char __user *ubuf,
2423 return cnt; 2418 return cnt;
2424} 2419}
2425 2420
2426static struct file_operations ftrace_pid_fops = { 2421static const struct file_operations ftrace_pid_fops = {
2427 .read = ftrace_pid_read, 2422 .read = ftrace_pid_read,
2428 .write = ftrace_pid_write, 2423 .write = ftrace_pid_write,
2429}; 2424};
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index f7473645b9c6..178858492a89 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -2606,7 +2606,7 @@ rb_simple_write(struct file *filp, const char __user *ubuf,
2606 return cnt; 2606 return cnt;
2607} 2607}
2608 2608
2609static struct file_operations rb_simple_fops = { 2609static const struct file_operations rb_simple_fops = {
2610 .open = tracing_open_generic, 2610 .open = tracing_open_generic,
2611 .read = rb_simple_read, 2611 .read = rb_simple_read,
2612 .write = rb_simple_write, 2612 .write = rb_simple_write,
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index c0e9c1263393..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 */
1177int 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
1222out_unlock:
1223 spin_unlock_irqrestore(&trace_buf_lock, flags);
1224
1225out:
1226 ftrace_preempt_enable(resched);
1227 unpause_graph_tracing();
1228
1229 return len;
1230}
1231EXPORT_SYMBOL_GPL(trace_vprintk);
1232
1172enum trace_file_type { 1233enum 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
@@ -1882,14 +1943,14 @@ static int show_traces_open(struct inode *inode, struct file *file)
1882 return ret; 1943 return ret;
1883} 1944}
1884 1945
1885static struct file_operations tracing_fops = { 1946static const struct file_operations tracing_fops = {
1886 .open = tracing_open, 1947 .open = tracing_open,
1887 .read = seq_read, 1948 .read = seq_read,
1888 .llseek = seq_lseek, 1949 .llseek = seq_lseek,
1889 .release = tracing_release, 1950 .release = tracing_release,
1890}; 1951};
1891 1952
1892static struct file_operations show_traces_fops = { 1953static const struct file_operations show_traces_fops = {
1893 .open = show_traces_open, 1954 .open = show_traces_open,
1894 .read = seq_read, 1955 .read = seq_read,
1895 .release = seq_release, 1956 .release = seq_release,
@@ -1982,7 +2043,7 @@ err_unlock:
1982 return err; 2043 return err;
1983} 2044}
1984 2045
1985static struct file_operations tracing_cpumask_fops = { 2046static const struct file_operations tracing_cpumask_fops = {
1986 .open = tracing_open_generic, 2047 .open = tracing_open_generic,
1987 .read = tracing_cpumask_read, 2048 .read = tracing_cpumask_read,
1988 .write = tracing_cpumask_write, 2049 .write = tracing_cpumask_write,
@@ -2134,7 +2195,7 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
2134 return cnt; 2195 return cnt;
2135} 2196}
2136 2197
2137static struct file_operations tracing_iter_fops = { 2198static const struct file_operations tracing_iter_fops = {
2138 .open = tracing_open_generic, 2199 .open = tracing_open_generic,
2139 .read = tracing_trace_options_read, 2200 .read = tracing_trace_options_read,
2140 .write = tracing_trace_options_write, 2201 .write = tracing_trace_options_write,
@@ -2167,7 +2228,7 @@ tracing_readme_read(struct file *filp, char __user *ubuf,
2167 readme_msg, strlen(readme_msg)); 2228 readme_msg, strlen(readme_msg));
2168} 2229}
2169 2230
2170static struct file_operations tracing_readme_fops = { 2231static const struct file_operations tracing_readme_fops = {
2171 .open = tracing_open_generic, 2232 .open = tracing_open_generic,
2172 .read = tracing_readme_read, 2233 .read = tracing_readme_read,
2173}; 2234};
@@ -2927,25 +2988,25 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
2927 return cnt; 2988 return cnt;
2928} 2989}
2929 2990
2930static struct file_operations tracing_max_lat_fops = { 2991static const struct file_operations tracing_max_lat_fops = {
2931 .open = tracing_open_generic, 2992 .open = tracing_open_generic,
2932 .read = tracing_max_lat_read, 2993 .read = tracing_max_lat_read,
2933 .write = tracing_max_lat_write, 2994 .write = tracing_max_lat_write,
2934}; 2995};
2935 2996
2936static struct file_operations tracing_ctrl_fops = { 2997static const struct file_operations tracing_ctrl_fops = {
2937 .open = tracing_open_generic, 2998 .open = tracing_open_generic,
2938 .read = tracing_ctrl_read, 2999 .read = tracing_ctrl_read,
2939 .write = tracing_ctrl_write, 3000 .write = tracing_ctrl_write,
2940}; 3001};
2941 3002
2942static struct file_operations set_tracer_fops = { 3003static const struct file_operations set_tracer_fops = {
2943 .open = tracing_open_generic, 3004 .open = tracing_open_generic,
2944 .read = tracing_set_trace_read, 3005 .read = tracing_set_trace_read,
2945 .write = tracing_set_trace_write, 3006 .write = tracing_set_trace_write,
2946}; 3007};
2947 3008
2948static struct file_operations tracing_pipe_fops = { 3009static const struct file_operations tracing_pipe_fops = {
2949 .open = tracing_open_pipe, 3010 .open = tracing_open_pipe,
2950 .poll = tracing_poll_pipe, 3011 .poll = tracing_poll_pipe,
2951 .read = tracing_read_pipe, 3012 .read = tracing_read_pipe,
@@ -2953,13 +3014,13 @@ static struct file_operations tracing_pipe_fops = {
2953 .release = tracing_release_pipe, 3014 .release = tracing_release_pipe,
2954}; 3015};
2955 3016
2956static struct file_operations tracing_entries_fops = { 3017static const struct file_operations tracing_entries_fops = {
2957 .open = tracing_open_generic, 3018 .open = tracing_open_generic,
2958 .read = tracing_entries_read, 3019 .read = tracing_entries_read,
2959 .write = tracing_entries_write, 3020 .write = tracing_entries_write,
2960}; 3021};
2961 3022
2962static struct file_operations tracing_mark_fops = { 3023static const struct file_operations tracing_mark_fops = {
2963 .open = tracing_open_generic, 3024 .open = tracing_open_generic,
2964 .write = tracing_mark_write, 3025 .write = tracing_mark_write,
2965}; 3026};
@@ -3240,7 +3301,7 @@ tracing_read_dyn_info(struct file *filp, char __user *ubuf,
3240 return r; 3301 return r;
3241} 3302}
3242 3303
3243static struct file_operations tracing_dyn_info_fops = { 3304static const struct file_operations tracing_dyn_info_fops = {
3244 .open = tracing_open_generic, 3305 .open = tracing_open_generic,
3245 .read = tracing_read_dyn_info, 3306 .read = tracing_read_dyn_info,
3246}; 3307};
@@ -3714,84 +3775,6 @@ static __init int tracer_init_debugfs(void)
3714 return 0; 3775 return 0;
3715} 3776}
3716 3777
3717int 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}
3769EXPORT_SYMBOL_GPL(trace_vprintk);
3770
3771int __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}
3784EXPORT_SYMBOL_GPL(__trace_printk);
3785
3786int __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}
3793EXPORT_SYMBOL_GPL(__ftrace_vprintk);
3794
3795static int trace_panic_handler(struct notifier_block *this, 3778static int trace_panic_handler(struct notifier_block *this,
3796 unsigned long event, void *unused) 3779 unsigned long event, void *unused)
3797{ 3780{
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 8beff03fda68..2bfb7d11fc17 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -121,7 +121,8 @@ struct print_entry {
121 struct trace_entry ent; 121 struct trace_entry ent;
122 unsigned long ip; 122 unsigned long ip;
123 int depth; 123 int depth;
124 char buf[]; 124 const char *fmt;
125 u32 buf[];
125}; 126};
126 127
127#define TRACE_OLD_SIZE 88 128#define TRACE_OLD_SIZE 88
@@ -195,7 +196,7 @@ struct kmemtrace_free_entry {
195 * trace_flag_type is an enumeration that holds different 196 * trace_flag_type is an enumeration that holds different
196 * states when a trace occurs. These are: 197 * states when a trace occurs. These are:
197 * IRQS_OFF - interrupts were disabled 198 * IRQS_OFF - interrupts were disabled
198 * IRQS_NOSUPPORT - arch does not support irqs_disabled_flags 199 * IRQS_NOSUPPORT - arch does not support irqs_disabled_flags
199 * NEED_RESCED - reschedule is requested 200 * NEED_RESCED - reschedule is requested
200 * HARDIRQ - inside an interrupt handler 201 * HARDIRQ - inside an interrupt handler
201 * SOFTIRQ - inside a softirq handler 202 * SOFTIRQ - inside a softirq handler
@@ -298,7 +299,7 @@ extern void __ftrace_bad_type(void);
298 IF_ASSIGN(var, ent, struct ftrace_graph_ret_entry, \ 299 IF_ASSIGN(var, ent, struct ftrace_graph_ret_entry, \
299 TRACE_GRAPH_RET); \ 300 TRACE_GRAPH_RET); \
300 IF_ASSIGN(var, ent, struct hw_branch_entry, TRACE_HW_BRANCHES);\ 301 IF_ASSIGN(var, ent, struct hw_branch_entry, TRACE_HW_BRANCHES);\
301 IF_ASSIGN(var, ent, struct trace_power, TRACE_POWER); \ 302 IF_ASSIGN(var, ent, struct trace_power, TRACE_POWER); \
302 IF_ASSIGN(var, ent, struct kmemtrace_alloc_entry, \ 303 IF_ASSIGN(var, ent, struct kmemtrace_alloc_entry, \
303 TRACE_KMEM_ALLOC); \ 304 TRACE_KMEM_ALLOC); \
304 IF_ASSIGN(var, ent, struct kmemtrace_free_entry, \ 305 IF_ASSIGN(var, ent, struct kmemtrace_free_entry, \
@@ -321,8 +322,8 @@ enum print_line_t {
321 * flags value in struct tracer_flags. 322 * flags value in struct tracer_flags.
322 */ 323 */
323struct tracer_opt { 324struct tracer_opt {
324 const char *name; /* Will appear on the trace_options file */ 325 const char *name; /* Will appear on the trace_options file */
325 u32 bit; /* Mask assigned in val field in tracer_flags */ 326 u32 bit; /* Mask assigned in val field in tracer_flags */
326}; 327};
327 328
328/* 329/*
@@ -331,7 +332,7 @@ struct tracer_opt {
331 */ 332 */
332struct tracer_flags { 333struct tracer_flags {
333 u32 val; 334 u32 val;
334 struct tracer_opt *opts; 335 struct tracer_opt *opts;
335}; 336};
336 337
337/* Makes more easy to define a tracer opt */ 338/* Makes more easy to define a tracer opt */
@@ -386,7 +387,7 @@ struct tracer {
386 int (*set_flag)(u32 old_flags, u32 bit, int set); 387 int (*set_flag)(u32 old_flags, u32 bit, int set);
387 struct tracer *next; 388 struct tracer *next;
388 int print_max; 389 int print_max;
389 struct tracer_flags *flags; 390 struct tracer_flags *flags;
390 struct tracer_stat *stats; 391 struct tracer_stat *stats;
391}; 392};
392 393
diff --git a/kernel/trace/trace_event_types.h b/kernel/trace/trace_event_types.h
new file mode 100644
index 000000000000..fb4eba166433
--- /dev/null
+++ b/kernel/trace/trace_event_types.h
@@ -0,0 +1,165 @@
1#undef TRACE_SYSTEM
2#define TRACE_SYSTEM ftrace
3
4/*
5 * We cheat and use the proto type field as the ID
6 * and args as the entry type (minus 'struct')
7 */
8TRACE_EVENT_FORMAT(function, TRACE_FN, ftrace_entry, ignore,
9 TRACE_STRUCT(
10 TRACE_FIELD(unsigned long, ip, ip)
11 TRACE_FIELD(unsigned long, parent_ip, parent_ip)
12 ),
13 TPRAWFMT(" %lx <-- %lx")
14);
15
16TRACE_EVENT_FORMAT(funcgraph_entry, TRACE_GRAPH_ENT,
17 ftrace_graph_ent_entry, ignore,
18 TRACE_STRUCT(
19 TRACE_FIELD(unsigned long, graph_ent.func, func)
20 TRACE_FIELD(int, graph_ent.depth, depth)
21 ),
22 TPRAWFMT("--> %lx (%d)")
23);
24
25TRACE_EVENT_FORMAT(funcgraph_exit, TRACE_GRAPH_RET,
26 ftrace_graph_ret_entry, ignore,
27 TRACE_STRUCT(
28 TRACE_FIELD(unsigned long, ret.func, func)
29 TRACE_FIELD(int, ret.depth, depth)
30 ),
31 TPRAWFMT("<-- %lx (%d)")
32);
33
34TRACE_EVENT_FORMAT(wakeup, TRACE_WAKE, ctx_switch_entry, ignore,
35 TRACE_STRUCT(
36 TRACE_FIELD(unsigned int, prev_pid, prev_pid)
37 TRACE_FIELD(unsigned char, prev_prio, prev_prio)
38 TRACE_FIELD(unsigned char, prev_state, prev_state)
39 TRACE_FIELD(unsigned int, next_pid, next_pid)
40 TRACE_FIELD(unsigned char, next_prio, next_prio)
41 TRACE_FIELD(unsigned char, next_state, next_state)
42 TRACE_FIELD(unsigned int, next_cpu, next_cpu)
43 ),
44 TPRAWFMT("%u:%u:%u ==+ %u:%u:%u [%03u]")
45);
46
47TRACE_EVENT_FORMAT(context_switch, TRACE_CTX, ctx_switch_entry, ignore,
48 TRACE_STRUCT(
49 TRACE_FIELD(unsigned int, prev_pid, prev_pid)
50 TRACE_FIELD(unsigned char, prev_prio, prev_prio)
51 TRACE_FIELD(unsigned char, prev_state, prev_state)
52 TRACE_FIELD(unsigned int, next_pid, next_pid)
53 TRACE_FIELD(unsigned char, next_prio, next_prio)
54 TRACE_FIELD(unsigned char, next_state, next_state)
55 TRACE_FIELD(unsigned int, next_cpu, next_cpu)
56 ),
57 TPRAWFMT("%u:%u:%u ==+ %u:%u:%u [%03u]")
58);
59
60TRACE_EVENT_FORMAT(special, TRACE_SPECIAL, special_entry, ignore,
61 TRACE_STRUCT(
62 TRACE_FIELD(unsigned long, arg1, arg1)
63 TRACE_FIELD(unsigned long, arg2, arg2)
64 TRACE_FIELD(unsigned long, arg3, arg3)
65 ),
66 TPRAWFMT("(%08lx) (%08lx) (%08lx)")
67);
68
69/*
70 * Stack-trace entry:
71 */
72
73/* #define FTRACE_STACK_ENTRIES 8 */
74
75TRACE_EVENT_FORMAT(kernel_stack, TRACE_STACK, stack_entry, ignore,
76 TRACE_STRUCT(
77 TRACE_FIELD(unsigned long, caller[0], stack0)
78 TRACE_FIELD(unsigned long, caller[1], stack1)
79 TRACE_FIELD(unsigned long, caller[2], stack2)
80 TRACE_FIELD(unsigned long, caller[3], stack3)
81 TRACE_FIELD(unsigned long, caller[4], stack4)
82 TRACE_FIELD(unsigned long, caller[5], stack5)
83 TRACE_FIELD(unsigned long, caller[6], stack6)
84 TRACE_FIELD(unsigned long, caller[7], stack7)
85 ),
86 TPRAWFMT("\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n"
87 "\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n")
88);
89
90TRACE_EVENT_FORMAT(user_stack, TRACE_USER_STACK, userstack_entry, ignore,
91 TRACE_STRUCT(
92 TRACE_FIELD(unsigned long, caller[0], stack0)
93 TRACE_FIELD(unsigned long, caller[1], stack1)
94 TRACE_FIELD(unsigned long, caller[2], stack2)
95 TRACE_FIELD(unsigned long, caller[3], stack3)
96 TRACE_FIELD(unsigned long, caller[4], stack4)
97 TRACE_FIELD(unsigned long, caller[5], stack5)
98 TRACE_FIELD(unsigned long, caller[6], stack6)
99 TRACE_FIELD(unsigned long, caller[7], stack7)
100 ),
101 TPRAWFMT("\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n"
102 "\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n")
103);
104
105TRACE_EVENT_FORMAT(print, TRACE_PRINT, print_entry, ignore,
106 TRACE_STRUCT(
107 TRACE_FIELD(unsigned long, ip, ip)
108 TRACE_FIELD(unsigned int, depth, depth)
109 TRACE_FIELD_ZERO_CHAR(buf)
110 ),
111 TPRAWFMT("%08lx (%d) %s")
112);
113
114TRACE_EVENT_FORMAT(branch, TRACE_BRANCH, trace_branch, ignore,
115 TRACE_STRUCT(
116 TRACE_FIELD(unsigned int, line, line)
117 TRACE_FIELD_SPECIAL(char func[TRACE_FUNC_SIZE+1], func, func)
118 TRACE_FIELD_SPECIAL(char file[TRACE_FUNC_SIZE+1], file, file)
119 TRACE_FIELD(char, correct, correct)
120 ),
121 TPRAWFMT("%u:%s:%s (%u)")
122);
123
124TRACE_EVENT_FORMAT(hw_branch, TRACE_HW_BRANCHES, hw_branch_entry, ignore,
125 TRACE_STRUCT(
126 TRACE_FIELD(u64, from, from)
127 TRACE_FIELD(u64, to, to)
128 ),
129 TPRAWFMT("from: %llx to: %llx")
130);
131
132TRACE_EVENT_FORMAT(power, TRACE_POWER, trace_power, ignore,
133 TRACE_STRUCT(
134 TRACE_FIELD(ktime_t, state_data.stamp, stamp)
135 TRACE_FIELD(ktime_t, state_data.end, end)
136 TRACE_FIELD(int, state_data.type, type)
137 TRACE_FIELD(int, state_data.state, state)
138 ),
139 TPRAWFMT("%llx->%llx type:%u state:%u")
140);
141
142TRACE_EVENT_FORMAT(kmem_alloc, TRACE_KMEM_ALLOC, kmemtrace_alloc_entry, ignore,
143 TRACE_STRUCT(
144 TRACE_FIELD(enum kmemtrace_type_id, type_id, type_id)
145 TRACE_FIELD(unsigned long, call_site, call_site)
146 TRACE_FIELD(const void *, ptr, ptr)
147 TRACE_FIELD(size_t, bytes_req, bytes_req)
148 TRACE_FIELD(size_t, bytes_alloc, bytes_alloc)
149 TRACE_FIELD(gfp_t, gfp_flags, gfp_flags)
150 TRACE_FIELD(int, node, node)
151 ),
152 TPRAWFMT("type:%u call_site:%lx ptr:%p req:%lu alloc:%lu"
153 " flags:%x node:%d")
154);
155
156TRACE_EVENT_FORMAT(kmem_free, TRACE_KMEM_FREE, kmemtrace_free_entry, ignore,
157 TRACE_STRUCT(
158 TRACE_FIELD(enum kmemtrace_type_id, type_id, type_id)
159 TRACE_FIELD(unsigned long, call_site, call_site)
160 TRACE_FIELD(const void *, ptr, ptr)
161 ),
162 TPRAWFMT("type:%u call_site:%lx ptr:%p")
163);
164
165#undef TRACE_SYSTEM
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 210e71ff82db..4488d90e75ef 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -656,11 +656,13 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events)
656 return -1; 656 return -1;
657 } 657 }
658 658
659 entry = debugfs_create_file("enable", 0644, call->dir, call, 659 if (call->regfunc) {
660 &ftrace_enable_fops); 660 entry = debugfs_create_file("enable", 0644, call->dir, call,
661 if (!entry) 661 &ftrace_enable_fops);
662 pr_warning("Could not create debugfs " 662 if (!entry)
663 "'%s/enable' entry\n", call->name); 663 pr_warning("Could not create debugfs "
664 "'%s/enable' entry\n", call->name);
665 }
664 666
665 /* Only let type be writable, if we can change it */ 667 /* Only let type be writable, if we can change it */
666 entry = debugfs_create_file("type", 668 entry = debugfs_create_file("type",
diff --git a/kernel/trace/trace_events_stage_2.h b/kernel/trace/trace_events_stage_2.h
index b1cebba1d9b4..d24a97e74aea 100644
--- a/kernel/trace/trace_events_stage_2.h
+++ b/kernel/trace/trace_events_stage_2.h
@@ -75,56 +75,5 @@ ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \
75 75
76#include <trace/trace_event_types.h> 76#include <trace/trace_event_types.h>
77 77
78/* 78#include "trace_format.h"
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) \
117int \
118ftrace_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> 79#include <trace/trace_event_types.h>
diff --git a/kernel/trace/trace_export.c b/kernel/trace/trace_export.c
new file mode 100644
index 000000000000..0fb7be73e31c
--- /dev/null
+++ b/kernel/trace/trace_export.c
@@ -0,0 +1,81 @@
1/*
2 * trace_export.c - export basic ftrace utilities to user space
3 *
4 * Copyright (C) 2009 Steven Rostedt <srostedt@redhat.com>
5 */
6#include <linux/stringify.h>
7#include <linux/kallsyms.h>
8#include <linux/seq_file.h>
9#include <linux/debugfs.h>
10#include <linux/uaccess.h>
11#include <linux/ftrace.h>
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/fs.h>
15
16#include "trace_output.h"
17
18#include "trace_format.h"
19
20#undef TRACE_FIELD_ZERO_CHAR
21#define TRACE_FIELD_ZERO_CHAR(item) \
22 ret = trace_seq_printf(s, "\tfield: char " #item ";\t" \
23 "offset:%lu;\tsize:0;\n", \
24 offsetof(typeof(field), item)); \
25 if (!ret) \
26 return 0;
27
28
29#undef TPRAWFMT
30#define TPRAWFMT(args...) args
31
32#undef TRACE_EVENT_FORMAT
33#define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt) \
34static int \
35ftrace_format_##call(struct trace_seq *s) \
36{ \
37 struct args field; \
38 int ret; \
39 \
40 tstruct; \
41 \
42 trace_seq_printf(s, "\nprint fmt: \"%s\"\n", tpfmt); \
43 \
44 return ret; \
45}
46
47#include "trace_event_types.h"
48
49#undef TRACE_ZERO_CHAR
50#define TRACE_ZERO_CHAR(arg)
51
52#undef TRACE_FIELD
53#define TRACE_FIELD(type, item, assign)\
54 entry->item = assign;
55
56#undef TRACE_FIELD
57#define TRACE_FIELD(type, item, assign)\
58 entry->item = assign;
59
60#undef TPCMD
61#define TPCMD(cmd...) cmd
62
63#undef TRACE_ENTRY
64#define TRACE_ENTRY entry
65
66#undef TRACE_FIELD_SPECIAL
67#define TRACE_FIELD_SPECIAL(type_item, item, cmd) \
68 cmd;
69
70#undef TRACE_EVENT_FORMAT
71#define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt) \
72 \
73static struct ftrace_event_call __used \
74__attribute__((__aligned__(4))) \
75__attribute__((section("_ftrace_events"))) event_##call = { \
76 .name = #call, \
77 .id = proto, \
78 .system = __stringify(TRACE_SYSTEM), \
79 .show_format = ftrace_format_##call, \
80}
81#include "trace_event_types.h"
diff --git a/kernel/trace/trace_format.h b/kernel/trace/trace_format.h
new file mode 100644
index 000000000000..03f9a4c165ca
--- /dev/null
+++ b/kernel/trace/trace_format.h
@@ -0,0 +1,55 @@
1/*
2 * Setup the showing format of trace point.
3 *
4 * int
5 * ftrace_format_##call(struct trace_seq *s)
6 * {
7 * struct ftrace_raw_##call field;
8 * int ret;
9 *
10 * ret = trace_seq_printf(s, #type " " #item ";"
11 * " size:%d; offset:%d;\n",
12 * sizeof(field.type),
13 * offsetof(struct ftrace_raw_##call,
14 * item));
15 *
16 * }
17 */
18
19#undef TRACE_STRUCT
20#define TRACE_STRUCT(args...) args
21
22#undef TRACE_FIELD
23#define TRACE_FIELD(type, item, assign) \
24 ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \
25 "offset:%lu;\tsize:%lu;\n", \
26 offsetof(typeof(field), item), \
27 sizeof(field.item)); \
28 if (!ret) \
29 return 0;
30
31
32#undef TRACE_FIELD_SPECIAL
33#define TRACE_FIELD_SPECIAL(type_item, item, cmd) \
34 ret = trace_seq_printf(s, "\tfield special:" #type_item ";\t" \
35 "offset:%lu;\tsize:%lu;\n", \
36 offsetof(typeof(field), item), \
37 sizeof(field.item)); \
38 if (!ret) \
39 return 0;
40
41#undef TRACE_EVENT_FORMAT
42#define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt) \
43static int \
44ftrace_format_##call(struct trace_seq *s) \
45{ \
46 struct ftrace_raw_##call field; \
47 int ret; \
48 \
49 tstruct; \
50 \
51 trace_seq_printf(s, "\nprint fmt: \"%s\"\n", tpfmt); \
52 \
53 return ret; \
54}
55
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 306fef84c503..ef8fd661b217 100644
--- a/kernel/trace/trace_output.c
+++ b/kernel/trace/trace_output.c
@@ -53,6 +53,25 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
53 return len; 53 return len;
54} 54}
55 55
56int trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary)
57{
58 int len = (PAGE_SIZE - 1) - s->len;
59 int ret;
60
61 if (!len)
62 return 0;
63
64 ret = bstr_printf(s->buffer + s->len, len, fmt, binary);
65
66 /* If we can't write it all, don't bother writing anything */
67 if (ret >= len)
68 return 0;
69
70 s->len += ret;
71
72 return len;
73}
74
56/** 75/**
57 * trace_seq_puts - trace sequence printing of simple string 76 * trace_seq_puts - trace sequence printing of simple string
58 * @s: trace sequence descriptor 77 * @s: trace sequence descriptor
@@ -814,18 +833,22 @@ static struct trace_event trace_user_stack_event = {
814}; 833};
815 834
816/* TRACE_PRINT */ 835/* TRACE_PRINT */
817static enum print_line_t trace_print_print(struct trace_iterator *iter, 836static enum print_line_t
818 int flags) 837trace_print_print(struct trace_iterator *iter, int flags)
819{ 838{
820 struct print_entry *field; 839 struct trace_entry *entry = iter->ent;
821 struct trace_seq *s = &iter->seq; 840 struct trace_seq *s = &iter->seq;
841 struct print_entry *field;
822 842
823 trace_assign_type(field, iter->ent); 843 trace_assign_type(field, entry);
824 844
825 if (!seq_print_ip_sym(s, field->ip, flags)) 845 if (!seq_print_ip_sym(s, field->ip, flags))
826 goto partial; 846 goto partial;
827 847
828 if (!trace_seq_printf(s, ": %s", field->buf)) 848 if (!trace_seq_puts(s, ": "))
849 goto partial;
850
851 if (!trace_seq_bprintf(s, field->fmt, field->buf))
829 goto partial; 852 goto partial;
830 853
831 return TRACE_TYPE_HANDLED; 854 return TRACE_TYPE_HANDLED;
@@ -834,13 +857,18 @@ static enum print_line_t trace_print_print(struct trace_iterator *iter,
834 return TRACE_TYPE_PARTIAL_LINE; 857 return TRACE_TYPE_PARTIAL_LINE;
835} 858}
836 859
860
837static enum print_line_t trace_print_raw(struct trace_iterator *iter, int flags) 861static enum print_line_t trace_print_raw(struct trace_iterator *iter, int flags)
838{ 862{
839 struct print_entry *field; 863 struct print_entry *field;
864 struct trace_seq *s = &iter->seq;
840 865
841 trace_assign_type(field, iter->ent); 866 trace_assign_type(field, iter->ent);
842 867
843 if (!trace_seq_printf(&iter->seq, "# %lx %s", field->ip, field->buf)) 868 if (!trace_seq_printf(s, ": %lx : ", field->ip))
869 goto partial;
870
871 if (!trace_seq_bprintf(s, field->fmt, field->buf))
844 goto partial; 872 goto partial;
845 873
846 return TRACE_TYPE_HANDLED; 874 return TRACE_TYPE_HANDLED;
@@ -849,6 +877,7 @@ static enum print_line_t trace_print_raw(struct trace_iterator *iter, int flags)
849 return TRACE_TYPE_PARTIAL_LINE; 877 return TRACE_TYPE_PARTIAL_LINE;
850} 878}
851 879
880
852static struct trace_event trace_print_event = { 881static struct trace_event trace_print_event = {
853 .type = TRACE_PRINT, 882 .type = TRACE_PRINT,
854 .trace = trace_print_print, 883 .trace = trace_print_print,
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 {
18extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...) 18extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
19 __attribute__ ((format (printf, 2, 3))); 19 __attribute__ ((format (printf, 2, 3)));
20extern int 20extern int
21trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary);
22extern int
21seq_print_ip_sym(struct trace_seq *s, unsigned long ip, 23seq_print_ip_sym(struct trace_seq *s, unsigned long ip,
22 unsigned long sym_flags); 24 unsigned long sym_flags);
23extern ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, 25extern ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf,
diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c
new file mode 100644
index 000000000000..a50aea22e929
--- /dev/null
+++ b/kernel/trace/trace_printk.c
@@ -0,0 +1,138 @@
1/*
2 * trace binary printk
3 *
4 * Copyright (C) 2008 Lai Jiangshan <laijs@cn.fujitsu.com>
5 *
6 */
7#include <linux/kernel.h>
8#include <linux/ftrace.h>
9#include <linux/string.h>
10#include <linux/ctype.h>
11#include <linux/list.h>
12#include <linux/mutex.h>
13#include <linux/slab.h>
14#include <linux/module.h>
15#include <linux/seq_file.h>
16#include <linux/fs.h>
17#include <linux/marker.h>
18#include <linux/uaccess.h>
19
20#include "trace.h"
21
22#ifdef CONFIG_MODULES
23
24/*
25 * modules trace_printk()'s formats are autosaved in struct trace_bprintk_fmt
26 * which are queued on trace_bprintk_fmt_list.
27 */
28static LIST_HEAD(trace_bprintk_fmt_list);
29
30/* serialize accesses to trace_bprintk_fmt_list */
31static DEFINE_MUTEX(btrace_mutex);
32
33struct trace_bprintk_fmt {
34 struct list_head list;
35 char fmt[0];
36};
37
38static inline struct trace_bprintk_fmt *lookup_format(const char *fmt)
39{
40 struct trace_bprintk_fmt *pos;
41 list_for_each_entry(pos, &trace_bprintk_fmt_list, list) {
42 if (!strcmp(pos->fmt, fmt))
43 return pos;
44 }
45 return NULL;
46}
47
48static
49void hold_module_trace_bprintk_format(const char **start, const char **end)
50{
51 const char **iter;
52
53 mutex_lock(&btrace_mutex);
54 for (iter = start; iter < end; iter++) {
55 struct trace_bprintk_fmt *tb_fmt = lookup_format(*iter);
56 if (tb_fmt) {
57 *iter = tb_fmt->fmt;
58 continue;
59 }
60
61 tb_fmt = kmalloc(offsetof(struct trace_bprintk_fmt, fmt)
62 + strlen(*iter) + 1, GFP_KERNEL);
63 if (tb_fmt) {
64 list_add_tail(&tb_fmt->list, &trace_bprintk_fmt_list);
65 strcpy(tb_fmt->fmt, *iter);
66 *iter = tb_fmt->fmt;
67 } else
68 *iter = NULL;
69 }
70 mutex_unlock(&btrace_mutex);
71}
72
73static int module_trace_bprintk_format_notify(struct notifier_block *self,
74 unsigned long val, void *data)
75{
76 struct module *mod = data;
77 if (mod->num_trace_bprintk_fmt) {
78 const char **start = mod->trace_bprintk_fmt_start;
79 const char **end = start + mod->num_trace_bprintk_fmt;
80
81 if (val == MODULE_STATE_COMING)
82 hold_module_trace_bprintk_format(start, end);
83 }
84 return 0;
85}
86
87#else /* !CONFIG_MODULES */
88__init static int
89module_trace_bprintk_format_notify(struct notifier_block *self,
90 unsigned long val, void *data)
91{
92 return 0;
93}
94#endif /* CONFIG_MODULES */
95
96
97__initdata_or_module static
98struct notifier_block module_trace_bprintk_format_nb = {
99 .notifier_call = module_trace_bprintk_format_notify,
100};
101
102int __trace_printk(unsigned long ip, const char *fmt, ...)
103 {
104 int ret;
105 va_list ap;
106
107 if (unlikely(!fmt))
108 return 0;
109
110 if (!(trace_flags & TRACE_ITER_PRINTK))
111 return 0;
112
113 va_start(ap, fmt);
114 ret = trace_vprintk(ip, task_curr_ret_stack(current), fmt, ap);
115 va_end(ap);
116 return ret;
117}
118EXPORT_SYMBOL_GPL(__trace_printk);
119
120int __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap)
121 {
122 if (unlikely(!fmt))
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);
129}
130EXPORT_SYMBOL_GPL(__ftrace_vprintk);
131
132
133static __init int init_trace_printk(void)
134{
135 return register_module_notifier(&module_trace_bprintk_format_nb);
136}
137
138early_initcall(init_trace_printk);
diff --git a/kernel/trace/trace_sysprof.c b/kernel/trace/trace_sysprof.c
index c771af4e8f1a..91fd19c2149f 100644
--- a/kernel/trace/trace_sysprof.c
+++ b/kernel/trace/trace_sysprof.c
@@ -314,7 +314,7 @@ sysprof_sample_write(struct file *filp, const char __user *ubuf,
314 return cnt; 314 return cnt;
315} 315}
316 316
317static struct file_operations sysprof_sample_fops = { 317static const struct file_operations sysprof_sample_fops = {
318 .read = sysprof_sample_read, 318 .read = sysprof_sample_read,
319 .write = sysprof_sample_write, 319 .write = sysprof_sample_write,
320}; 320};