aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/trace.c117
1 files changed, 87 insertions, 30 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 85bee775a03e..e4c40c868d67 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -64,6 +64,37 @@ static cpumask_t __read_mostly tracing_buffer_mask;
64 64
65static int tracing_disabled = 1; 65static int tracing_disabled = 1;
66 66
67/*
68 * ftrace_dump_on_oops - variable to dump ftrace buffer on oops
69 *
70 * If there is an oops (or kernel panic) and the ftrace_dump_on_oops
71 * is set, then ftrace_dump is called. This will output the contents
72 * of the ftrace buffers to the console. This is very useful for
73 * capturing traces that lead to crashes and outputing it to a
74 * serial console.
75 *
76 * It is default off, but you can enable it with either specifying
77 * "ftrace_dump_on_oops" in the kernel command line, or setting
78 * /proc/sys/kernel/ftrace_dump_on_oops to true.
79 */
80int ftrace_dump_on_oops;
81
82static int tracing_set_tracer(char *buf);
83
84static int __init set_ftrace(char *str)
85{
86 tracing_set_tracer(str);
87 return 1;
88}
89__setup("ftrace", set_ftrace);
90
91static int __init set_ftrace_dump_on_oops(char *str)
92{
93 ftrace_dump_on_oops = 1;
94 return 1;
95}
96__setup("ftrace_dump_on_oops", set_ftrace_dump_on_oops);
97
67long 98long
68ns2usecs(cycle_t nsec) 99ns2usecs(cycle_t nsec)
69{ 100{
@@ -2374,29 +2405,11 @@ tracing_set_trace_read(struct file *filp, char __user *ubuf,
2374 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); 2405 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
2375} 2406}
2376 2407
2377static ssize_t 2408static int tracing_set_tracer(char *buf)
2378tracing_set_trace_write(struct file *filp, const char __user *ubuf,
2379 size_t cnt, loff_t *ppos)
2380{ 2409{
2381 struct trace_array *tr = &global_trace; 2410 struct trace_array *tr = &global_trace;
2382 struct tracer *t; 2411 struct tracer *t;
2383 char buf[max_tracer_type_len+1]; 2412 int ret = 0;
2384 int i;
2385 size_t ret;
2386
2387 ret = cnt;
2388
2389 if (cnt > max_tracer_type_len)
2390 cnt = max_tracer_type_len;
2391
2392 if (copy_from_user(&buf, ubuf, cnt))
2393 return -EFAULT;
2394
2395 buf[cnt] = 0;
2396
2397 /* strip ending whitespace. */
2398 for (i = cnt - 1; i > 0 && isspace(buf[i]); i--)
2399 buf[i] = 0;
2400 2413
2401 mutex_lock(&trace_types_lock); 2414 mutex_lock(&trace_types_lock);
2402 for (t = trace_types; t; t = t->next) { 2415 for (t = trace_types; t; t = t->next) {
@@ -2420,6 +2433,33 @@ tracing_set_trace_write(struct file *filp, const char __user *ubuf,
2420 out: 2433 out:
2421 mutex_unlock(&trace_types_lock); 2434 mutex_unlock(&trace_types_lock);
2422 2435
2436 return ret;
2437}
2438
2439static ssize_t
2440tracing_set_trace_write(struct file *filp, const char __user *ubuf,
2441 size_t cnt, loff_t *ppos)
2442{
2443 char buf[max_tracer_type_len+1];
2444 int i;
2445 size_t ret;
2446
2447 if (cnt > max_tracer_type_len)
2448 cnt = max_tracer_type_len;
2449
2450 if (copy_from_user(&buf, ubuf, cnt))
2451 return -EFAULT;
2452
2453 buf[cnt] = 0;
2454
2455 /* strip ending whitespace. */
2456 for (i = cnt - 1; i > 0 && isspace(buf[i]); i--)
2457 buf[i] = 0;
2458
2459 ret = tracing_set_tracer(buf);
2460 if (!ret)
2461 ret = cnt;
2462
2423 if (ret > 0) 2463 if (ret > 0)
2424 filp->f_pos += ret; 2464 filp->f_pos += ret;
2425 2465
@@ -2822,22 +2862,38 @@ static struct file_operations tracing_mark_fops = {
2822 2862
2823#ifdef CONFIG_DYNAMIC_FTRACE 2863#ifdef CONFIG_DYNAMIC_FTRACE
2824 2864
2865int __weak ftrace_arch_read_dyn_info(char *buf, int size)
2866{
2867 return 0;
2868}
2869
2825static ssize_t 2870static ssize_t
2826tracing_read_long(struct file *filp, char __user *ubuf, 2871tracing_read_dyn_info(struct file *filp, char __user *ubuf,
2827 size_t cnt, loff_t *ppos) 2872 size_t cnt, loff_t *ppos)
2828{ 2873{
2874 static char ftrace_dyn_info_buffer[1024];
2875 static DEFINE_MUTEX(dyn_info_mutex);
2829 unsigned long *p = filp->private_data; 2876 unsigned long *p = filp->private_data;
2830 char buf[64]; 2877 char *buf = ftrace_dyn_info_buffer;
2878 int size = ARRAY_SIZE(ftrace_dyn_info_buffer);
2831 int r; 2879 int r;
2832 2880
2833 r = sprintf(buf, "%ld\n", *p); 2881 mutex_lock(&dyn_info_mutex);
2882 r = sprintf(buf, "%ld ", *p);
2834 2883
2835 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); 2884 r += ftrace_arch_read_dyn_info(buf+r, (size-1)-r);
2885 buf[r++] = '\n';
2886
2887 r = simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
2888
2889 mutex_unlock(&dyn_info_mutex);
2890
2891 return r;
2836} 2892}
2837 2893
2838static struct file_operations tracing_read_long_fops = { 2894static struct file_operations tracing_dyn_info_fops = {
2839 .open = tracing_open_generic, 2895 .open = tracing_open_generic,
2840 .read = tracing_read_long, 2896 .read = tracing_read_dyn_info,
2841}; 2897};
2842#endif 2898#endif
2843 2899
@@ -2946,7 +3002,7 @@ static __init int tracer_init_debugfs(void)
2946#ifdef CONFIG_DYNAMIC_FTRACE 3002#ifdef CONFIG_DYNAMIC_FTRACE
2947 entry = debugfs_create_file("dyn_ftrace_total_info", 0444, d_tracer, 3003 entry = debugfs_create_file("dyn_ftrace_total_info", 0444, d_tracer,
2948 &ftrace_update_tot_cnt, 3004 &ftrace_update_tot_cnt,
2949 &tracing_read_long_fops); 3005 &tracing_dyn_info_fops);
2950 if (!entry) 3006 if (!entry)
2951 pr_warning("Could not create debugfs " 3007 pr_warning("Could not create debugfs "
2952 "'dyn_ftrace_total_info' entry\n"); 3008 "'dyn_ftrace_total_info' entry\n");
@@ -3027,7 +3083,8 @@ EXPORT_SYMBOL_GPL(__ftrace_printk);
3027static int trace_panic_handler(struct notifier_block *this, 3083static int trace_panic_handler(struct notifier_block *this,
3028 unsigned long event, void *unused) 3084 unsigned long event, void *unused)
3029{ 3085{
3030 ftrace_dump(); 3086 if (ftrace_dump_on_oops)
3087 ftrace_dump();
3031 return NOTIFY_OK; 3088 return NOTIFY_OK;
3032} 3089}
3033 3090
@@ -3043,7 +3100,8 @@ static int trace_die_handler(struct notifier_block *self,
3043{ 3100{
3044 switch (val) { 3101 switch (val) {
3045 case DIE_OOPS: 3102 case DIE_OOPS:
3046 ftrace_dump(); 3103 if (ftrace_dump_on_oops)
3104 ftrace_dump();
3047 break; 3105 break;
3048 default: 3106 default:
3049 break; 3107 break;
@@ -3084,7 +3142,6 @@ trace_printk_seq(struct trace_seq *s)
3084 trace_seq_reset(s); 3142 trace_seq_reset(s);
3085} 3143}
3086 3144
3087
3088void ftrace_dump(void) 3145void ftrace_dump(void)
3089{ 3146{
3090 static DEFINE_SPINLOCK(ftrace_dump_lock); 3147 static DEFINE_SPINLOCK(ftrace_dump_lock);