Skip to content

Commit 1ba28e0

Browse files
Lai JiangshanIngo Molnar
authored andcommitted
tracing: add trace_bprintk()
Impact: add a generic printk() for tracing, like trace_printk() trace_bprintk() uses the infrastructure to record events on ring_buffer. [ [email protected]: ported to latest -tip, made it work if !CONFIG_MODULES, never free the format strings from modules because we can't keep track of them and conditionnaly create the ftrace format strings section (reported by Steven Rostedt) ] Signed-off-by: Lai Jiangshan <[email protected]> Signed-off-by: Frederic Weisbecker <[email protected]> Acked-by: Steven Rostedt <[email protected]> LKML-Reference: <[email protected]> Signed-off-by: Ingo Molnar <[email protected]>
1 parent 1427cdf commit 1ba28e0

File tree

6 files changed

+133
-10
lines changed

6 files changed

+133
-10
lines changed

include/asm-generic/vmlinux.lds.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,14 @@
6969
#define FTRACE_EVENTS()
7070
#endif
7171

72+
#ifdef CONFIG_TRACING
73+
#define TRACE_PRINTKS() VMLINUX_SYMBOL(__start___trace_bprintk_fmt) = .; \
74+
*(__trace_printk_fmt) /* Trace_printk fmt' pointer */ \
75+
VMLINUX_SYMBOL(__stop___trace_bprintk_fmt) = .;
76+
#else
77+
#define TRACE_PRINTKS()
78+
#endif
79+
7280
/* .data section */
7381
#define DATA_DATA \
7482
*(.data) \
@@ -100,6 +108,7 @@
100108
*(__vermagic) /* Kernel version magic */ \
101109
*(__markers_strings) /* Markers: strings */ \
102110
*(__tracepoints_strings)/* Tracepoints: strings */ \
111+
TRACE_PRINTKS() \
103112
} \
104113
\
105114
.rodata1 : AT(ADDR(.rodata1) - LOAD_OFFSET) { \

include/linux/ftrace.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,27 @@ extern int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr);
225225

226226
#ifdef CONFIG_TRACE_BPRINTK
227227
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
228249
#endif
229250

230251
/* May be defined in arch */

include/linux/module.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,11 @@ struct module
329329
unsigned int num_tracepoints;
330330
#endif
331331

332+
#ifdef CONFIG_TRACE_BPRINTK
333+
const char **trace_bprintk_fmt_start;
334+
unsigned int num_trace_bprintk_fmt;
335+
#endif
336+
332337
#ifdef CONFIG_MODULE_UNLOAD
333338
/* What modules depend on me? */
334339
struct list_head modules_which_use_me;

kernel/module.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2158,6 +2158,12 @@ static noinline struct module *load_module(void __user *umod,
21582158
&mod->num_tracepoints);
21592159
#endif
21602160

2161+
#ifdef CONFIG_TRACE_BPRINTK
2162+
mod->trace_bprintk_fmt_start = section_objs(hdr, sechdrs, secstrings,
2163+
"__trace_bprintk_fmt", sizeof(char *),
2164+
&mod->num_trace_bprintk_fmt);
2165+
#endif
2166+
21612167
#ifdef CONFIG_MODVERSIONS
21622168
if ((mod->num_syms && !mod->crcs)
21632169
|| (mod->num_gpl_syms && !mod->gpl_crcs)

kernel/trace/trace.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3848,6 +3848,21 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
38483848
}
38493849
EXPORT_SYMBOL_GPL(trace_vbprintk);
38503850

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+
38513866
static int trace_panic_handler(struct notifier_block *this,
38523867
unsigned long event, void *unused)
38533868
{

kernel/trace/trace_bprintk.c

Lines changed: 77 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,21 @@
1919

2020
#include "trace.h"
2121

22+
#ifdef CONFIG_MODULES
23+
2224
/* binary printk basic */
2325
static DEFINE_MUTEX(btrace_mutex);
24-
static int btrace_metadata_count;
26+
/*
27+
* modules trace_bprintk()'s formats are autosaved in struct trace_bprintk_fmt
28+
* which are queued on trace_bprintk_fmt_list.
29+
*/
30+
static LIST_HEAD(trace_bprintk_fmt_list);
31+
32+
struct trace_bprintk_fmt {
33+
struct list_head list;
34+
char fmt[0];
35+
};
36+
2537

2638
static inline void lock_btrace(void)
2739
{
@@ -33,26 +45,75 @@ static inline void unlock_btrace(void)
3345
mutex_unlock(&btrace_mutex);
3446
}
3547

36-
static void get_btrace_metadata(void)
48+
49+
static inline struct trace_bprintk_fmt *lookup_format(const char *fmt)
3750
{
38-
lock_btrace();
39-
btrace_metadata_count++;
40-
unlock_btrace();
51+
struct trace_bprintk_fmt *pos;
52+
list_for_each_entry(pos, &trace_bprintk_fmt_list, list) {
53+
if (!strcmp(pos->fmt, fmt))
54+
return pos;
55+
}
56+
return NULL;
4157
}
4258

43-
static void put_btrace_metadata(void)
59+
static
60+
void hold_module_trace_bprintk_format(const char **start, const char **end)
4461
{
62+
const char **iter;
4563
lock_btrace();
46-
btrace_metadata_count--;
64+
for (iter = start; iter < end; iter++) {
65+
struct trace_bprintk_fmt *tb_fmt = lookup_format(*iter);
66+
if (tb_fmt) {
67+
*iter = tb_fmt->fmt;
68+
continue;
69+
}
70+
71+
tb_fmt = kmalloc(offsetof(struct trace_bprintk_fmt, fmt)
72+
+ strlen(*iter) + 1, GFP_KERNEL);
73+
if (tb_fmt) {
74+
list_add_tail(&tb_fmt->list, &trace_bprintk_fmt_list);
75+
strcpy(tb_fmt->fmt, *iter);
76+
*iter = tb_fmt->fmt;
77+
} else
78+
*iter = NULL;
79+
}
4780
unlock_btrace();
4881
}
4982

83+
static int module_trace_bprintk_format_notify(struct notifier_block *self,
84+
unsigned long val, void *data)
85+
{
86+
struct module *mod = data;
87+
if (mod->num_trace_bprintk_fmt) {
88+
const char **start = mod->trace_bprintk_fmt_start;
89+
const char **end = start + mod->num_trace_bprintk_fmt;
90+
91+
if (val == MODULE_STATE_COMING)
92+
hold_module_trace_bprintk_format(start, end);
93+
}
94+
return 0;
95+
}
96+
97+
#else /* !CONFIG_MODULES */
98+
__init static int
99+
module_trace_bprintk_format_notify(struct notifier_block *self,
100+
unsigned long val, void *data)
101+
{
102+
return 0;
103+
}
104+
#endif /* CONFIG_MODULES */
105+
106+
107+
__initdata_or_module static
108+
struct notifier_block module_trace_bprintk_format_nb = {
109+
.notifier_call = module_trace_bprintk_format_notify,
110+
};
111+
50112
/* events tracer */
51113
int trace_bprintk_enable;
52114

53115
static void start_bprintk_trace(struct trace_array *tr)
54116
{
55-
get_btrace_metadata();
56117
tracing_reset_online_cpus(tr);
57118
trace_bprintk_enable = 1;
58119
}
@@ -61,7 +122,6 @@ static void stop_bprintk_trace(struct trace_array *tr)
61122
{
62123
trace_bprintk_enable = 0;
63124
tracing_reset_online_cpus(tr);
64-
put_btrace_metadata();
65125
}
66126

67127
static int init_bprintk_trace(struct trace_array *tr)
@@ -81,7 +141,14 @@ static struct tracer bprintk_trace __read_mostly =
81141

82142
static __init int init_bprintk(void)
83143
{
84-
return register_tracer(&bprintk_trace);
144+
int ret = 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;
85152
}
86153

87154
device_initcall(init_bprintk);

0 commit comments

Comments
 (0)