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

Commit 568b329a authored by Alexei Starovoitov's avatar Alexei Starovoitov Committed by David S. Miller
Browse files

perf: generalize perf_callchain



. avoid walking the stack when there is no room left in the buffer
. generalize get_perf_callchain() to be called from bpf helper

Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6b83d28a
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -37,7 +37,7 @@ print_context_stack_bp(struct thread_info *tinfo,
/* Generic stack tracer with callbacks */
/* Generic stack tracer with callbacks */


struct stacktrace_ops {
struct stacktrace_ops {
	void (*address)(void *data, unsigned long address, int reliable);
	int (*address)(void *data, unsigned long address, int reliable);
	/* On negative return stop dumping */
	/* On negative return stop dumping */
	int (*stack)(void *data, char *name);
	int (*stack)(void *data, char *name);
	walk_stack_t	walk_stack;
	walk_stack_t	walk_stack;
+2 −2
Original line number Original line Diff line number Diff line
@@ -2180,11 +2180,11 @@ static int backtrace_stack(void *data, char *name)
	return 0;
	return 0;
}
}


static void backtrace_address(void *data, unsigned long addr, int reliable)
static int backtrace_address(void *data, unsigned long addr, int reliable)
{
{
	struct perf_callchain_entry *entry = data;
	struct perf_callchain_entry *entry = data;


	perf_callchain_store(entry, addr);
	return perf_callchain_store(entry, addr);
}
}


static const struct stacktrace_ops backtrace_ops = {
static const struct stacktrace_ops backtrace_ops = {
+4 −2
Original line number Original line Diff line number Diff line
@@ -135,7 +135,8 @@ print_context_stack_bp(struct thread_info *tinfo,
		if (!__kernel_text_address(addr))
		if (!__kernel_text_address(addr))
			break;
			break;


		ops->address(data, addr, 1);
		if (ops->address(data, addr, 1))
			break;
		frame = frame->next_frame;
		frame = frame->next_frame;
		ret_addr = &frame->return_address;
		ret_addr = &frame->return_address;
		print_ftrace_graph_addr(addr, data, ops, tinfo, graph);
		print_ftrace_graph_addr(addr, data, ops, tinfo, graph);
@@ -154,10 +155,11 @@ static int print_trace_stack(void *data, char *name)
/*
/*
 * Print one address/symbol entries per line.
 * Print one address/symbol entries per line.
 */
 */
static void print_trace_address(void *data, unsigned long addr, int reliable)
static int print_trace_address(void *data, unsigned long addr, int reliable)
{
{
	touch_nmi_watchdog();
	touch_nmi_watchdog();
	printk_stack_address(addr, reliable, data);
	printk_stack_address(addr, reliable, data);
	return 0;
}
}


static const struct stacktrace_ops print_trace_ops = {
static const struct stacktrace_ops print_trace_ops = {
+11 −7
Original line number Original line Diff line number Diff line
@@ -14,30 +14,34 @@ static int save_stack_stack(void *data, char *name)
	return 0;
	return 0;
}
}


static void
static int
__save_stack_address(void *data, unsigned long addr, bool reliable, bool nosched)
__save_stack_address(void *data, unsigned long addr, bool reliable, bool nosched)
{
{
	struct stack_trace *trace = data;
	struct stack_trace *trace = data;
#ifdef CONFIG_FRAME_POINTER
#ifdef CONFIG_FRAME_POINTER
	if (!reliable)
	if (!reliable)
		return;
		return 0;
#endif
#endif
	if (nosched && in_sched_functions(addr))
	if (nosched && in_sched_functions(addr))
		return;
		return 0;
	if (trace->skip > 0) {
	if (trace->skip > 0) {
		trace->skip--;
		trace->skip--;
		return;
		return 0;
	}
	}
	if (trace->nr_entries < trace->max_entries)
	if (trace->nr_entries < trace->max_entries) {
		trace->entries[trace->nr_entries++] = addr;
		trace->entries[trace->nr_entries++] = addr;
		return 0;
	} else {
		return -1; /* no more room, stop walking the stack */
	}
}
}


static void save_stack_address(void *data, unsigned long addr, int reliable)
static int save_stack_address(void *data, unsigned long addr, int reliable)
{
{
	return __save_stack_address(data, addr, reliable, false);
	return __save_stack_address(data, addr, reliable, false);
}
}


static void
static int
save_stack_address_nosched(void *data, unsigned long addr, int reliable)
save_stack_address_nosched(void *data, unsigned long addr, int reliable)
{
{
	return __save_stack_address(data, addr, reliable, true);
	return __save_stack_address(data, addr, reliable, true);
+2 −1
Original line number Original line Diff line number Diff line
@@ -23,12 +23,13 @@ static int backtrace_stack(void *data, char *name)
	return 0;
	return 0;
}
}


static void backtrace_address(void *data, unsigned long addr, int reliable)
static int backtrace_address(void *data, unsigned long addr, int reliable)
{
{
	unsigned int *depth = data;
	unsigned int *depth = data;


	if ((*depth)--)
	if ((*depth)--)
		oprofile_add_trace(addr);
		oprofile_add_trace(addr);
	return 0;
}
}


static struct stacktrace_ops backtrace_ops = {
static struct stacktrace_ops backtrace_ops = {
Loading