diff options
author | Jens Axboe <jens.axboe@oracle.com> | 2010-05-21 15:27:26 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2010-05-21 15:27:26 -0400 |
commit | ee9a3607fb03e804ddf624544105f4e34260c380 (patch) | |
tree | ce41b6e0fa10982a306f6c142a92dbf3c9961284 /kernel/trace/trace.c | |
parent | b492e95be0ae672922f4734acf3f5d35c30be948 (diff) | |
parent | d515e86e639890b33a09390d062b0831664f04a2 (diff) |
Merge branch 'master' into for-2.6.35
Conflicts:
fs/ext3/fsync.c
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r-- | kernel/trace/trace.c | 127 |
1 files changed, 91 insertions, 36 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 7b155a0e6f31..8a76339a9e65 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -117,9 +117,12 @@ static cpumask_var_t __read_mostly tracing_buffer_mask; | |||
117 | * | 117 | * |
118 | * It is default off, but you can enable it with either specifying | 118 | * It is default off, but you can enable it with either specifying |
119 | * "ftrace_dump_on_oops" in the kernel command line, or setting | 119 | * "ftrace_dump_on_oops" in the kernel command line, or setting |
120 | * /proc/sys/kernel/ftrace_dump_on_oops to true. | 120 | * /proc/sys/kernel/ftrace_dump_on_oops |
121 | * Set 1 if you want to dump buffers of all CPUs | ||
122 | * Set 2 if you want to dump the buffer of the CPU that triggered oops | ||
121 | */ | 123 | */ |
122 | int ftrace_dump_on_oops; | 124 | |
125 | enum ftrace_dump_mode ftrace_dump_on_oops; | ||
123 | 126 | ||
124 | static int tracing_set_tracer(const char *buf); | 127 | static int tracing_set_tracer(const char *buf); |
125 | 128 | ||
@@ -139,8 +142,17 @@ __setup("ftrace=", set_cmdline_ftrace); | |||
139 | 142 | ||
140 | static int __init set_ftrace_dump_on_oops(char *str) | 143 | static int __init set_ftrace_dump_on_oops(char *str) |
141 | { | 144 | { |
142 | ftrace_dump_on_oops = 1; | 145 | if (*str++ != '=' || !*str) { |
143 | return 1; | 146 | ftrace_dump_on_oops = DUMP_ALL; |
147 | return 1; | ||
148 | } | ||
149 | |||
150 | if (!strcmp("orig_cpu", str)) { | ||
151 | ftrace_dump_on_oops = DUMP_ORIG; | ||
152 | return 1; | ||
153 | } | ||
154 | |||
155 | return 0; | ||
144 | } | 156 | } |
145 | __setup("ftrace_dump_on_oops", set_ftrace_dump_on_oops); | 157 | __setup("ftrace_dump_on_oops", set_ftrace_dump_on_oops); |
146 | 158 | ||
@@ -1545,7 +1557,8 @@ static void trace_iterator_increment(struct trace_iterator *iter) | |||
1545 | } | 1557 | } |
1546 | 1558 | ||
1547 | static struct trace_entry * | 1559 | static struct trace_entry * |
1548 | peek_next_entry(struct trace_iterator *iter, int cpu, u64 *ts) | 1560 | peek_next_entry(struct trace_iterator *iter, int cpu, u64 *ts, |
1561 | unsigned long *lost_events) | ||
1549 | { | 1562 | { |
1550 | struct ring_buffer_event *event; | 1563 | struct ring_buffer_event *event; |
1551 | struct ring_buffer_iter *buf_iter = iter->buffer_iter[cpu]; | 1564 | struct ring_buffer_iter *buf_iter = iter->buffer_iter[cpu]; |
@@ -1556,7 +1569,8 @@ peek_next_entry(struct trace_iterator *iter, int cpu, u64 *ts) | |||
1556 | if (buf_iter) | 1569 | if (buf_iter) |
1557 | event = ring_buffer_iter_peek(buf_iter, ts); | 1570 | event = ring_buffer_iter_peek(buf_iter, ts); |
1558 | else | 1571 | else |
1559 | event = ring_buffer_peek(iter->tr->buffer, cpu, ts); | 1572 | event = ring_buffer_peek(iter->tr->buffer, cpu, ts, |
1573 | lost_events); | ||
1560 | 1574 | ||
1561 | ftrace_enable_cpu(); | 1575 | ftrace_enable_cpu(); |
1562 | 1576 | ||
@@ -1564,10 +1578,12 @@ peek_next_entry(struct trace_iterator *iter, int cpu, u64 *ts) | |||
1564 | } | 1578 | } |
1565 | 1579 | ||
1566 | static struct trace_entry * | 1580 | static struct trace_entry * |
1567 | __find_next_entry(struct trace_iterator *iter, int *ent_cpu, u64 *ent_ts) | 1581 | __find_next_entry(struct trace_iterator *iter, int *ent_cpu, |
1582 | unsigned long *missing_events, u64 *ent_ts) | ||
1568 | { | 1583 | { |
1569 | struct ring_buffer *buffer = iter->tr->buffer; | 1584 | struct ring_buffer *buffer = iter->tr->buffer; |
1570 | struct trace_entry *ent, *next = NULL; | 1585 | struct trace_entry *ent, *next = NULL; |
1586 | unsigned long lost_events = 0, next_lost = 0; | ||
1571 | int cpu_file = iter->cpu_file; | 1587 | int cpu_file = iter->cpu_file; |
1572 | u64 next_ts = 0, ts; | 1588 | u64 next_ts = 0, ts; |
1573 | int next_cpu = -1; | 1589 | int next_cpu = -1; |
@@ -1580,7 +1596,7 @@ __find_next_entry(struct trace_iterator *iter, int *ent_cpu, u64 *ent_ts) | |||
1580 | if (cpu_file > TRACE_PIPE_ALL_CPU) { | 1596 | if (cpu_file > TRACE_PIPE_ALL_CPU) { |
1581 | if (ring_buffer_empty_cpu(buffer, cpu_file)) | 1597 | if (ring_buffer_empty_cpu(buffer, cpu_file)) |
1582 | return NULL; | 1598 | return NULL; |
1583 | ent = peek_next_entry(iter, cpu_file, ent_ts); | 1599 | ent = peek_next_entry(iter, cpu_file, ent_ts, missing_events); |
1584 | if (ent_cpu) | 1600 | if (ent_cpu) |
1585 | *ent_cpu = cpu_file; | 1601 | *ent_cpu = cpu_file; |
1586 | 1602 | ||
@@ -1592,7 +1608,7 @@ __find_next_entry(struct trace_iterator *iter, int *ent_cpu, u64 *ent_ts) | |||
1592 | if (ring_buffer_empty_cpu(buffer, cpu)) | 1608 | if (ring_buffer_empty_cpu(buffer, cpu)) |
1593 | continue; | 1609 | continue; |
1594 | 1610 | ||
1595 | ent = peek_next_entry(iter, cpu, &ts); | 1611 | ent = peek_next_entry(iter, cpu, &ts, &lost_events); |
1596 | 1612 | ||
1597 | /* | 1613 | /* |
1598 | * Pick the entry with the smallest timestamp: | 1614 | * Pick the entry with the smallest timestamp: |
@@ -1601,6 +1617,7 @@ __find_next_entry(struct trace_iterator *iter, int *ent_cpu, u64 *ent_ts) | |||
1601 | next = ent; | 1617 | next = ent; |
1602 | next_cpu = cpu; | 1618 | next_cpu = cpu; |
1603 | next_ts = ts; | 1619 | next_ts = ts; |
1620 | next_lost = lost_events; | ||
1604 | } | 1621 | } |
1605 | } | 1622 | } |
1606 | 1623 | ||
@@ -1610,6 +1627,9 @@ __find_next_entry(struct trace_iterator *iter, int *ent_cpu, u64 *ent_ts) | |||
1610 | if (ent_ts) | 1627 | if (ent_ts) |
1611 | *ent_ts = next_ts; | 1628 | *ent_ts = next_ts; |
1612 | 1629 | ||
1630 | if (missing_events) | ||
1631 | *missing_events = next_lost; | ||
1632 | |||
1613 | return next; | 1633 | return next; |
1614 | } | 1634 | } |
1615 | 1635 | ||
@@ -1617,13 +1637,14 @@ __find_next_entry(struct trace_iterator *iter, int *ent_cpu, u64 *ent_ts) | |||
1617 | struct trace_entry *trace_find_next_entry(struct trace_iterator *iter, | 1637 | struct trace_entry *trace_find_next_entry(struct trace_iterator *iter, |
1618 | int *ent_cpu, u64 *ent_ts) | 1638 | int *ent_cpu, u64 *ent_ts) |
1619 | { | 1639 | { |
1620 | return __find_next_entry(iter, ent_cpu, ent_ts); | 1640 | return __find_next_entry(iter, ent_cpu, NULL, ent_ts); |
1621 | } | 1641 | } |
1622 | 1642 | ||
1623 | /* Find the next real entry, and increment the iterator to the next entry */ | 1643 | /* Find the next real entry, and increment the iterator to the next entry */ |
1624 | static void *find_next_entry_inc(struct trace_iterator *iter) | 1644 | static void *find_next_entry_inc(struct trace_iterator *iter) |
1625 | { | 1645 | { |
1626 | iter->ent = __find_next_entry(iter, &iter->cpu, &iter->ts); | 1646 | iter->ent = __find_next_entry(iter, &iter->cpu, |
1647 | &iter->lost_events, &iter->ts); | ||
1627 | 1648 | ||
1628 | if (iter->ent) | 1649 | if (iter->ent) |
1629 | trace_iterator_increment(iter); | 1650 | trace_iterator_increment(iter); |
@@ -1635,7 +1656,8 @@ static void trace_consume(struct trace_iterator *iter) | |||
1635 | { | 1656 | { |
1636 | /* Don't allow ftrace to trace into the ring buffers */ | 1657 | /* Don't allow ftrace to trace into the ring buffers */ |
1637 | ftrace_disable_cpu(); | 1658 | ftrace_disable_cpu(); |
1638 | ring_buffer_consume(iter->tr->buffer, iter->cpu, &iter->ts); | 1659 | ring_buffer_consume(iter->tr->buffer, iter->cpu, &iter->ts, |
1660 | &iter->lost_events); | ||
1639 | ftrace_enable_cpu(); | 1661 | ftrace_enable_cpu(); |
1640 | } | 1662 | } |
1641 | 1663 | ||
@@ -1786,7 +1808,7 @@ static void print_func_help_header(struct seq_file *m) | |||
1786 | } | 1808 | } |
1787 | 1809 | ||
1788 | 1810 | ||
1789 | static void | 1811 | void |
1790 | print_trace_header(struct seq_file *m, struct trace_iterator *iter) | 1812 | print_trace_header(struct seq_file *m, struct trace_iterator *iter) |
1791 | { | 1813 | { |
1792 | unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK); | 1814 | unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK); |
@@ -1995,7 +2017,7 @@ static enum print_line_t print_bin_fmt(struct trace_iterator *iter) | |||
1995 | return event ? event->binary(iter, 0) : TRACE_TYPE_HANDLED; | 2017 | return event ? event->binary(iter, 0) : TRACE_TYPE_HANDLED; |
1996 | } | 2018 | } |
1997 | 2019 | ||
1998 | static int trace_empty(struct trace_iterator *iter) | 2020 | int trace_empty(struct trace_iterator *iter) |
1999 | { | 2021 | { |
2000 | int cpu; | 2022 | int cpu; |
2001 | 2023 | ||
@@ -2030,6 +2052,10 @@ static enum print_line_t print_trace_line(struct trace_iterator *iter) | |||
2030 | { | 2052 | { |
2031 | enum print_line_t ret; | 2053 | enum print_line_t ret; |
2032 | 2054 | ||
2055 | if (iter->lost_events) | ||
2056 | trace_seq_printf(&iter->seq, "CPU:%d [LOST %lu EVENTS]\n", | ||
2057 | iter->cpu, iter->lost_events); | ||
2058 | |||
2033 | if (iter->trace && iter->trace->print_line) { | 2059 | if (iter->trace && iter->trace->print_line) { |
2034 | ret = iter->trace->print_line(iter); | 2060 | ret = iter->trace->print_line(iter); |
2035 | if (ret != TRACE_TYPE_UNHANDLED) | 2061 | if (ret != TRACE_TYPE_UNHANDLED) |
@@ -2058,6 +2084,23 @@ static enum print_line_t print_trace_line(struct trace_iterator *iter) | |||
2058 | return print_trace_fmt(iter); | 2084 | return print_trace_fmt(iter); |
2059 | } | 2085 | } |
2060 | 2086 | ||
2087 | void trace_default_header(struct seq_file *m) | ||
2088 | { | ||
2089 | struct trace_iterator *iter = m->private; | ||
2090 | |||
2091 | if (iter->iter_flags & TRACE_FILE_LAT_FMT) { | ||
2092 | /* print nothing if the buffers are empty */ | ||
2093 | if (trace_empty(iter)) | ||
2094 | return; | ||
2095 | print_trace_header(m, iter); | ||
2096 | if (!(trace_flags & TRACE_ITER_VERBOSE)) | ||
2097 | print_lat_help_header(m); | ||
2098 | } else { | ||
2099 | if (!(trace_flags & TRACE_ITER_VERBOSE)) | ||
2100 | print_func_help_header(m); | ||
2101 | } | ||
2102 | } | ||
2103 | |||
2061 | static int s_show(struct seq_file *m, void *v) | 2104 | static int s_show(struct seq_file *m, void *v) |
2062 | { | 2105 | { |
2063 | struct trace_iterator *iter = v; | 2106 | struct trace_iterator *iter = v; |
@@ -2070,17 +2113,9 @@ static int s_show(struct seq_file *m, void *v) | |||
2070 | } | 2113 | } |
2071 | if (iter->trace && iter->trace->print_header) | 2114 | if (iter->trace && iter->trace->print_header) |
2072 | iter->trace->print_header(m); | 2115 | iter->trace->print_header(m); |
2073 | else if (iter->iter_flags & TRACE_FILE_LAT_FMT) { | 2116 | else |
2074 | /* print nothing if the buffers are empty */ | 2117 | trace_default_header(m); |
2075 | if (trace_empty(iter)) | 2118 | |
2076 | return 0; | ||
2077 | print_trace_header(m, iter); | ||
2078 | if (!(trace_flags & TRACE_ITER_VERBOSE)) | ||
2079 | print_lat_help_header(m); | ||
2080 | } else { | ||
2081 | if (!(trace_flags & TRACE_ITER_VERBOSE)) | ||
2082 | print_func_help_header(m); | ||
2083 | } | ||
2084 | } else if (iter->leftover) { | 2119 | } else if (iter->leftover) { |
2085 | /* | 2120 | /* |
2086 | * If we filled the seq_file buffer earlier, we | 2121 | * If we filled the seq_file buffer earlier, we |
@@ -2166,15 +2201,20 @@ __tracing_open(struct inode *inode, struct file *file) | |||
2166 | 2201 | ||
2167 | if (iter->cpu_file == TRACE_PIPE_ALL_CPU) { | 2202 | if (iter->cpu_file == TRACE_PIPE_ALL_CPU) { |
2168 | for_each_tracing_cpu(cpu) { | 2203 | for_each_tracing_cpu(cpu) { |
2169 | |||
2170 | iter->buffer_iter[cpu] = | 2204 | iter->buffer_iter[cpu] = |
2171 | ring_buffer_read_start(iter->tr->buffer, cpu); | 2205 | ring_buffer_read_prepare(iter->tr->buffer, cpu); |
2206 | } | ||
2207 | ring_buffer_read_prepare_sync(); | ||
2208 | for_each_tracing_cpu(cpu) { | ||
2209 | ring_buffer_read_start(iter->buffer_iter[cpu]); | ||
2172 | tracing_iter_reset(iter, cpu); | 2210 | tracing_iter_reset(iter, cpu); |
2173 | } | 2211 | } |
2174 | } else { | 2212 | } else { |
2175 | cpu = iter->cpu_file; | 2213 | cpu = iter->cpu_file; |
2176 | iter->buffer_iter[cpu] = | 2214 | iter->buffer_iter[cpu] = |
2177 | ring_buffer_read_start(iter->tr->buffer, cpu); | 2215 | ring_buffer_read_prepare(iter->tr->buffer, cpu); |
2216 | ring_buffer_read_prepare_sync(); | ||
2217 | ring_buffer_read_start(iter->buffer_iter[cpu]); | ||
2178 | tracing_iter_reset(iter, cpu); | 2218 | tracing_iter_reset(iter, cpu); |
2179 | } | 2219 | } |
2180 | 2220 | ||
@@ -4336,7 +4376,7 @@ static int trace_panic_handler(struct notifier_block *this, | |||
4336 | unsigned long event, void *unused) | 4376 | unsigned long event, void *unused) |
4337 | { | 4377 | { |
4338 | if (ftrace_dump_on_oops) | 4378 | if (ftrace_dump_on_oops) |
4339 | ftrace_dump(); | 4379 | ftrace_dump(ftrace_dump_on_oops); |
4340 | return NOTIFY_OK; | 4380 | return NOTIFY_OK; |
4341 | } | 4381 | } |
4342 | 4382 | ||
@@ -4353,7 +4393,7 @@ static int trace_die_handler(struct notifier_block *self, | |||
4353 | switch (val) { | 4393 | switch (val) { |
4354 | case DIE_OOPS: | 4394 | case DIE_OOPS: |
4355 | if (ftrace_dump_on_oops) | 4395 | if (ftrace_dump_on_oops) |
4356 | ftrace_dump(); | 4396 | ftrace_dump(ftrace_dump_on_oops); |
4357 | break; | 4397 | break; |
4358 | default: | 4398 | default: |
4359 | break; | 4399 | break; |
@@ -4394,7 +4434,8 @@ trace_printk_seq(struct trace_seq *s) | |||
4394 | trace_seq_init(s); | 4434 | trace_seq_init(s); |
4395 | } | 4435 | } |
4396 | 4436 | ||
4397 | static void __ftrace_dump(bool disable_tracing) | 4437 | static void |
4438 | __ftrace_dump(bool disable_tracing, enum ftrace_dump_mode oops_dump_mode) | ||
4398 | { | 4439 | { |
4399 | static arch_spinlock_t ftrace_dump_lock = | 4440 | static arch_spinlock_t ftrace_dump_lock = |
4400 | (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; | 4441 | (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; |
@@ -4427,12 +4468,25 @@ static void __ftrace_dump(bool disable_tracing) | |||
4427 | /* don't look at user memory in panic mode */ | 4468 | /* don't look at user memory in panic mode */ |
4428 | trace_flags &= ~TRACE_ITER_SYM_USEROBJ; | 4469 | trace_flags &= ~TRACE_ITER_SYM_USEROBJ; |
4429 | 4470 | ||
4430 | printk(KERN_TRACE "Dumping ftrace buffer:\n"); | ||
4431 | |||
4432 | /* Simulate the iterator */ | 4471 | /* Simulate the iterator */ |
4433 | iter.tr = &global_trace; | 4472 | iter.tr = &global_trace; |
4434 | iter.trace = current_trace; | 4473 | iter.trace = current_trace; |
4435 | iter.cpu_file = TRACE_PIPE_ALL_CPU; | 4474 | |
4475 | switch (oops_dump_mode) { | ||
4476 | case DUMP_ALL: | ||
4477 | iter.cpu_file = TRACE_PIPE_ALL_CPU; | ||
4478 | break; | ||
4479 | case DUMP_ORIG: | ||
4480 | iter.cpu_file = raw_smp_processor_id(); | ||
4481 | break; | ||
4482 | case DUMP_NONE: | ||
4483 | goto out_enable; | ||
4484 | default: | ||
4485 | printk(KERN_TRACE "Bad dumping mode, switching to all CPUs dump\n"); | ||
4486 | iter.cpu_file = TRACE_PIPE_ALL_CPU; | ||
4487 | } | ||
4488 | |||
4489 | printk(KERN_TRACE "Dumping ftrace buffer:\n"); | ||
4436 | 4490 | ||
4437 | /* | 4491 | /* |
4438 | * We need to stop all tracing on all CPUS to read the | 4492 | * We need to stop all tracing on all CPUS to read the |
@@ -4471,6 +4525,7 @@ static void __ftrace_dump(bool disable_tracing) | |||
4471 | else | 4525 | else |
4472 | printk(KERN_TRACE "---------------------------------\n"); | 4526 | printk(KERN_TRACE "---------------------------------\n"); |
4473 | 4527 | ||
4528 | out_enable: | ||
4474 | /* Re-enable tracing if requested */ | 4529 | /* Re-enable tracing if requested */ |
4475 | if (!disable_tracing) { | 4530 | if (!disable_tracing) { |
4476 | trace_flags |= old_userobj; | 4531 | trace_flags |= old_userobj; |
@@ -4487,9 +4542,9 @@ static void __ftrace_dump(bool disable_tracing) | |||
4487 | } | 4542 | } |
4488 | 4543 | ||
4489 | /* By default: disable tracing after the dump */ | 4544 | /* By default: disable tracing after the dump */ |
4490 | void ftrace_dump(void) | 4545 | void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) |
4491 | { | 4546 | { |
4492 | __ftrace_dump(true); | 4547 | __ftrace_dump(true, oops_dump_mode); |
4493 | } | 4548 | } |
4494 | 4549 | ||
4495 | __init static int tracer_alloc_buffers(void) | 4550 | __init static int tracer_alloc_buffers(void) |