diff options
Diffstat (limited to 'kernel/trace')
-rw-r--r-- | kernel/trace/ring_buffer.c | 24 | ||||
-rw-r--r-- | kernel/trace/trace.c | 34 | ||||
-rw-r--r-- | kernel/trace/trace.h | 3 | ||||
-rw-r--r-- | kernel/trace/trace_entries.h | 6 | ||||
-rw-r--r-- | kernel/trace/trace_events.c | 2 | ||||
-rw-r--r-- | kernel/trace/trace_output.c | 36 |
6 files changed, 70 insertions, 35 deletions
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index bd1c35a4fbcc..db7b439d23ee 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
@@ -5,7 +5,6 @@ | |||
5 | */ | 5 | */ |
6 | #include <linux/ring_buffer.h> | 6 | #include <linux/ring_buffer.h> |
7 | #include <linux/trace_clock.h> | 7 | #include <linux/trace_clock.h> |
8 | #include <linux/ftrace_irq.h> | ||
9 | #include <linux/spinlock.h> | 8 | #include <linux/spinlock.h> |
10 | #include <linux/debugfs.h> | 9 | #include <linux/debugfs.h> |
11 | #include <linux/uaccess.h> | 10 | #include <linux/uaccess.h> |
@@ -1429,6 +1428,17 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size) | |||
1429 | } | 1428 | } |
1430 | EXPORT_SYMBOL_GPL(ring_buffer_resize); | 1429 | EXPORT_SYMBOL_GPL(ring_buffer_resize); |
1431 | 1430 | ||
1431 | void ring_buffer_change_overwrite(struct ring_buffer *buffer, int val) | ||
1432 | { | ||
1433 | mutex_lock(&buffer->mutex); | ||
1434 | if (val) | ||
1435 | buffer->flags |= RB_FL_OVERWRITE; | ||
1436 | else | ||
1437 | buffer->flags &= ~RB_FL_OVERWRITE; | ||
1438 | mutex_unlock(&buffer->mutex); | ||
1439 | } | ||
1440 | EXPORT_SYMBOL_GPL(ring_buffer_change_overwrite); | ||
1441 | |||
1432 | static inline void * | 1442 | static inline void * |
1433 | __rb_data_page_index(struct buffer_data_page *bpage, unsigned index) | 1443 | __rb_data_page_index(struct buffer_data_page *bpage, unsigned index) |
1434 | { | 1444 | { |
@@ -2162,11 +2172,19 @@ rb_reserve_next_event(struct ring_buffer *buffer, | |||
2162 | if (likely(ts >= cpu_buffer->write_stamp)) { | 2172 | if (likely(ts >= cpu_buffer->write_stamp)) { |
2163 | delta = diff; | 2173 | delta = diff; |
2164 | if (unlikely(test_time_stamp(delta))) { | 2174 | if (unlikely(test_time_stamp(delta))) { |
2175 | int local_clock_stable = 1; | ||
2176 | #ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK | ||
2177 | local_clock_stable = sched_clock_stable; | ||
2178 | #endif | ||
2165 | WARN_ONCE(delta > (1ULL << 59), | 2179 | WARN_ONCE(delta > (1ULL << 59), |
2166 | KERN_WARNING "Delta way too big! %llu ts=%llu write stamp = %llu\n", | 2180 | KERN_WARNING "Delta way too big! %llu ts=%llu write stamp = %llu\n%s", |
2167 | (unsigned long long)delta, | 2181 | (unsigned long long)delta, |
2168 | (unsigned long long)ts, | 2182 | (unsigned long long)ts, |
2169 | (unsigned long long)cpu_buffer->write_stamp); | 2183 | (unsigned long long)cpu_buffer->write_stamp, |
2184 | local_clock_stable ? "" : | ||
2185 | "If you just came from a suspend/resume,\n" | ||
2186 | "please switch to the trace global clock:\n" | ||
2187 | " echo global > /sys/kernel/debug/tracing/trace_clock\n"); | ||
2170 | add_timestamp = 1; | 2188 | add_timestamp = 1; |
2171 | } | 2189 | } |
2172 | } | 2190 | } |
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 8dc8da6733f9..9541c27c1cf2 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -41,8 +41,6 @@ | |||
41 | #include "trace.h" | 41 | #include "trace.h" |
42 | #include "trace_output.h" | 42 | #include "trace_output.h" |
43 | 43 | ||
44 | #define TRACE_BUFFER_FLAGS (RB_FL_OVERWRITE) | ||
45 | |||
46 | /* | 44 | /* |
47 | * On boot up, the ring buffer is set to the minimum size, so that | 45 | * On boot up, the ring buffer is set to the minimum size, so that |
48 | * we do not waste memory on systems that are not using tracing. | 46 | * we do not waste memory on systems that are not using tracing. |
@@ -340,7 +338,7 @@ static DECLARE_WAIT_QUEUE_HEAD(trace_wait); | |||
340 | /* trace_flags holds trace_options default values */ | 338 | /* trace_flags holds trace_options default values */ |
341 | unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK | | 339 | unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK | |
342 | TRACE_ITER_ANNOTATE | TRACE_ITER_CONTEXT_INFO | TRACE_ITER_SLEEP_TIME | | 340 | TRACE_ITER_ANNOTATE | TRACE_ITER_CONTEXT_INFO | TRACE_ITER_SLEEP_TIME | |
343 | TRACE_ITER_GRAPH_TIME | TRACE_ITER_RECORD_CMD; | 341 | TRACE_ITER_GRAPH_TIME | TRACE_ITER_RECORD_CMD | TRACE_ITER_OVERWRITE; |
344 | 342 | ||
345 | static int trace_stop_count; | 343 | static int trace_stop_count; |
346 | static DEFINE_SPINLOCK(tracing_start_lock); | 344 | static DEFINE_SPINLOCK(tracing_start_lock); |
@@ -425,6 +423,7 @@ static const char *trace_options[] = { | |||
425 | "sleep-time", | 423 | "sleep-time", |
426 | "graph-time", | 424 | "graph-time", |
427 | "record-cmd", | 425 | "record-cmd", |
426 | "overwrite", | ||
428 | NULL | 427 | NULL |
429 | }; | 428 | }; |
430 | 429 | ||
@@ -780,6 +779,11 @@ __acquires(kernel_lock) | |||
780 | tracing_reset_online_cpus(tr); | 779 | tracing_reset_online_cpus(tr); |
781 | 780 | ||
782 | current_trace = type; | 781 | current_trace = type; |
782 | |||
783 | /* If we expanded the buffers, make sure the max is expanded too */ | ||
784 | if (ring_buffer_expanded && type->use_max_tr) | ||
785 | ring_buffer_resize(max_tr.buffer, trace_buf_size); | ||
786 | |||
783 | /* the test is responsible for initializing and enabling */ | 787 | /* the test is responsible for initializing and enabling */ |
784 | pr_info("Testing tracer %s: ", type->name); | 788 | pr_info("Testing tracer %s: ", type->name); |
785 | ret = type->selftest(type, tr); | 789 | ret = type->selftest(type, tr); |
@@ -792,6 +796,10 @@ __acquires(kernel_lock) | |||
792 | /* Only reset on passing, to avoid touching corrupted buffers */ | 796 | /* Only reset on passing, to avoid touching corrupted buffers */ |
793 | tracing_reset_online_cpus(tr); | 797 | tracing_reset_online_cpus(tr); |
794 | 798 | ||
799 | /* Shrink the max buffer again */ | ||
800 | if (ring_buffer_expanded && type->use_max_tr) | ||
801 | ring_buffer_resize(max_tr.buffer, 1); | ||
802 | |||
795 | printk(KERN_CONT "PASSED\n"); | 803 | printk(KERN_CONT "PASSED\n"); |
796 | } | 804 | } |
797 | #endif | 805 | #endif |
@@ -1102,7 +1110,6 @@ tracing_generic_entry_update(struct trace_entry *entry, unsigned long flags, | |||
1102 | 1110 | ||
1103 | entry->preempt_count = pc & 0xff; | 1111 | entry->preempt_count = pc & 0xff; |
1104 | entry->pid = (tsk) ? tsk->pid : 0; | 1112 | entry->pid = (tsk) ? tsk->pid : 0; |
1105 | entry->lock_depth = (tsk) ? tsk->lock_depth : 0; | ||
1106 | entry->flags = | 1113 | entry->flags = |
1107 | #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT | 1114 | #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT |
1108 | (irqs_disabled_flags(flags) ? TRACE_FLAG_IRQS_OFF : 0) | | 1115 | (irqs_disabled_flags(flags) ? TRACE_FLAG_IRQS_OFF : 0) | |
@@ -1749,10 +1756,9 @@ static void print_lat_help_header(struct seq_file *m) | |||
1749 | seq_puts(m, "# | / _----=> need-resched \n"); | 1756 | seq_puts(m, "# | / _----=> need-resched \n"); |
1750 | seq_puts(m, "# || / _---=> hardirq/softirq \n"); | 1757 | seq_puts(m, "# || / _---=> hardirq/softirq \n"); |
1751 | seq_puts(m, "# ||| / _--=> preempt-depth \n"); | 1758 | seq_puts(m, "# ||| / _--=> preempt-depth \n"); |
1752 | seq_puts(m, "# |||| /_--=> lock-depth \n"); | 1759 | seq_puts(m, "# |||| / delay \n"); |
1753 | seq_puts(m, "# |||||/ delay \n"); | 1760 | seq_puts(m, "# cmd pid ||||| time | caller \n"); |
1754 | seq_puts(m, "# cmd pid |||||| time | caller \n"); | 1761 | seq_puts(m, "# \\ / ||||| \\ | / \n"); |
1755 | seq_puts(m, "# \\ / |||||| \\ | / \n"); | ||
1756 | } | 1762 | } |
1757 | 1763 | ||
1758 | static void print_func_help_header(struct seq_file *m) | 1764 | static void print_func_help_header(struct seq_file *m) |
@@ -2529,6 +2535,9 @@ static void set_tracer_flags(unsigned int mask, int enabled) | |||
2529 | 2535 | ||
2530 | if (mask == TRACE_ITER_RECORD_CMD) | 2536 | if (mask == TRACE_ITER_RECORD_CMD) |
2531 | trace_event_enable_cmd_record(enabled); | 2537 | trace_event_enable_cmd_record(enabled); |
2538 | |||
2539 | if (mask == TRACE_ITER_OVERWRITE) | ||
2540 | ring_buffer_change_overwrite(global_trace.buffer, enabled); | ||
2532 | } | 2541 | } |
2533 | 2542 | ||
2534 | static ssize_t | 2543 | static ssize_t |
@@ -4555,9 +4564,11 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) | |||
4555 | __init static int tracer_alloc_buffers(void) | 4564 | __init static int tracer_alloc_buffers(void) |
4556 | { | 4565 | { |
4557 | int ring_buf_size; | 4566 | int ring_buf_size; |
4567 | enum ring_buffer_flags rb_flags; | ||
4558 | int i; | 4568 | int i; |
4559 | int ret = -ENOMEM; | 4569 | int ret = -ENOMEM; |
4560 | 4570 | ||
4571 | |||
4561 | if (!alloc_cpumask_var(&tracing_buffer_mask, GFP_KERNEL)) | 4572 | if (!alloc_cpumask_var(&tracing_buffer_mask, GFP_KERNEL)) |
4562 | goto out; | 4573 | goto out; |
4563 | 4574 | ||
@@ -4570,12 +4581,13 @@ __init static int tracer_alloc_buffers(void) | |||
4570 | else | 4581 | else |
4571 | ring_buf_size = 1; | 4582 | ring_buf_size = 1; |
4572 | 4583 | ||
4584 | rb_flags = trace_flags & TRACE_ITER_OVERWRITE ? RB_FL_OVERWRITE : 0; | ||
4585 | |||
4573 | cpumask_copy(tracing_buffer_mask, cpu_possible_mask); | 4586 | cpumask_copy(tracing_buffer_mask, cpu_possible_mask); |
4574 | cpumask_copy(tracing_cpumask, cpu_all_mask); | 4587 | cpumask_copy(tracing_cpumask, cpu_all_mask); |
4575 | 4588 | ||
4576 | /* TODO: make the number of buffers hot pluggable with CPUS */ | 4589 | /* TODO: make the number of buffers hot pluggable with CPUS */ |
4577 | global_trace.buffer = ring_buffer_alloc(ring_buf_size, | 4590 | global_trace.buffer = ring_buffer_alloc(ring_buf_size, rb_flags); |
4578 | TRACE_BUFFER_FLAGS); | ||
4579 | if (!global_trace.buffer) { | 4591 | if (!global_trace.buffer) { |
4580 | printk(KERN_ERR "tracer: failed to allocate ring buffer!\n"); | 4592 | printk(KERN_ERR "tracer: failed to allocate ring buffer!\n"); |
4581 | WARN_ON(1); | 4593 | WARN_ON(1); |
@@ -4585,7 +4597,7 @@ __init static int tracer_alloc_buffers(void) | |||
4585 | 4597 | ||
4586 | 4598 | ||
4587 | #ifdef CONFIG_TRACER_MAX_TRACE | 4599 | #ifdef CONFIG_TRACER_MAX_TRACE |
4588 | max_tr.buffer = ring_buffer_alloc(1, TRACE_BUFFER_FLAGS); | 4600 | max_tr.buffer = ring_buffer_alloc(1, rb_flags); |
4589 | if (!max_tr.buffer) { | 4601 | if (!max_tr.buffer) { |
4590 | printk(KERN_ERR "tracer: failed to allocate max ring buffer!\n"); | 4602 | printk(KERN_ERR "tracer: failed to allocate max ring buffer!\n"); |
4591 | WARN_ON(1); | 4603 | WARN_ON(1); |
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 856e73cc1d3f..5e9dfc6286dd 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -272,8 +272,8 @@ struct tracer { | |||
272 | /* If you handled the flag setting, return 0 */ | 272 | /* If you handled the flag setting, return 0 */ |
273 | int (*set_flag)(u32 old_flags, u32 bit, int set); | 273 | int (*set_flag)(u32 old_flags, u32 bit, int set); |
274 | struct tracer *next; | 274 | struct tracer *next; |
275 | int print_max; | ||
276 | struct tracer_flags *flags; | 275 | struct tracer_flags *flags; |
276 | int print_max; | ||
277 | int use_max_tr; | 277 | int use_max_tr; |
278 | }; | 278 | }; |
279 | 279 | ||
@@ -606,6 +606,7 @@ enum trace_iterator_flags { | |||
606 | TRACE_ITER_SLEEP_TIME = 0x40000, | 606 | TRACE_ITER_SLEEP_TIME = 0x40000, |
607 | TRACE_ITER_GRAPH_TIME = 0x80000, | 607 | TRACE_ITER_GRAPH_TIME = 0x80000, |
608 | TRACE_ITER_RECORD_CMD = 0x100000, | 608 | TRACE_ITER_RECORD_CMD = 0x100000, |
609 | TRACE_ITER_OVERWRITE = 0x200000, | ||
609 | }; | 610 | }; |
610 | 611 | ||
611 | /* | 612 | /* |
diff --git a/kernel/trace/trace_entries.h b/kernel/trace/trace_entries.h index 6cf223764be8..1516cb3ec549 100644 --- a/kernel/trace/trace_entries.h +++ b/kernel/trace/trace_entries.h | |||
@@ -109,12 +109,12 @@ FTRACE_ENTRY(funcgraph_exit, ftrace_graph_ret_entry, | |||
109 | */ | 109 | */ |
110 | #define FTRACE_CTX_FIELDS \ | 110 | #define FTRACE_CTX_FIELDS \ |
111 | __field( unsigned int, prev_pid ) \ | 111 | __field( unsigned int, prev_pid ) \ |
112 | __field( unsigned int, next_pid ) \ | ||
113 | __field( unsigned int, next_cpu ) \ | ||
112 | __field( unsigned char, prev_prio ) \ | 114 | __field( unsigned char, prev_prio ) \ |
113 | __field( unsigned char, prev_state ) \ | 115 | __field( unsigned char, prev_state ) \ |
114 | __field( unsigned int, next_pid ) \ | ||
115 | __field( unsigned char, next_prio ) \ | 116 | __field( unsigned char, next_prio ) \ |
116 | __field( unsigned char, next_state ) \ | 117 | __field( unsigned char, next_state ) |
117 | __field( unsigned int, next_cpu ) | ||
118 | 118 | ||
119 | FTRACE_ENTRY(context_switch, ctx_switch_entry, | 119 | FTRACE_ENTRY(context_switch, ctx_switch_entry, |
120 | 120 | ||
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 5f499e0438a4..e88f74fe1d4c 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
@@ -116,7 +116,6 @@ static int trace_define_common_fields(void) | |||
116 | __common_field(unsigned char, flags); | 116 | __common_field(unsigned char, flags); |
117 | __common_field(unsigned char, preempt_count); | 117 | __common_field(unsigned char, preempt_count); |
118 | __common_field(int, pid); | 118 | __common_field(int, pid); |
119 | __common_field(int, lock_depth); | ||
120 | 119 | ||
121 | return ret; | 120 | return ret; |
122 | } | 121 | } |
@@ -326,6 +325,7 @@ int trace_set_clr_event(const char *system, const char *event, int set) | |||
326 | { | 325 | { |
327 | return __ftrace_set_clr_event(NULL, system, event, set); | 326 | return __ftrace_set_clr_event(NULL, system, event, set); |
328 | } | 327 | } |
328 | EXPORT_SYMBOL_GPL(trace_set_clr_event); | ||
329 | 329 | ||
330 | /* 128 should be much more than enough */ | 330 | /* 128 should be much more than enough */ |
331 | #define EVENT_BUF_SIZE 127 | 331 | #define EVENT_BUF_SIZE 127 |
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c index 02272baa2206..456be9063c2d 100644 --- a/kernel/trace/trace_output.c +++ b/kernel/trace/trace_output.c | |||
@@ -529,24 +529,34 @@ seq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags) | |||
529 | * @entry: The trace entry field from the ring buffer | 529 | * @entry: The trace entry field from the ring buffer |
530 | * | 530 | * |
531 | * Prints the generic fields of irqs off, in hard or softirq, preempt | 531 | * Prints the generic fields of irqs off, in hard or softirq, preempt |
532 | * count and lock depth. | 532 | * count. |
533 | */ | 533 | */ |
534 | int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry) | 534 | int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry) |
535 | { | 535 | { |
536 | int hardirq, softirq; | 536 | char hardsoft_irq; |
537 | char need_resched; | ||
538 | char irqs_off; | ||
539 | int hardirq; | ||
540 | int softirq; | ||
537 | int ret; | 541 | int ret; |
538 | 542 | ||
539 | hardirq = entry->flags & TRACE_FLAG_HARDIRQ; | 543 | hardirq = entry->flags & TRACE_FLAG_HARDIRQ; |
540 | softirq = entry->flags & TRACE_FLAG_SOFTIRQ; | 544 | softirq = entry->flags & TRACE_FLAG_SOFTIRQ; |
541 | 545 | ||
546 | irqs_off = | ||
547 | (entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' : | ||
548 | (entry->flags & TRACE_FLAG_IRQS_NOSUPPORT) ? 'X' : | ||
549 | '.'; | ||
550 | need_resched = | ||
551 | (entry->flags & TRACE_FLAG_NEED_RESCHED) ? 'N' : '.'; | ||
552 | hardsoft_irq = | ||
553 | (hardirq && softirq) ? 'H' : | ||
554 | hardirq ? 'h' : | ||
555 | softirq ? 's' : | ||
556 | '.'; | ||
557 | |||
542 | if (!trace_seq_printf(s, "%c%c%c", | 558 | if (!trace_seq_printf(s, "%c%c%c", |
543 | (entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' : | 559 | irqs_off, need_resched, hardsoft_irq)) |
544 | (entry->flags & TRACE_FLAG_IRQS_NOSUPPORT) ? | ||
545 | 'X' : '.', | ||
546 | (entry->flags & TRACE_FLAG_NEED_RESCHED) ? | ||
547 | 'N' : '.', | ||
548 | (hardirq && softirq) ? 'H' : | ||
549 | hardirq ? 'h' : softirq ? 's' : '.')) | ||
550 | return 0; | 560 | return 0; |
551 | 561 | ||
552 | if (entry->preempt_count) | 562 | if (entry->preempt_count) |
@@ -554,13 +564,7 @@ int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry) | |||
554 | else | 564 | else |
555 | ret = trace_seq_putc(s, '.'); | 565 | ret = trace_seq_putc(s, '.'); |
556 | 566 | ||
557 | if (!ret) | 567 | return ret; |
558 | return 0; | ||
559 | |||
560 | if (entry->lock_depth < 0) | ||
561 | return trace_seq_putc(s, '.'); | ||
562 | |||
563 | return trace_seq_printf(s, "%d", entry->lock_depth); | ||
564 | } | 568 | } |
565 | 569 | ||
566 | static int | 570 | static int |