Merge branch 'tracing-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'tracing-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: tracing/documentation: Cover new frame pointer semantics tracing/documentation: Fix a typo in ftrace.txt ring-buffer: Check for end of page in iterator ring-buffer: Check if ring buffer iterator has stale data tracing: Prevent kernel oops with corrupted buffer
This commit is contained in:
commit
935cc9323a
|
@ -1,5 +1,6 @@
|
|||
function tracer guts
|
||||
====================
|
||||
By Mike Frysinger
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
@ -173,14 +174,16 @@ void ftrace_graph_caller(void)
|
|||
|
||||
unsigned long *frompc = &...;
|
||||
unsigned long selfpc = <return address> - MCOUNT_INSN_SIZE;
|
||||
prepare_ftrace_return(frompc, selfpc);
|
||||
/* passing frame pointer up is optional -- see below */
|
||||
prepare_ftrace_return(frompc, selfpc, frame_pointer);
|
||||
|
||||
/* restore all state needed by the ABI */
|
||||
}
|
||||
#endif
|
||||
|
||||
For information on how to implement prepare_ftrace_return(), simply look at
|
||||
the x86 version. The only architecture-specific piece in it is the setup of
|
||||
For information on how to implement prepare_ftrace_return(), simply look at the
|
||||
x86 version (the frame pointer passing is optional; see the next section for
|
||||
more information). The only architecture-specific piece in it is the setup of
|
||||
the fault recovery table (the asm(...) code). The rest should be the same
|
||||
across architectures.
|
||||
|
||||
|
@ -205,6 +208,23 @@ void return_to_handler(void)
|
|||
#endif
|
||||
|
||||
|
||||
HAVE_FUNCTION_GRAPH_FP_TEST
|
||||
---------------------------
|
||||
|
||||
An arch may pass in a unique value (frame pointer) to both the entering and
|
||||
exiting of a function. On exit, the value is compared and if it does not
|
||||
match, then it will panic the kernel. This is largely a sanity check for bad
|
||||
code generation with gcc. If gcc for your port sanely updates the frame
|
||||
pointer under different opitmization levels, then ignore this option.
|
||||
|
||||
However, adding support for it isn't terribly difficult. In your assembly code
|
||||
that calls prepare_ftrace_return(), pass the frame pointer as the 3rd argument.
|
||||
Then in the C version of that function, do what the x86 port does and pass it
|
||||
along to ftrace_push_return_trace() instead of a stub value of 0.
|
||||
|
||||
Similarly, when you call ftrace_return_to_handler(), pass it the frame pointer.
|
||||
|
||||
|
||||
HAVE_FTRACE_NMI_ENTER
|
||||
---------------------
|
||||
|
||||
|
|
|
@ -1625,7 +1625,7 @@ If I am only interested in sys_nanosleep and hrtimer_interrupt:
|
|||
|
||||
# echo sys_nanosleep hrtimer_interrupt \
|
||||
> set_ftrace_filter
|
||||
# echo ftrace > current_tracer
|
||||
# echo function > current_tracer
|
||||
# echo 1 > tracing_enabled
|
||||
# usleep 1
|
||||
# echo 0 > tracing_enabled
|
||||
|
|
|
@ -27,9 +27,7 @@ config HAVE_FUNCTION_GRAPH_TRACER
|
|||
config HAVE_FUNCTION_GRAPH_FP_TEST
|
||||
bool
|
||||
help
|
||||
An arch may pass in a unique value (frame pointer) to both the
|
||||
entering and exiting of a function. On exit, the value is compared
|
||||
and if it does not match, then it will panic the kernel.
|
||||
See Documentation/trace/ftrace-design.txt
|
||||
|
||||
config HAVE_FUNCTION_TRACE_MCOUNT_TEST
|
||||
bool
|
||||
|
|
|
@ -464,6 +464,8 @@ struct ring_buffer_iter {
|
|||
struct ring_buffer_per_cpu *cpu_buffer;
|
||||
unsigned long head;
|
||||
struct buffer_page *head_page;
|
||||
struct buffer_page *cache_reader_page;
|
||||
unsigned long cache_read;
|
||||
u64 read_stamp;
|
||||
};
|
||||
|
||||
|
@ -2716,6 +2718,8 @@ static void rb_iter_reset(struct ring_buffer_iter *iter)
|
|||
iter->read_stamp = cpu_buffer->read_stamp;
|
||||
else
|
||||
iter->read_stamp = iter->head_page->page->time_stamp;
|
||||
iter->cache_reader_page = cpu_buffer->reader_page;
|
||||
iter->cache_read = cpu_buffer->read;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3060,13 +3064,22 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts)
|
|||
struct ring_buffer_event *event;
|
||||
int nr_loops = 0;
|
||||
|
||||
if (ring_buffer_iter_empty(iter))
|
||||
return NULL;
|
||||
|
||||
cpu_buffer = iter->cpu_buffer;
|
||||
buffer = cpu_buffer->buffer;
|
||||
|
||||
/*
|
||||
* Check if someone performed a consuming read to
|
||||
* the buffer. A consuming read invalidates the iterator
|
||||
* and we need to reset the iterator in this case.
|
||||
*/
|
||||
if (unlikely(iter->cache_read != cpu_buffer->read ||
|
||||
iter->cache_reader_page != cpu_buffer->reader_page))
|
||||
rb_iter_reset(iter);
|
||||
|
||||
again:
|
||||
if (ring_buffer_iter_empty(iter))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* We repeat when a timestamp is encountered.
|
||||
* We can get multiple timestamps by nested interrupts or also
|
||||
|
@ -3081,6 +3094,11 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts)
|
|||
if (rb_per_cpu_empty(cpu_buffer))
|
||||
return NULL;
|
||||
|
||||
if (iter->head >= local_read(&iter->head_page->page->commit)) {
|
||||
rb_inc_iter(iter);
|
||||
goto again;
|
||||
}
|
||||
|
||||
event = rb_iter_head_event(iter);
|
||||
|
||||
switch (event->type_len) {
|
||||
|
|
|
@ -951,6 +951,11 @@ void trace_find_cmdline(int pid, char comm[])
|
|||
return;
|
||||
}
|
||||
|
||||
if (WARN_ON_ONCE(pid < 0)) {
|
||||
strcpy(comm, "<XXX>");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pid > PID_MAX_DEFAULT) {
|
||||
strcpy(comm, "<...>");
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue