diff options
Diffstat (limited to 'kernel/trace/trace.c')
| -rw-r--r-- | kernel/trace/trace.c | 83 |
1 files changed, 54 insertions, 29 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index d345d649d073..d86e3252f300 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | 34 | ||
| 35 | #include <linux/stacktrace.h> | 35 | #include <linux/stacktrace.h> |
| 36 | #include <linux/ring_buffer.h> | 36 | #include <linux/ring_buffer.h> |
| 37 | #include <linux/irqflags.h> | ||
| 37 | 38 | ||
| 38 | #include "trace.h" | 39 | #include "trace.h" |
| 39 | 40 | ||
| @@ -655,7 +656,11 @@ tracing_generic_entry_update(struct trace_entry *entry, unsigned long flags, | |||
| 655 | entry->preempt_count = pc & 0xff; | 656 | entry->preempt_count = pc & 0xff; |
| 656 | entry->pid = (tsk) ? tsk->pid : 0; | 657 | entry->pid = (tsk) ? tsk->pid : 0; |
| 657 | entry->flags = | 658 | entry->flags = |
| 659 | #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT | ||
| 658 | (irqs_disabled_flags(flags) ? TRACE_FLAG_IRQS_OFF : 0) | | 660 | (irqs_disabled_flags(flags) ? TRACE_FLAG_IRQS_OFF : 0) | |
| 661 | #else | ||
| 662 | TRACE_FLAG_IRQS_NOSUPPORT | | ||
| 663 | #endif | ||
| 659 | ((pc & HARDIRQ_MASK) ? TRACE_FLAG_HARDIRQ : 0) | | 664 | ((pc & HARDIRQ_MASK) ? TRACE_FLAG_HARDIRQ : 0) | |
| 660 | ((pc & SOFTIRQ_MASK) ? TRACE_FLAG_SOFTIRQ : 0) | | 665 | ((pc & SOFTIRQ_MASK) ? TRACE_FLAG_SOFTIRQ : 0) | |
| 661 | (need_resched() ? TRACE_FLAG_NEED_RESCHED : 0); | 666 | (need_resched() ? TRACE_FLAG_NEED_RESCHED : 0); |
| @@ -700,6 +705,7 @@ static void ftrace_trace_stack(struct trace_array *tr, | |||
| 700 | unsigned long flags, | 705 | unsigned long flags, |
| 701 | int skip, int pc) | 706 | int skip, int pc) |
| 702 | { | 707 | { |
| 708 | #ifdef CONFIG_STACKTRACE | ||
| 703 | struct ring_buffer_event *event; | 709 | struct ring_buffer_event *event; |
| 704 | struct stack_entry *entry; | 710 | struct stack_entry *entry; |
| 705 | struct stack_trace trace; | 711 | struct stack_trace trace; |
| @@ -725,6 +731,7 @@ static void ftrace_trace_stack(struct trace_array *tr, | |||
| 725 | 731 | ||
| 726 | save_stack_trace(&trace); | 732 | save_stack_trace(&trace); |
| 727 | ring_buffer_unlock_commit(tr->buffer, event, irq_flags); | 733 | ring_buffer_unlock_commit(tr->buffer, event, irq_flags); |
| 734 | #endif | ||
| 728 | } | 735 | } |
| 729 | 736 | ||
| 730 | void __trace_stack(struct trace_array *tr, | 737 | void __trace_stack(struct trace_array *tr, |
| @@ -851,7 +858,7 @@ ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3) | |||
| 851 | preempt_enable_notrace(); | 858 | preempt_enable_notrace(); |
| 852 | } | 859 | } |
| 853 | 860 | ||
| 854 | #ifdef CONFIG_FTRACE | 861 | #ifdef CONFIG_FUNCTION_TRACER |
| 855 | static void | 862 | static void |
| 856 | function_trace_call(unsigned long ip, unsigned long parent_ip) | 863 | function_trace_call(unsigned long ip, unsigned long parent_ip) |
| 857 | { | 864 | { |
| @@ -865,9 +872,6 @@ function_trace_call(unsigned long ip, unsigned long parent_ip) | |||
| 865 | if (unlikely(!ftrace_function_enabled)) | 872 | if (unlikely(!ftrace_function_enabled)) |
| 866 | return; | 873 | return; |
| 867 | 874 | ||
| 868 | if (skip_trace(ip)) | ||
| 869 | return; | ||
| 870 | |||
| 871 | pc = preempt_count(); | 875 | pc = preempt_count(); |
| 872 | resched = need_resched(); | 876 | resched = need_resched(); |
| 873 | preempt_disable_notrace(); | 877 | preempt_disable_notrace(); |
| @@ -1084,17 +1088,20 @@ static void s_stop(struct seq_file *m, void *p) | |||
| 1084 | mutex_unlock(&trace_types_lock); | 1088 | mutex_unlock(&trace_types_lock); |
| 1085 | } | 1089 | } |
| 1086 | 1090 | ||
| 1087 | #define KRETPROBE_MSG "[unknown/kretprobe'd]" | ||
| 1088 | |||
| 1089 | #ifdef CONFIG_KRETPROBES | 1091 | #ifdef CONFIG_KRETPROBES |
| 1090 | static inline int kretprobed(unsigned long addr) | 1092 | static inline const char *kretprobed(const char *name) |
| 1091 | { | 1093 | { |
| 1092 | return addr == (unsigned long)kretprobe_trampoline; | 1094 | static const char tramp_name[] = "kretprobe_trampoline"; |
| 1095 | int size = sizeof(tramp_name); | ||
| 1096 | |||
| 1097 | if (strncmp(tramp_name, name, size) == 0) | ||
| 1098 | return "[unknown/kretprobe'd]"; | ||
| 1099 | return name; | ||
| 1093 | } | 1100 | } |
| 1094 | #else | 1101 | #else |
| 1095 | static inline int kretprobed(unsigned long addr) | 1102 | static inline const char *kretprobed(const char *name) |
| 1096 | { | 1103 | { |
| 1097 | return 0; | 1104 | return name; |
| 1098 | } | 1105 | } |
| 1099 | #endif /* CONFIG_KRETPROBES */ | 1106 | #endif /* CONFIG_KRETPROBES */ |
| 1100 | 1107 | ||
| @@ -1103,10 +1110,13 @@ seq_print_sym_short(struct trace_seq *s, const char *fmt, unsigned long address) | |||
| 1103 | { | 1110 | { |
| 1104 | #ifdef CONFIG_KALLSYMS | 1111 | #ifdef CONFIG_KALLSYMS |
| 1105 | char str[KSYM_SYMBOL_LEN]; | 1112 | char str[KSYM_SYMBOL_LEN]; |
| 1113 | const char *name; | ||
| 1106 | 1114 | ||
| 1107 | kallsyms_lookup(address, NULL, NULL, NULL, str); | 1115 | kallsyms_lookup(address, NULL, NULL, NULL, str); |
| 1108 | 1116 | ||
| 1109 | return trace_seq_printf(s, fmt, str); | 1117 | name = kretprobed(str); |
| 1118 | |||
| 1119 | return trace_seq_printf(s, fmt, name); | ||
| 1110 | #endif | 1120 | #endif |
| 1111 | return 1; | 1121 | return 1; |
| 1112 | } | 1122 | } |
| @@ -1117,9 +1127,12 @@ seq_print_sym_offset(struct trace_seq *s, const char *fmt, | |||
| 1117 | { | 1127 | { |
| 1118 | #ifdef CONFIG_KALLSYMS | 1128 | #ifdef CONFIG_KALLSYMS |
| 1119 | char str[KSYM_SYMBOL_LEN]; | 1129 | char str[KSYM_SYMBOL_LEN]; |
| 1130 | const char *name; | ||
| 1120 | 1131 | ||
| 1121 | sprint_symbol(str, address); | 1132 | sprint_symbol(str, address); |
| 1122 | return trace_seq_printf(s, fmt, str); | 1133 | name = kretprobed(str); |
| 1134 | |||
| 1135 | return trace_seq_printf(s, fmt, name); | ||
| 1123 | #endif | 1136 | #endif |
| 1124 | return 1; | 1137 | return 1; |
| 1125 | } | 1138 | } |
| @@ -1246,7 +1259,8 @@ lat_print_generic(struct trace_seq *s, struct trace_entry *entry, int cpu) | |||
| 1246 | trace_seq_printf(s, "%8.8s-%-5d ", comm, entry->pid); | 1259 | trace_seq_printf(s, "%8.8s-%-5d ", comm, entry->pid); |
| 1247 | trace_seq_printf(s, "%3d", cpu); | 1260 | trace_seq_printf(s, "%3d", cpu); |
| 1248 | trace_seq_printf(s, "%c%c", | 1261 | trace_seq_printf(s, "%c%c", |
| 1249 | (entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' : '.', | 1262 | (entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' : |
| 1263 | (entry->flags & TRACE_FLAG_IRQS_NOSUPPORT) ? 'X' : '.', | ||
| 1250 | ((entry->flags & TRACE_FLAG_NEED_RESCHED) ? 'N' : '.')); | 1264 | ((entry->flags & TRACE_FLAG_NEED_RESCHED) ? 'N' : '.')); |
| 1251 | 1265 | ||
| 1252 | hardirq = entry->flags & TRACE_FLAG_HARDIRQ; | 1266 | hardirq = entry->flags & TRACE_FLAG_HARDIRQ; |
| @@ -1372,10 +1386,7 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) | |||
| 1372 | 1386 | ||
| 1373 | seq_print_ip_sym(s, field->ip, sym_flags); | 1387 | seq_print_ip_sym(s, field->ip, sym_flags); |
| 1374 | trace_seq_puts(s, " ("); | 1388 | trace_seq_puts(s, " ("); |
| 1375 | if (kretprobed(field->parent_ip)) | 1389 | seq_print_ip_sym(s, field->parent_ip, sym_flags); |
| 1376 | trace_seq_puts(s, KRETPROBE_MSG); | ||
| 1377 | else | ||
| 1378 | seq_print_ip_sym(s, field->parent_ip, sym_flags); | ||
| 1379 | trace_seq_puts(s, ")\n"); | 1390 | trace_seq_puts(s, ")\n"); |
| 1380 | break; | 1391 | break; |
| 1381 | } | 1392 | } |
| @@ -1491,12 +1502,9 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter) | |||
| 1491 | ret = trace_seq_printf(s, " <-"); | 1502 | ret = trace_seq_printf(s, " <-"); |
| 1492 | if (!ret) | 1503 | if (!ret) |
| 1493 | return TRACE_TYPE_PARTIAL_LINE; | 1504 | return TRACE_TYPE_PARTIAL_LINE; |
| 1494 | if (kretprobed(field->parent_ip)) | 1505 | ret = seq_print_ip_sym(s, |
| 1495 | ret = trace_seq_puts(s, KRETPROBE_MSG); | 1506 | field->parent_ip, |
| 1496 | else | 1507 | sym_flags); |
| 1497 | ret = seq_print_ip_sym(s, | ||
| 1498 | field->parent_ip, | ||
| 1499 | sym_flags); | ||
| 1500 | if (!ret) | 1508 | if (!ret) |
| 1501 | return TRACE_TYPE_PARTIAL_LINE; | 1509 | return TRACE_TYPE_PARTIAL_LINE; |
| 1502 | } | 1510 | } |
| @@ -1747,7 +1755,7 @@ static enum print_line_t print_bin_fmt(struct trace_iterator *iter) | |||
| 1747 | return TRACE_TYPE_HANDLED; | 1755 | return TRACE_TYPE_HANDLED; |
| 1748 | 1756 | ||
| 1749 | SEQ_PUT_FIELD_RET(s, entry->pid); | 1757 | SEQ_PUT_FIELD_RET(s, entry->pid); |
| 1750 | SEQ_PUT_FIELD_RET(s, iter->cpu); | 1758 | SEQ_PUT_FIELD_RET(s, entry->cpu); |
| 1751 | SEQ_PUT_FIELD_RET(s, iter->ts); | 1759 | SEQ_PUT_FIELD_RET(s, iter->ts); |
| 1752 | 1760 | ||
| 1753 | switch (entry->type) { | 1761 | switch (entry->type) { |
| @@ -1928,6 +1936,7 @@ __tracing_open(struct inode *inode, struct file *file, int *ret) | |||
| 1928 | ring_buffer_read_finish(iter->buffer_iter[cpu]); | 1936 | ring_buffer_read_finish(iter->buffer_iter[cpu]); |
| 1929 | } | 1937 | } |
| 1930 | mutex_unlock(&trace_types_lock); | 1938 | mutex_unlock(&trace_types_lock); |
| 1939 | kfree(iter); | ||
| 1931 | 1940 | ||
| 1932 | return ERR_PTR(-ENOMEM); | 1941 | return ERR_PTR(-ENOMEM); |
| 1933 | } | 1942 | } |
| @@ -2379,9 +2388,10 @@ tracing_set_trace_write(struct file *filp, const char __user *ubuf, | |||
| 2379 | int i; | 2388 | int i; |
| 2380 | size_t ret; | 2389 | size_t ret; |
| 2381 | 2390 | ||
| 2391 | ret = cnt; | ||
| 2392 | |||
| 2382 | if (cnt > max_tracer_type_len) | 2393 | if (cnt > max_tracer_type_len) |
| 2383 | cnt = max_tracer_type_len; | 2394 | cnt = max_tracer_type_len; |
| 2384 | ret = cnt; | ||
| 2385 | 2395 | ||
| 2386 | if (copy_from_user(&buf, ubuf, cnt)) | 2396 | if (copy_from_user(&buf, ubuf, cnt)) |
| 2387 | return -EFAULT; | 2397 | return -EFAULT; |
| @@ -2414,8 +2424,8 @@ tracing_set_trace_write(struct file *filp, const char __user *ubuf, | |||
| 2414 | out: | 2424 | out: |
| 2415 | mutex_unlock(&trace_types_lock); | 2425 | mutex_unlock(&trace_types_lock); |
| 2416 | 2426 | ||
| 2417 | if (ret == cnt) | 2427 | if (ret > 0) |
| 2418 | filp->f_pos += cnt; | 2428 | filp->f_pos += ret; |
| 2419 | 2429 | ||
| 2420 | return ret; | 2430 | return ret; |
| 2421 | } | 2431 | } |
| @@ -2667,7 +2677,7 @@ tracing_entries_write(struct file *filp, const char __user *ubuf, | |||
| 2667 | { | 2677 | { |
| 2668 | unsigned long val; | 2678 | unsigned long val; |
| 2669 | char buf[64]; | 2679 | char buf[64]; |
| 2670 | int ret; | 2680 | int ret, cpu; |
| 2671 | struct trace_array *tr = filp->private_data; | 2681 | struct trace_array *tr = filp->private_data; |
| 2672 | 2682 | ||
| 2673 | if (cnt >= sizeof(buf)) | 2683 | if (cnt >= sizeof(buf)) |
| @@ -2695,6 +2705,14 @@ tracing_entries_write(struct file *filp, const char __user *ubuf, | |||
| 2695 | goto out; | 2705 | goto out; |
| 2696 | } | 2706 | } |
| 2697 | 2707 | ||
| 2708 | /* disable all cpu buffers */ | ||
| 2709 | for_each_tracing_cpu(cpu) { | ||
| 2710 | if (global_trace.data[cpu]) | ||
| 2711 | atomic_inc(&global_trace.data[cpu]->disabled); | ||
| 2712 | if (max_tr.data[cpu]) | ||
| 2713 | atomic_inc(&max_tr.data[cpu]->disabled); | ||
| 2714 | } | ||
| 2715 | |||
| 2698 | if (val != global_trace.entries) { | 2716 | if (val != global_trace.entries) { |
| 2699 | ret = ring_buffer_resize(global_trace.buffer, val); | 2717 | ret = ring_buffer_resize(global_trace.buffer, val); |
| 2700 | if (ret < 0) { | 2718 | if (ret < 0) { |
| @@ -2726,6 +2744,13 @@ tracing_entries_write(struct file *filp, const char __user *ubuf, | |||
| 2726 | if (tracing_disabled) | 2744 | if (tracing_disabled) |
| 2727 | cnt = -ENOMEM; | 2745 | cnt = -ENOMEM; |
| 2728 | out: | 2746 | out: |
| 2747 | for_each_tracing_cpu(cpu) { | ||
| 2748 | if (global_trace.data[cpu]) | ||
| 2749 | atomic_dec(&global_trace.data[cpu]->disabled); | ||
| 2750 | if (max_tr.data[cpu]) | ||
| 2751 | atomic_dec(&max_tr.data[cpu]->disabled); | ||
| 2752 | } | ||
| 2753 | |||
| 2729 | max_tr.entries = global_trace.entries; | 2754 | max_tr.entries = global_trace.entries; |
| 2730 | mutex_unlock(&trace_types_lock); | 2755 | mutex_unlock(&trace_types_lock); |
| 2731 | 2756 | ||
| @@ -3097,7 +3122,7 @@ void ftrace_dump(void) | |||
| 3097 | dump_ran = 1; | 3122 | dump_ran = 1; |
| 3098 | 3123 | ||
| 3099 | /* No turning back! */ | 3124 | /* No turning back! */ |
| 3100 | ftrace_kill_atomic(); | 3125 | ftrace_kill(); |
| 3101 | 3126 | ||
| 3102 | for_each_tracing_cpu(cpu) { | 3127 | for_each_tracing_cpu(cpu) { |
| 3103 | atomic_inc(&global_trace.data[cpu]->disabled); | 3128 | atomic_inc(&global_trace.data[cpu]->disabled); |
