Skip to content

Commit 1427cdf

Browse files
Lai JiangshanIngo Molnar
authored andcommitted
tracing: infrastructure for supporting binary record
Impact: save on memory for tracing Current tracers are typically using a struct(like struct ftrace_entry, struct ctx_switch_entry, struct special_entr etc...)to record a binary event. These structs can only record a their own kind of events. A new kind of tracer need a new struct and a lot of code too handle it. So we need a generic binary record for events. This infrastructure is for this purpose. [[email protected]: rebase against latest -tip, make it safe while sched tracing as 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 546e535 commit 1427cdf

File tree

7 files changed

+240
-0
lines changed

7 files changed

+240
-0
lines changed

include/linux/ftrace.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,9 @@ extern int ftrace_make_nop(struct module *mod,
223223
*/
224224
extern int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr);
225225

226+
#ifdef CONFIG_TRACE_BPRINTK
227+
extern int trace_vbprintk(unsigned long ip, const char *fmt, va_list args);
228+
#endif
226229

227230
/* May be defined in arch */
228231
extern int ftrace_arch_read_dyn_info(char *buf, int size);

kernel/trace/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@ config FUNCTION_GRAPH_TRACER
9797
This is done by setting the current return address on the current
9898
task structure into a stack of calls.
9999

100+
config TRACE_BPRINTK
101+
bool "Binary printk for tracing"
102+
default y
103+
depends on TRACING
104+
select BINARY_PRINTF
105+
100106
config IRQSOFF_TRACER
101107
bool "Interrupts-off Latency Tracer"
102108
default n

kernel/trace/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ obj-$(CONFIG_TRACING) += trace.o
2222
obj-$(CONFIG_TRACING) += trace_clock.o
2323
obj-$(CONFIG_TRACING) += trace_output.o
2424
obj-$(CONFIG_TRACING) += trace_stat.o
25+
obj-$(CONFIG_TRACE_BPRINTK) += trace_bprintk.o
2526
obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o
2627
obj-$(CONFIG_SYSPROF_TRACER) += trace_sysprof.o
2728
obj-$(CONFIG_FUNCTION_TRACER) += trace_functions.o

kernel/trace/trace.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3792,6 +3792,62 @@ int __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap)
37923792
}
37933793
EXPORT_SYMBOL_GPL(__ftrace_vprintk);
37943794

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

kernel/trace/trace.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ enum trace_type {
2020
TRACE_WAKE,
2121
TRACE_STACK,
2222
TRACE_PRINT,
23+
TRACE_BPRINTK,
2324
TRACE_SPECIAL,
2425
TRACE_MMIO_RW,
2526
TRACE_MMIO_MAP,
@@ -124,6 +125,16 @@ struct print_entry {
124125
char buf[];
125126
};
126127

128+
struct bprintk_entry {
129+
struct trace_entry ent;
130+
unsigned long ip;
131+
const char *fmt;
132+
u32 buf[];
133+
};
134+
#ifdef CONFIG_TRACE_BPRINTK
135+
extern int trace_bprintk_enable;
136+
#endif
137+
127138
#define TRACE_OLD_SIZE 88
128139

129140
struct trace_field_cont {
@@ -285,6 +296,7 @@ extern void __ftrace_bad_type(void);
285296
IF_ASSIGN(var, ent, struct stack_entry, TRACE_STACK); \
286297
IF_ASSIGN(var, ent, struct userstack_entry, TRACE_USER_STACK);\
287298
IF_ASSIGN(var, ent, struct print_entry, TRACE_PRINT); \
299+
IF_ASSIGN(var, ent, struct bprintk_entry, TRACE_BPRINTK);\
288300
IF_ASSIGN(var, ent, struct special_entry, 0); \
289301
IF_ASSIGN(var, ent, struct trace_mmiotrace_rw, \
290302
TRACE_MMIO_RW); \

kernel/trace/trace_bprintk.c

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* trace binary printk
3+
*
4+
* Copyright (C) 2008 Lai Jiangshan <[email protected]>
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+
/* binary printk basic */
23+
static DEFINE_MUTEX(btrace_mutex);
24+
static int btrace_metadata_count;
25+
26+
static inline void lock_btrace(void)
27+
{
28+
mutex_lock(&btrace_mutex);
29+
}
30+
31+
static inline void unlock_btrace(void)
32+
{
33+
mutex_unlock(&btrace_mutex);
34+
}
35+
36+
static void get_btrace_metadata(void)
37+
{
38+
lock_btrace();
39+
btrace_metadata_count++;
40+
unlock_btrace();
41+
}
42+
43+
static void put_btrace_metadata(void)
44+
{
45+
lock_btrace();
46+
btrace_metadata_count--;
47+
unlock_btrace();
48+
}
49+
50+
/* events tracer */
51+
int trace_bprintk_enable;
52+
53+
static void start_bprintk_trace(struct trace_array *tr)
54+
{
55+
get_btrace_metadata();
56+
tracing_reset_online_cpus(tr);
57+
trace_bprintk_enable = 1;
58+
}
59+
60+
static void stop_bprintk_trace(struct trace_array *tr)
61+
{
62+
trace_bprintk_enable = 0;
63+
tracing_reset_online_cpus(tr);
64+
put_btrace_metadata();
65+
}
66+
67+
static int init_bprintk_trace(struct trace_array *tr)
68+
{
69+
start_bprintk_trace(tr);
70+
return 0;
71+
}
72+
73+
static struct tracer bprintk_trace __read_mostly =
74+
{
75+
.name = "events",
76+
.init = init_bprintk_trace,
77+
.reset = stop_bprintk_trace,
78+
.start = start_bprintk_trace,
79+
.stop = stop_bprintk_trace,
80+
};
81+
82+
static __init int init_bprintk(void)
83+
{
84+
return register_tracer(&bprintk_trace);
85+
}
86+
87+
device_initcall(init_bprintk);

kernel/trace/trace_output.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,26 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
5353
return len;
5454
}
5555

56+
static int
57+
trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary)
58+
{
59+
int len = (PAGE_SIZE - 1) - s->len;
60+
int ret;
61+
62+
if (!len)
63+
return 0;
64+
65+
ret = bstr_printf(s->buffer + s->len, len, fmt, binary);
66+
67+
/* If we can't write it all, don't bother writing anything */
68+
if (ret >= len)
69+
return 0;
70+
71+
s->len += ret;
72+
73+
return len;
74+
}
75+
5676
/**
5777
* trace_seq_puts - trace sequence printing of simple string
5878
* @s: trace sequence descriptor
@@ -855,6 +875,60 @@ static struct trace_event trace_print_event = {
855875
.raw = trace_print_raw,
856876
};
857877

878+
/* TRACE_BPRINTK */
879+
static enum print_line_t
880+
trace_bprintk_print(struct trace_iterator *iter, int flags)
881+
{
882+
struct trace_entry *entry = iter->ent;
883+
struct trace_seq *s = &iter->seq;
884+
struct bprintk_entry *field;
885+
886+
trace_assign_type(field, entry);
887+
888+
if (!seq_print_ip_sym(s, field->ip, flags))
889+
goto partial;
890+
891+
if (!trace_seq_puts(s, ": "))
892+
goto partial;
893+
894+
if (!trace_seq_bprintf(s, field->fmt, field->buf))
895+
goto partial;
896+
897+
return TRACE_TYPE_HANDLED;
898+
899+
partial:
900+
return TRACE_TYPE_PARTIAL_LINE;
901+
}
902+
903+
static enum print_line_t
904+
trace_bprintk_raw(struct trace_iterator *iter, int flags)
905+
{
906+
struct trace_entry *entry = iter->ent;
907+
struct trace_seq *s = &iter->seq;
908+
struct bprintk_entry *field;
909+
910+
trace_assign_type(field, entry);
911+
912+
if (!trace_seq_printf(s, ": %lx : ", field->ip))
913+
goto partial;
914+
915+
if (!trace_seq_bprintf(s, field->fmt, field->buf))
916+
goto partial;
917+
918+
return TRACE_TYPE_HANDLED;
919+
920+
partial:
921+
return TRACE_TYPE_PARTIAL_LINE;
922+
}
923+
924+
static struct trace_event trace_bprintk_event = {
925+
.type = TRACE_BPRINTK,
926+
.trace = trace_bprintk_print,
927+
.raw = trace_bprintk_raw,
928+
.hex = trace_nop_print,
929+
.binary = trace_nop_print,
930+
};
931+
858932
static struct trace_event *events[] __initdata = {
859933
&trace_fn_event,
860934
&trace_ctx_event,
@@ -863,6 +937,7 @@ static struct trace_event *events[] __initdata = {
863937
&trace_stack_event,
864938
&trace_user_stack_event,
865939
&trace_print_event,
940+
&trace_bprintk_event,
866941
NULL
867942
};
868943

0 commit comments

Comments
 (0)