aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ftrace.h4
-rw-r--r--kernel/sysctl.c2
-rw-r--r--kernel/trace/trace.c78
-rw-r--r--kernel/trace/trace_events.c40
4 files changed, 83 insertions, 41 deletions
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index b3d34d3e0e7e..8700049fd0e5 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -945,6 +945,10 @@ extern int __disable_trace_on_warning;
945#define INIT_TRACE_RECURSION .trace_recursion = 0, 945#define INIT_TRACE_RECURSION .trace_recursion = 0,
946#endif 946#endif
947 947
948int tracepoint_printk_sysctl(struct ctl_table *table, int write,
949 void __user *buffer, size_t *lenp,
950 loff_t *ppos);
951
948#else /* CONFIG_TRACING */ 952#else /* CONFIG_TRACING */
949static inline void disable_trace_on_warning(void) { } 953static inline void disable_trace_on_warning(void) { }
950#endif /* CONFIG_TRACING */ 954#endif /* CONFIG_TRACING */
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 706309f9ed84..6ccc60dfbc7a 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -634,7 +634,7 @@ static struct ctl_table kern_table[] = {
634 .data = &tracepoint_printk, 634 .data = &tracepoint_printk,
635 .maxlen = sizeof(tracepoint_printk), 635 .maxlen = sizeof(tracepoint_printk),
636 .mode = 0644, 636 .mode = 0644,
637 .proc_handler = proc_dointvec, 637 .proc_handler = tracepoint_printk_sysctl,
638 }, 638 },
639#endif 639#endif
640#ifdef CONFIG_KEXEC_CORE 640#ifdef CONFIG_KEXEC_CORE
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 490533726b54..725e8b2c453f 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -69,6 +69,7 @@ bool __read_mostly tracing_selftest_disabled;
69/* Pipe tracepoints to printk */ 69/* Pipe tracepoints to printk */
70struct trace_iterator *tracepoint_print_iter; 70struct trace_iterator *tracepoint_print_iter;
71int tracepoint_printk; 71int tracepoint_printk;
72static DEFINE_STATIC_KEY_FALSE(tracepoint_printk_key);
72 73
73/* For tracers that don't implement custom flags */ 74/* For tracers that don't implement custom flags */
74static struct tracer_opt dummy_tracer_opt[] = { 75static struct tracer_opt dummy_tracer_opt[] = {
@@ -2116,6 +2117,81 @@ trace_event_buffer_lock_reserve(struct ring_buffer **current_rb,
2116} 2117}
2117EXPORT_SYMBOL_GPL(trace_event_buffer_lock_reserve); 2118EXPORT_SYMBOL_GPL(trace_event_buffer_lock_reserve);
2118 2119
2120static DEFINE_SPINLOCK(tracepoint_iter_lock);
2121static DEFINE_MUTEX(tracepoint_printk_mutex);
2122
2123static void output_printk(struct trace_event_buffer *fbuffer)
2124{
2125 struct trace_event_call *event_call;
2126 struct trace_event *event;
2127 unsigned long flags;
2128 struct trace_iterator *iter = tracepoint_print_iter;
2129
2130 /* We should never get here if iter is NULL */
2131 if (WARN_ON_ONCE(!iter))
2132 return;
2133
2134 event_call = fbuffer->trace_file->event_call;
2135 if (!event_call || !event_call->event.funcs ||
2136 !event_call->event.funcs->trace)
2137 return;
2138
2139 event = &fbuffer->trace_file->event_call->event;
2140
2141 spin_lock_irqsave(&tracepoint_iter_lock, flags);
2142 trace_seq_init(&iter->seq);
2143 iter->ent = fbuffer->entry;
2144 event_call->event.funcs->trace(iter, 0, event);
2145 trace_seq_putc(&iter->seq, 0);
2146 printk("%s", iter->seq.buffer);
2147
2148 spin_unlock_irqrestore(&tracepoint_iter_lock, flags);
2149}
2150
2151int tracepoint_printk_sysctl(struct ctl_table *table, int write,
2152 void __user *buffer, size_t *lenp,
2153 loff_t *ppos)
2154{
2155 int save_tracepoint_printk;
2156 int ret;
2157
2158 mutex_lock(&tracepoint_printk_mutex);
2159 save_tracepoint_printk = tracepoint_printk;
2160
2161 ret = proc_dointvec(table, write, buffer, lenp, ppos);
2162
2163 /*
2164 * This will force exiting early, as tracepoint_printk
2165 * is always zero when tracepoint_printk_iter is not allocated
2166 */
2167 if (!tracepoint_print_iter)
2168 tracepoint_printk = 0;
2169
2170 if (save_tracepoint_printk == tracepoint_printk)
2171 goto out;
2172
2173 if (tracepoint_printk)
2174 static_key_enable(&tracepoint_printk_key.key);
2175 else
2176 static_key_disable(&tracepoint_printk_key.key);
2177
2178 out:
2179 mutex_unlock(&tracepoint_printk_mutex);
2180
2181 return ret;
2182}
2183
2184void trace_event_buffer_commit(struct trace_event_buffer *fbuffer)
2185{
2186 if (static_key_false(&tracepoint_printk_key.key))
2187 output_printk(fbuffer);
2188
2189 event_trigger_unlock_commit(fbuffer->trace_file, fbuffer->buffer,
2190 fbuffer->event, fbuffer->entry,
2191 fbuffer->flags, fbuffer->pc);
2192}
2193EXPORT_SYMBOL_GPL(trace_event_buffer_commit);
2194
2119void trace_buffer_unlock_commit_regs(struct trace_array *tr, 2195void trace_buffer_unlock_commit_regs(struct trace_array *tr,
2120 struct ring_buffer *buffer, 2196 struct ring_buffer *buffer,
2121 struct ring_buffer_event *event, 2197 struct ring_buffer_event *event,
@@ -7977,6 +8053,8 @@ void __init trace_init(void)
7977 kmalloc(sizeof(*tracepoint_print_iter), GFP_KERNEL); 8053 kmalloc(sizeof(*tracepoint_print_iter), GFP_KERNEL);
7978 if (WARN_ON(!tracepoint_print_iter)) 8054 if (WARN_ON(!tracepoint_print_iter))
7979 tracepoint_printk = 0; 8055 tracepoint_printk = 0;
8056 else
8057 static_key_enable(&tracepoint_printk_key.key);
7980 } 8058 }
7981 tracer_alloc_buffers(); 8059 tracer_alloc_buffers();
7982 trace_event_init(); 8060 trace_event_init();
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index ba67ede48822..d35fc2b0d304 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -283,46 +283,6 @@ void *trace_event_buffer_reserve(struct trace_event_buffer *fbuffer,
283} 283}
284EXPORT_SYMBOL_GPL(trace_event_buffer_reserve); 284EXPORT_SYMBOL_GPL(trace_event_buffer_reserve);
285 285
286static DEFINE_SPINLOCK(tracepoint_iter_lock);
287
288static void output_printk(struct trace_event_buffer *fbuffer)
289{
290 struct trace_event_call *event_call;
291 struct trace_event *event;
292 unsigned long flags;
293 struct trace_iterator *iter = tracepoint_print_iter;
294
295 if (!iter)
296 return;
297
298 event_call = fbuffer->trace_file->event_call;
299 if (!event_call || !event_call->event.funcs ||
300 !event_call->event.funcs->trace)
301 return;
302
303 event = &fbuffer->trace_file->event_call->event;
304
305 spin_lock_irqsave(&tracepoint_iter_lock, flags);
306 trace_seq_init(&iter->seq);
307 iter->ent = fbuffer->entry;
308 event_call->event.funcs->trace(iter, 0, event);
309 trace_seq_putc(&iter->seq, 0);
310 printk("%s", iter->seq.buffer);
311
312 spin_unlock_irqrestore(&tracepoint_iter_lock, flags);
313}
314
315void trace_event_buffer_commit(struct trace_event_buffer *fbuffer)
316{
317 if (tracepoint_printk)
318 output_printk(fbuffer);
319
320 event_trigger_unlock_commit(fbuffer->trace_file, fbuffer->buffer,
321 fbuffer->event, fbuffer->entry,
322 fbuffer->flags, fbuffer->pc);
323}
324EXPORT_SYMBOL_GPL(trace_event_buffer_commit);
325
326int trace_event_reg(struct trace_event_call *call, 286int trace_event_reg(struct trace_event_call *call,
327 enum trace_reg type, void *data) 287 enum trace_reg type, void *data)
328{ 288{