diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/trace/ring_buffer.c | 56 | ||||
-rw-r--r-- | kernel/trace/trace.c | 41 |
2 files changed, 78 insertions, 19 deletions
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index a2dea5008826..6781e9aab2c0 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
@@ -1027,8 +1027,23 @@ rb_reserve_next_event(struct ring_buffer_per_cpu *cpu_buffer, | |||
1027 | struct ring_buffer_event *event; | 1027 | struct ring_buffer_event *event; |
1028 | u64 ts, delta; | 1028 | u64 ts, delta; |
1029 | int commit = 0; | 1029 | int commit = 0; |
1030 | int nr_loops = 0; | ||
1030 | 1031 | ||
1031 | again: | 1032 | again: |
1033 | /* | ||
1034 | * We allow for interrupts to reenter here and do a trace. | ||
1035 | * If one does, it will cause this original code to loop | ||
1036 | * back here. Even with heavy interrupts happening, this | ||
1037 | * should only happen a few times in a row. If this happens | ||
1038 | * 1000 times in a row, there must be either an interrupt | ||
1039 | * storm or we have something buggy. | ||
1040 | * Bail! | ||
1041 | */ | ||
1042 | if (unlikely(++nr_loops > 1000)) { | ||
1043 | RB_WARN_ON(cpu_buffer, 1); | ||
1044 | return NULL; | ||
1045 | } | ||
1046 | |||
1032 | ts = ring_buffer_time_stamp(cpu_buffer->cpu); | 1047 | ts = ring_buffer_time_stamp(cpu_buffer->cpu); |
1033 | 1048 | ||
1034 | /* | 1049 | /* |
@@ -1526,11 +1541,24 @@ rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer) | |||
1526 | { | 1541 | { |
1527 | struct buffer_page *reader = NULL; | 1542 | struct buffer_page *reader = NULL; |
1528 | unsigned long flags; | 1543 | unsigned long flags; |
1544 | int nr_loops = 0; | ||
1529 | 1545 | ||
1530 | local_irq_save(flags); | 1546 | local_irq_save(flags); |
1531 | __raw_spin_lock(&cpu_buffer->lock); | 1547 | __raw_spin_lock(&cpu_buffer->lock); |
1532 | 1548 | ||
1533 | again: | 1549 | again: |
1550 | /* | ||
1551 | * This should normally only loop twice. But because the | ||
1552 | * start of the reader inserts an empty page, it causes | ||
1553 | * a case where we will loop three times. There should be no | ||
1554 | * reason to loop four times (that I know of). | ||
1555 | */ | ||
1556 | if (unlikely(++nr_loops > 3)) { | ||
1557 | RB_WARN_ON(cpu_buffer, 1); | ||
1558 | reader = NULL; | ||
1559 | goto out; | ||
1560 | } | ||
1561 | |||
1534 | reader = cpu_buffer->reader_page; | 1562 | reader = cpu_buffer->reader_page; |
1535 | 1563 | ||
1536 | /* If there's more to read, return this page */ | 1564 | /* If there's more to read, return this page */ |
@@ -1661,6 +1689,7 @@ ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts) | |||
1661 | struct ring_buffer_per_cpu *cpu_buffer; | 1689 | struct ring_buffer_per_cpu *cpu_buffer; |
1662 | struct ring_buffer_event *event; | 1690 | struct ring_buffer_event *event; |
1663 | struct buffer_page *reader; | 1691 | struct buffer_page *reader; |
1692 | int nr_loops = 0; | ||
1664 | 1693 | ||
1665 | if (!cpu_isset(cpu, buffer->cpumask)) | 1694 | if (!cpu_isset(cpu, buffer->cpumask)) |
1666 | return NULL; | 1695 | return NULL; |
@@ -1668,6 +1697,19 @@ ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts) | |||
1668 | cpu_buffer = buffer->buffers[cpu]; | 1697 | cpu_buffer = buffer->buffers[cpu]; |
1669 | 1698 | ||
1670 | again: | 1699 | again: |
1700 | /* | ||
1701 | * We repeat when a timestamp is encountered. It is possible | ||
1702 | * to get multiple timestamps from an interrupt entering just | ||
1703 | * as one timestamp is about to be written. The max times | ||
1704 | * that this can happen is the number of nested interrupts we | ||
1705 | * can have. Nesting 10 deep of interrupts is clearly | ||
1706 | * an anomaly. | ||
1707 | */ | ||
1708 | if (unlikely(++nr_loops > 10)) { | ||
1709 | RB_WARN_ON(cpu_buffer, 1); | ||
1710 | return NULL; | ||
1711 | } | ||
1712 | |||
1671 | reader = rb_get_reader_page(cpu_buffer); | 1713 | reader = rb_get_reader_page(cpu_buffer); |
1672 | if (!reader) | 1714 | if (!reader) |
1673 | return NULL; | 1715 | return NULL; |
@@ -1718,6 +1760,7 @@ ring_buffer_iter_peek(struct ring_buffer_iter *iter, u64 *ts) | |||
1718 | struct ring_buffer *buffer; | 1760 | struct ring_buffer *buffer; |
1719 | struct ring_buffer_per_cpu *cpu_buffer; | 1761 | struct ring_buffer_per_cpu *cpu_buffer; |
1720 | struct ring_buffer_event *event; | 1762 | struct ring_buffer_event *event; |
1763 | int nr_loops = 0; | ||
1721 | 1764 | ||
1722 | if (ring_buffer_iter_empty(iter)) | 1765 | if (ring_buffer_iter_empty(iter)) |
1723 | return NULL; | 1766 | return NULL; |
@@ -1726,6 +1769,19 @@ ring_buffer_iter_peek(struct ring_buffer_iter *iter, u64 *ts) | |||
1726 | buffer = cpu_buffer->buffer; | 1769 | buffer = cpu_buffer->buffer; |
1727 | 1770 | ||
1728 | again: | 1771 | again: |
1772 | /* | ||
1773 | * We repeat when a timestamp is encountered. It is possible | ||
1774 | * to get multiple timestamps from an interrupt entering just | ||
1775 | * as one timestamp is about to be written. The max times | ||
1776 | * that this can happen is the number of nested interrupts we | ||
1777 | * can have. Nesting 10 deep of interrupts is clearly | ||
1778 | * an anomaly. | ||
1779 | */ | ||
1780 | if (unlikely(++nr_loops > 10)) { | ||
1781 | RB_WARN_ON(cpu_buffer, 1); | ||
1782 | return NULL; | ||
1783 | } | ||
1784 | |||
1729 | if (rb_per_cpu_empty(cpu_buffer)) | 1785 | if (rb_per_cpu_empty(cpu_buffer)) |
1730 | return NULL; | 1786 | return NULL; |
1731 | 1787 | ||
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index ff1e9ed9b587..d55ccfc8d674 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -1231,17 +1231,20 @@ static void s_stop(struct seq_file *m, void *p) | |||
1231 | mutex_unlock(&trace_types_lock); | 1231 | mutex_unlock(&trace_types_lock); |
1232 | } | 1232 | } |
1233 | 1233 | ||
1234 | #define KRETPROBE_MSG "[unknown/kretprobe'd]" | ||
1235 | |||
1236 | #ifdef CONFIG_KRETPROBES | 1234 | #ifdef CONFIG_KRETPROBES |
1237 | static inline int kretprobed(unsigned long addr) | 1235 | static inline const char *kretprobed(const char *name) |
1238 | { | 1236 | { |
1239 | return addr == (unsigned long)kretprobe_trampoline; | 1237 | static const char tramp_name[] = "kretprobe_trampoline"; |
1238 | int size = sizeof(tramp_name); | ||
1239 | |||
1240 | if (strncmp(tramp_name, name, size) == 0) | ||
1241 | return "[unknown/kretprobe'd]"; | ||
1242 | return name; | ||
1240 | } | 1243 | } |
1241 | #else | 1244 | #else |
1242 | static inline int kretprobed(unsigned long addr) | 1245 | static inline const char *kretprobed(const char *name) |
1243 | { | 1246 | { |
1244 | return 0; | 1247 | return name; |
1245 | } | 1248 | } |
1246 | #endif /* CONFIG_KRETPROBES */ | 1249 | #endif /* CONFIG_KRETPROBES */ |
1247 | 1250 | ||
@@ -1250,10 +1253,13 @@ seq_print_sym_short(struct trace_seq *s, const char *fmt, unsigned long address) | |||
1250 | { | 1253 | { |
1251 | #ifdef CONFIG_KALLSYMS | 1254 | #ifdef CONFIG_KALLSYMS |
1252 | char str[KSYM_SYMBOL_LEN]; | 1255 | char str[KSYM_SYMBOL_LEN]; |
1256 | const char *name; | ||
1253 | 1257 | ||
1254 | kallsyms_lookup(address, NULL, NULL, NULL, str); | 1258 | kallsyms_lookup(address, NULL, NULL, NULL, str); |
1255 | 1259 | ||
1256 | return trace_seq_printf(s, fmt, str); | 1260 | name = kretprobed(str); |
1261 | |||
1262 | return trace_seq_printf(s, fmt, name); | ||
1257 | #endif | 1263 | #endif |
1258 | return 1; | 1264 | return 1; |
1259 | } | 1265 | } |
@@ -1264,9 +1270,12 @@ seq_print_sym_offset(struct trace_seq *s, const char *fmt, | |||
1264 | { | 1270 | { |
1265 | #ifdef CONFIG_KALLSYMS | 1271 | #ifdef CONFIG_KALLSYMS |
1266 | char str[KSYM_SYMBOL_LEN]; | 1272 | char str[KSYM_SYMBOL_LEN]; |
1273 | const char *name; | ||
1267 | 1274 | ||
1268 | sprint_symbol(str, address); | 1275 | sprint_symbol(str, address); |
1269 | return trace_seq_printf(s, fmt, str); | 1276 | name = kretprobed(str); |
1277 | |||
1278 | return trace_seq_printf(s, fmt, name); | ||
1270 | #endif | 1279 | #endif |
1271 | return 1; | 1280 | return 1; |
1272 | } | 1281 | } |
@@ -1520,10 +1529,7 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) | |||
1520 | 1529 | ||
1521 | seq_print_ip_sym(s, field->ip, sym_flags); | 1530 | seq_print_ip_sym(s, field->ip, sym_flags); |
1522 | trace_seq_puts(s, " ("); | 1531 | trace_seq_puts(s, " ("); |
1523 | if (kretprobed(field->parent_ip)) | 1532 | seq_print_ip_sym(s, field->parent_ip, sym_flags); |
1524 | trace_seq_puts(s, KRETPROBE_MSG); | ||
1525 | else | ||
1526 | seq_print_ip_sym(s, field->parent_ip, sym_flags); | ||
1527 | trace_seq_puts(s, ")\n"); | 1533 | trace_seq_puts(s, ")\n"); |
1528 | break; | 1534 | break; |
1529 | } | 1535 | } |
@@ -1639,12 +1645,9 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter) | |||
1639 | ret = trace_seq_printf(s, " <-"); | 1645 | ret = trace_seq_printf(s, " <-"); |
1640 | if (!ret) | 1646 | if (!ret) |
1641 | return TRACE_TYPE_PARTIAL_LINE; | 1647 | return TRACE_TYPE_PARTIAL_LINE; |
1642 | if (kretprobed(field->parent_ip)) | 1648 | ret = seq_print_ip_sym(s, |
1643 | ret = trace_seq_puts(s, KRETPROBE_MSG); | 1649 | field->parent_ip, |
1644 | else | 1650 | sym_flags); |
1645 | ret = seq_print_ip_sym(s, | ||
1646 | field->parent_ip, | ||
1647 | sym_flags); | ||
1648 | if (!ret) | 1651 | if (!ret) |
1649 | return TRACE_TYPE_PARTIAL_LINE; | 1652 | return TRACE_TYPE_PARTIAL_LINE; |
1650 | } | 1653 | } |
@@ -1895,7 +1898,7 @@ static enum print_line_t print_bin_fmt(struct trace_iterator *iter) | |||
1895 | return TRACE_TYPE_HANDLED; | 1898 | return TRACE_TYPE_HANDLED; |
1896 | 1899 | ||
1897 | SEQ_PUT_FIELD_RET(s, entry->pid); | 1900 | SEQ_PUT_FIELD_RET(s, entry->pid); |
1898 | SEQ_PUT_FIELD_RET(s, iter->cpu); | 1901 | SEQ_PUT_FIELD_RET(s, entry->cpu); |
1899 | SEQ_PUT_FIELD_RET(s, iter->ts); | 1902 | SEQ_PUT_FIELD_RET(s, iter->ts); |
1900 | 1903 | ||
1901 | switch (entry->type) { | 1904 | switch (entry->type) { |