aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r--kernel/trace/trace.c82
1 files changed, 53 insertions, 29 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index d345d649d073..697eda36b86a 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
730void __trace_stack(struct trace_array *tr, 737void __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
855static void 862static void
856function_trace_call(unsigned long ip, unsigned long parent_ip) 863function_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
1090static inline int kretprobed(unsigned long addr) 1092static 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
1095static inline int kretprobed(unsigned long addr) 1102static 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) {
@@ -2379,9 +2387,10 @@ tracing_set_trace_write(struct file *filp, const char __user *ubuf,
2379 int i; 2387 int i;
2380 size_t ret; 2388 size_t ret;
2381 2389
2390 ret = cnt;
2391
2382 if (cnt > max_tracer_type_len) 2392 if (cnt > max_tracer_type_len)
2383 cnt = max_tracer_type_len; 2393 cnt = max_tracer_type_len;
2384 ret = cnt;
2385 2394
2386 if (copy_from_user(&buf, ubuf, cnt)) 2395 if (copy_from_user(&buf, ubuf, cnt))
2387 return -EFAULT; 2396 return -EFAULT;
@@ -2414,8 +2423,8 @@ tracing_set_trace_write(struct file *filp, const char __user *ubuf,
2414 out: 2423 out:
2415 mutex_unlock(&trace_types_lock); 2424 mutex_unlock(&trace_types_lock);
2416 2425
2417 if (ret == cnt) 2426 if (ret > 0)
2418 filp->f_pos += cnt; 2427 filp->f_pos += ret;
2419 2428
2420 return ret; 2429 return ret;
2421} 2430}
@@ -2667,7 +2676,7 @@ tracing_entries_write(struct file *filp, const char __user *ubuf,
2667{ 2676{
2668 unsigned long val; 2677 unsigned long val;
2669 char buf[64]; 2678 char buf[64];
2670 int ret; 2679 int ret, cpu;
2671 struct trace_array *tr = filp->private_data; 2680 struct trace_array *tr = filp->private_data;
2672 2681
2673 if (cnt >= sizeof(buf)) 2682 if (cnt >= sizeof(buf))
@@ -2695,6 +2704,14 @@ tracing_entries_write(struct file *filp, const char __user *ubuf,
2695 goto out; 2704 goto out;
2696 } 2705 }
2697 2706
2707 /* disable all cpu buffers */
2708 for_each_tracing_cpu(cpu) {
2709 if (global_trace.data[cpu])
2710 atomic_inc(&global_trace.data[cpu]->disabled);
2711 if (max_tr.data[cpu])
2712 atomic_inc(&max_tr.data[cpu]->disabled);
2713 }
2714
2698 if (val != global_trace.entries) { 2715 if (val != global_trace.entries) {
2699 ret = ring_buffer_resize(global_trace.buffer, val); 2716 ret = ring_buffer_resize(global_trace.buffer, val);
2700 if (ret < 0) { 2717 if (ret < 0) {
@@ -2726,6 +2743,13 @@ tracing_entries_write(struct file *filp, const char __user *ubuf,
2726 if (tracing_disabled) 2743 if (tracing_disabled)
2727 cnt = -ENOMEM; 2744 cnt = -ENOMEM;
2728 out: 2745 out:
2746 for_each_tracing_cpu(cpu) {
2747 if (global_trace.data[cpu])
2748 atomic_dec(&global_trace.data[cpu]->disabled);
2749 if (max_tr.data[cpu])
2750 atomic_dec(&max_tr.data[cpu]->disabled);
2751 }
2752
2729 max_tr.entries = global_trace.entries; 2753 max_tr.entries = global_trace.entries;
2730 mutex_unlock(&trace_types_lock); 2754 mutex_unlock(&trace_types_lock);
2731 2755
@@ -3097,7 +3121,7 @@ void ftrace_dump(void)
3097 dump_ran = 1; 3121 dump_ran = 1;
3098 3122
3099 /* No turning back! */ 3123 /* No turning back! */
3100 ftrace_kill_atomic(); 3124 ftrace_kill();
3101 3125
3102 for_each_tracing_cpu(cpu) { 3126 for_each_tracing_cpu(cpu) {
3103 atomic_inc(&global_trace.data[cpu]->disabled); 3127 atomic_inc(&global_trace.data[cpu]->disabled);