Commit 457d2ee2 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'tracing-fixes-for-linus' of...

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, ring-buffer: add paranoid checks for loops
  ftrace: use kretprobe trampoline name to test in output
  tracing, alpha: undefined reference to `save_stack_trace'
parents da4a22cb 818e3dd3
...@@ -25,7 +25,7 @@ config TRACING ...@@ -25,7 +25,7 @@ config TRACING
bool bool
select DEBUG_FS select DEBUG_FS
select RING_BUFFER select RING_BUFFER
select STACKTRACE select STACKTRACE if STACKTRACE_SUPPORT
select TRACEPOINTS select TRACEPOINTS
select NOP_TRACER select NOP_TRACER
......
...@@ -1022,8 +1022,23 @@ rb_reserve_next_event(struct ring_buffer_per_cpu *cpu_buffer, ...@@ -1022,8 +1022,23 @@ rb_reserve_next_event(struct ring_buffer_per_cpu *cpu_buffer,
struct ring_buffer_event *event; struct ring_buffer_event *event;
u64 ts, delta; u64 ts, delta;
int commit = 0; int commit = 0;
int nr_loops = 0;
again: again:
/*
* We allow for interrupts to reenter here and do a trace.
* If one does, it will cause this original code to loop
* back here. Even with heavy interrupts happening, this
* should only happen a few times in a row. If this happens
* 1000 times in a row, there must be either an interrupt
* storm or we have something buggy.
* Bail!
*/
if (unlikely(++nr_loops > 1000)) {
RB_WARN_ON(cpu_buffer, 1);
return NULL;
}
ts = ring_buffer_time_stamp(cpu_buffer->cpu); ts = ring_buffer_time_stamp(cpu_buffer->cpu);
/* /*
...@@ -1532,10 +1547,23 @@ rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer) ...@@ -1532,10 +1547,23 @@ rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer)
{ {
struct buffer_page *reader = NULL; struct buffer_page *reader = NULL;
unsigned long flags; unsigned long flags;
int nr_loops = 0;
spin_lock_irqsave(&cpu_buffer->lock, flags); spin_lock_irqsave(&cpu_buffer->lock, flags);
again: again:
/*
* This should normally only loop twice. But because the
* start of the reader inserts an empty page, it causes
* a case where we will loop three times. There should be no
* reason to loop four times (that I know of).
*/
if (unlikely(++nr_loops > 3)) {
RB_WARN_ON(cpu_buffer, 1);
reader = NULL;
goto out;
}
reader = cpu_buffer->reader_page; reader = cpu_buffer->reader_page;
/* If there's more to read, return this page */ /* If there's more to read, return this page */
...@@ -1665,6 +1693,7 @@ ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts) ...@@ -1665,6 +1693,7 @@ ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts)
struct ring_buffer_per_cpu *cpu_buffer; struct ring_buffer_per_cpu *cpu_buffer;
struct ring_buffer_event *event; struct ring_buffer_event *event;
struct buffer_page *reader; struct buffer_page *reader;
int nr_loops = 0;
if (!cpu_isset(cpu, buffer->cpumask)) if (!cpu_isset(cpu, buffer->cpumask))
return NULL; return NULL;
...@@ -1672,6 +1701,19 @@ ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts) ...@@ -1672,6 +1701,19 @@ ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts)
cpu_buffer = buffer->buffers[cpu]; cpu_buffer = buffer->buffers[cpu];
again: again:
/*
* We repeat when a timestamp is encountered. It is possible
* to get multiple timestamps from an interrupt entering just
* as one timestamp is about to be written. The max times
* that this can happen is the number of nested interrupts we
* can have. Nesting 10 deep of interrupts is clearly
* an anomaly.
*/
if (unlikely(++nr_loops > 10)) {
RB_WARN_ON(cpu_buffer, 1);
return NULL;
}
reader = rb_get_reader_page(cpu_buffer); reader = rb_get_reader_page(cpu_buffer);
if (!reader) if (!reader)
return NULL; return NULL;
...@@ -1722,6 +1764,7 @@ ring_buffer_iter_peek(struct ring_buffer_iter *iter, u64 *ts) ...@@ -1722,6 +1764,7 @@ ring_buffer_iter_peek(struct ring_buffer_iter *iter, u64 *ts)
struct ring_buffer *buffer; struct ring_buffer *buffer;
struct ring_buffer_per_cpu *cpu_buffer; struct ring_buffer_per_cpu *cpu_buffer;
struct ring_buffer_event *event; struct ring_buffer_event *event;
int nr_loops = 0;
if (ring_buffer_iter_empty(iter)) if (ring_buffer_iter_empty(iter))
return NULL; return NULL;
...@@ -1730,6 +1773,19 @@ ring_buffer_iter_peek(struct ring_buffer_iter *iter, u64 *ts) ...@@ -1730,6 +1773,19 @@ ring_buffer_iter_peek(struct ring_buffer_iter *iter, u64 *ts)
buffer = cpu_buffer->buffer; buffer = cpu_buffer->buffer;
again: again:
/*
* We repeat when a timestamp is encountered. It is possible
* to get multiple timestamps from an interrupt entering just
* as one timestamp is about to be written. The max times
* that this can happen is the number of nested interrupts we
* can have. Nesting 10 deep of interrupts is clearly
* an anomaly.
*/
if (unlikely(++nr_loops > 10)) {
RB_WARN_ON(cpu_buffer, 1);
return NULL;
}
if (rb_per_cpu_empty(cpu_buffer)) if (rb_per_cpu_empty(cpu_buffer))
return NULL; return NULL;
......
...@@ -705,6 +705,7 @@ static void ftrace_trace_stack(struct trace_array *tr, ...@@ -705,6 +705,7 @@ static void ftrace_trace_stack(struct trace_array *tr,
unsigned long flags, unsigned long flags,
int skip, int pc) int skip, int pc)
{ {
#ifdef CONFIG_STACKTRACE
struct ring_buffer_event *event; struct ring_buffer_event *event;
struct stack_entry *entry; struct stack_entry *entry;
struct stack_trace trace; struct stack_trace trace;
...@@ -730,6 +731,7 @@ static void ftrace_trace_stack(struct trace_array *tr, ...@@ -730,6 +731,7 @@ static void ftrace_trace_stack(struct trace_array *tr,
save_stack_trace(&trace); save_stack_trace(&trace);
ring_buffer_unlock_commit(tr->buffer, event, irq_flags); ring_buffer_unlock_commit(tr->buffer, event, irq_flags);
#endif
} }
void __trace_stack(struct trace_array *tr, void __trace_stack(struct trace_array *tr,
...@@ -1086,17 +1088,20 @@ static void s_stop(struct seq_file *m, void *p) ...@@ -1086,17 +1088,20 @@ static void s_stop(struct seq_file *m, void *p)
mutex_unlock(&trace_types_lock); mutex_unlock(&trace_types_lock);
} }
#define KRETPROBE_MSG "[unknown/kretprobe'd]"
#ifdef CONFIG_KRETPROBES #ifdef CONFIG_KRETPROBES
static inline int kretprobed(unsigned long addr) static inline const char *kretprobed(const char *name)
{ {
return addr == (unsigned long)kretprobe_trampoline; static const char tramp_name[] = "kretprobe_trampoline";
int size = sizeof(tramp_name);
if (strncmp(tramp_name, name, size) == 0)
return "[unknown/kretprobe'd]";
return name;
} }
#else #else
static inline int kretprobed(unsigned long addr) static inline const char *kretprobed(const char *name)
{ {
return 0; return name;
} }
#endif /* CONFIG_KRETPROBES */ #endif /* CONFIG_KRETPROBES */
...@@ -1105,10 +1110,13 @@ seq_print_sym_short(struct trace_seq *s, const char *fmt, unsigned long address) ...@@ -1105,10 +1110,13 @@ seq_print_sym_short(struct trace_seq *s, const char *fmt, unsigned long address)
{ {
#ifdef CONFIG_KALLSYMS #ifdef CONFIG_KALLSYMS
char str[KSYM_SYMBOL_LEN]; char str[KSYM_SYMBOL_LEN];
const char *name;
kallsyms_lookup(address, NULL, NULL, NULL, str); kallsyms_lookup(address, NULL, NULL, NULL, str);
return trace_seq_printf(s, fmt, str); name = kretprobed(str);
return trace_seq_printf(s, fmt, name);
#endif #endif
return 1; return 1;
} }
...@@ -1119,9 +1127,12 @@ seq_print_sym_offset(struct trace_seq *s, const char *fmt, ...@@ -1119,9 +1127,12 @@ seq_print_sym_offset(struct trace_seq *s, const char *fmt,
{ {
#ifdef CONFIG_KALLSYMS #ifdef CONFIG_KALLSYMS
char str[KSYM_SYMBOL_LEN]; char str[KSYM_SYMBOL_LEN];
const char *name;
sprint_symbol(str, address); sprint_symbol(str, address);
return trace_seq_printf(s, fmt, str); name = kretprobed(str);
return trace_seq_printf(s, fmt, name);
#endif #endif
return 1; return 1;
} }
...@@ -1375,10 +1386,7 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) ...@@ -1375,10 +1386,7 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)
seq_print_ip_sym(s, field->ip, sym_flags); seq_print_ip_sym(s, field->ip, sym_flags);
trace_seq_puts(s, " ("); trace_seq_puts(s, " (");
if (kretprobed(field->parent_ip)) seq_print_ip_sym(s, field->parent_ip, sym_flags);
trace_seq_puts(s, KRETPROBE_MSG);
else
seq_print_ip_sym(s, field->parent_ip, sym_flags);
trace_seq_puts(s, ")\n"); trace_seq_puts(s, ")\n");
break; break;
} }
...@@ -1494,12 +1502,9 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter) ...@@ -1494,12 +1502,9 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter)
ret = trace_seq_printf(s, " <-"); ret = trace_seq_printf(s, " <-");
if (!ret) if (!ret)
return TRACE_TYPE_PARTIAL_LINE; return TRACE_TYPE_PARTIAL_LINE;
if (kretprobed(field->parent_ip)) ret = seq_print_ip_sym(s,
ret = trace_seq_puts(s, KRETPROBE_MSG); field->parent_ip,
else sym_flags);
ret = seq_print_ip_sym(s,
field->parent_ip,
sym_flags);
if (!ret) if (!ret)
return TRACE_TYPE_PARTIAL_LINE; return TRACE_TYPE_PARTIAL_LINE;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment