Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1427cdf0 authored by Lai Jiangshan's avatar Lai Jiangshan Committed by Ingo Molnar
Browse files

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.

[fweisbec@gmail.com: rebase against latest -tip, make it safe while sched
tracing as reported by Steven Rostedt]

Signed-off-by: default avatarLai Jiangshan <laijs@cn.fujitsu.com>
Signed-off-by: default avatarFrederic Weisbecker <fweisbec@gmail.com>
Acked-by: default avatarSteven Rostedt <rostedt@goodmis.org>
LKML-Reference: <1236356510-8381-3-git-send-email-fweisbec@gmail.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 546e5354
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -223,6 +223,9 @@ extern int ftrace_make_nop(struct module *mod,
 */
extern int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr);

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

/* May be defined in arch */
extern int ftrace_arch_read_dyn_info(char *buf, int size);
+6 −0
Original line number Diff line number Diff line
@@ -97,6 +97,12 @@ config FUNCTION_GRAPH_TRACER
	  This is done by setting the current return address on the current
	  task structure into a stack of calls.

config TRACE_BPRINTK
	bool "Binary printk for tracing"
	default y
	depends on TRACING
	select BINARY_PRINTF

config IRQSOFF_TRACER
	bool "Interrupts-off Latency Tracer"
	default n
+1 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ obj-$(CONFIG_TRACING) += trace.o
obj-$(CONFIG_TRACING) += trace_clock.o
obj-$(CONFIG_TRACING) += trace_output.o
obj-$(CONFIG_TRACING) += trace_stat.o
obj-$(CONFIG_TRACE_BPRINTK) += trace_bprintk.o
obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o
obj-$(CONFIG_SYSPROF_TRACER) += trace_sysprof.o
obj-$(CONFIG_FUNCTION_TRACER) += trace_functions.o
+56 −0
Original line number Diff line number Diff line
@@ -3792,6 +3792,62 @@ int __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap)
}
EXPORT_SYMBOL_GPL(__ftrace_vprintk);

/**
 * trace_vbprintk - write binary msg to tracing buffer
 *
 * Caller must insure @fmt are valid when msg is in tracing buffer.
 */
int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
{
	static DEFINE_SPINLOCK(trace_buf_lock);
	static u32 trace_buf[TRACE_BUF_SIZE];

	struct ring_buffer_event *event;
	struct trace_array *tr = &global_trace;
	struct trace_array_cpu *data;
	struct bprintk_entry *entry;
	unsigned long flags;
	int resched;
	int cpu, len = 0, size, pc;

	if (tracing_disabled || !trace_bprintk_enable)
		return 0;

	pc = preempt_count();
	resched = ftrace_preempt_disable();
	cpu = raw_smp_processor_id();
	data = tr->data[cpu];

	if (unlikely(atomic_read(&data->disabled)))
		goto out;

	spin_lock_irqsave(&trace_buf_lock, flags);
	len = vbin_printf(trace_buf, TRACE_BUF_SIZE, fmt, args);

	if (len > TRACE_BUF_SIZE || len < 0)
		goto out_unlock;

	size = sizeof(*entry) + sizeof(u32) * len;
	event = trace_buffer_lock_reserve(tr, TRACE_BPRINTK, size, flags, pc);
	if (!event)
		goto out_unlock;
	entry = ring_buffer_event_data(event);
	entry->ip			= ip;
	entry->fmt			= fmt;

	memcpy(entry->buf, trace_buf, sizeof(u32) * len);
	ring_buffer_unlock_commit(tr->buffer, event);

out_unlock:
	spin_unlock_irqrestore(&trace_buf_lock, flags);

out:
	ftrace_preempt_enable(resched);

	return len;
}
EXPORT_SYMBOL_GPL(trace_vbprintk);

static int trace_panic_handler(struct notifier_block *this,
			       unsigned long event, void *unused)
{
+12 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ enum trace_type {
	TRACE_WAKE,
	TRACE_STACK,
	TRACE_PRINT,
	TRACE_BPRINTK,
	TRACE_SPECIAL,
	TRACE_MMIO_RW,
	TRACE_MMIO_MAP,
@@ -124,6 +125,16 @@ struct print_entry {
	char			buf[];
};

struct bprintk_entry {
	struct trace_entry ent;
	unsigned long ip;
	const char *fmt;
	u32 buf[];
};
#ifdef CONFIG_TRACE_BPRINTK
extern int trace_bprintk_enable;
#endif

#define TRACE_OLD_SIZE		88

struct trace_field_cont {
@@ -285,6 +296,7 @@ extern void __ftrace_bad_type(void);
		IF_ASSIGN(var, ent, struct stack_entry, TRACE_STACK);	\
		IF_ASSIGN(var, ent, struct userstack_entry, TRACE_USER_STACK);\
		IF_ASSIGN(var, ent, struct print_entry, TRACE_PRINT);	\
		IF_ASSIGN(var, ent, struct bprintk_entry, TRACE_BPRINTK);\
		IF_ASSIGN(var, ent, struct special_entry, 0);		\
		IF_ASSIGN(var, ent, struct trace_mmiotrace_rw,		\
			  TRACE_MMIO_RW);				\
Loading