aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2008-05-12 15:20:48 -0400
committerThomas Gleixner <tglx@linutronix.de>2008-05-23 14:54:16 -0400
commit4eebcc81a33fbc45e28542b50197ed7b3c486d90 (patch)
tree13bbad50aa8d4dc36d630ef08886876f4dc0b6eb /kernel
parent37ad508419f0fdfda7b378756eb1f35cfd26d96d (diff)
ftrace: disable tracing on failure
Since ftrace touches practically every function. If we detect any anomaly, we want to fully disable ftrace. This patch adds code to try shutdown ftrace as much as possible without doing any more harm is something is detected not quite correct. This only kills ftrace, this patch does have checks for other parts of the tracer (irqsoff, wakeup, etc.). Signed-off-by: Steven Rostedt <srostedt@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/ftrace.c112
-rw-r--r--kernel/trace/trace_selftest.c4
2 files changed, 107 insertions, 9 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 8e02aa690b2b..ff42345dd78e 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -29,9 +29,16 @@
29 29
30#include "trace.h" 30#include "trace.h"
31 31
32int ftrace_enabled; 32/* ftrace_enabled is a method to turn ftrace on or off */
33int ftrace_enabled __read_mostly;
33static int last_ftrace_enabled; 34static int last_ftrace_enabled;
34 35
36/*
37 * ftrace_disabled is set when an anomaly is discovered.
38 * ftrace_disabled is much stronger than ftrace_enabled.
39 */
40static int ftrace_disabled __read_mostly;
41
35static DEFINE_SPINLOCK(ftrace_lock); 42static DEFINE_SPINLOCK(ftrace_lock);
36static DEFINE_MUTEX(ftrace_sysctl_lock); 43static DEFINE_MUTEX(ftrace_sysctl_lock);
37 44
@@ -230,10 +237,11 @@ static notrace struct dyn_ftrace *ftrace_alloc_dyn_node(unsigned long ip)
230 if (ftrace_free_records) { 237 if (ftrace_free_records) {
231 rec = ftrace_free_records; 238 rec = ftrace_free_records;
232 239
233 /* todo, disable tracing altogether on this warning */
234 if (unlikely(!(rec->flags & FTRACE_FL_FREE))) { 240 if (unlikely(!(rec->flags & FTRACE_FL_FREE))) {
235 WARN_ON_ONCE(1); 241 WARN_ON_ONCE(1);
236 ftrace_free_records = NULL; 242 ftrace_free_records = NULL;
243 ftrace_disabled = 1;
244 ftrace_enabled = 0;
237 return NULL; 245 return NULL;
238 } 246 }
239 247
@@ -260,7 +268,7 @@ ftrace_record_ip(unsigned long ip)
260 int resched; 268 int resched;
261 int atomic; 269 int atomic;
262 270
263 if (!ftrace_enabled) 271 if (!ftrace_enabled || ftrace_disabled)
264 return; 272 return;
265 273
266 resched = need_resched(); 274 resched = need_resched();
@@ -485,6 +493,9 @@ static void notrace ftrace_startup(void)
485{ 493{
486 int command = 0; 494 int command = 0;
487 495
496 if (unlikely(ftrace_disabled))
497 return;
498
488 mutex_lock(&ftraced_lock); 499 mutex_lock(&ftraced_lock);
489 ftraced_suspend++; 500 ftraced_suspend++;
490 if (ftraced_suspend == 1) 501 if (ftraced_suspend == 1)
@@ -507,6 +518,9 @@ static void notrace ftrace_shutdown(void)
507{ 518{
508 int command = 0; 519 int command = 0;
509 520
521 if (unlikely(ftrace_disabled))
522 return;
523
510 mutex_lock(&ftraced_lock); 524 mutex_lock(&ftraced_lock);
511 ftraced_suspend--; 525 ftraced_suspend--;
512 if (!ftraced_suspend) 526 if (!ftraced_suspend)
@@ -529,6 +543,9 @@ static void notrace ftrace_startup_sysctl(void)
529{ 543{
530 int command = FTRACE_ENABLE_MCOUNT; 544 int command = FTRACE_ENABLE_MCOUNT;
531 545
546 if (unlikely(ftrace_disabled))
547 return;
548
532 mutex_lock(&ftraced_lock); 549 mutex_lock(&ftraced_lock);
533 /* Force update next time */ 550 /* Force update next time */
534 saved_ftrace_func = NULL; 551 saved_ftrace_func = NULL;
@@ -544,6 +561,9 @@ static void notrace ftrace_shutdown_sysctl(void)
544{ 561{
545 int command = FTRACE_DISABLE_MCOUNT; 562 int command = FTRACE_DISABLE_MCOUNT;
546 563
564 if (unlikely(ftrace_disabled))
565 return;
566
547 mutex_lock(&ftraced_lock); 567 mutex_lock(&ftraced_lock);
548 /* ftraced_suspend is true if ftrace is running */ 568 /* ftraced_suspend is true if ftrace is running */
549 if (ftraced_suspend) 569 if (ftraced_suspend)
@@ -600,6 +620,9 @@ static int notrace __ftrace_update_code(void *ignore)
600 620
601static void notrace ftrace_update_code(void) 621static void notrace ftrace_update_code(void)
602{ 622{
623 if (unlikely(ftrace_disabled))
624 return;
625
603 stop_machine_run(__ftrace_update_code, NULL, NR_CPUS); 626 stop_machine_run(__ftrace_update_code, NULL, NR_CPUS);
604} 627}
605 628
@@ -614,6 +637,9 @@ static int notrace ftraced(void *ignore)
614 /* check once a second */ 637 /* check once a second */
615 schedule_timeout(HZ); 638 schedule_timeout(HZ);
616 639
640 if (unlikely(ftrace_disabled))
641 continue;
642
617 mutex_lock(&ftrace_sysctl_lock); 643 mutex_lock(&ftrace_sysctl_lock);
618 mutex_lock(&ftraced_lock); 644 mutex_lock(&ftraced_lock);
619 if (ftrace_enabled && ftraced_trigger && !ftraced_suspend) { 645 if (ftrace_enabled && ftraced_trigger && !ftraced_suspend) {
@@ -628,6 +654,7 @@ static int notrace ftraced(void *ignore)
628 ftrace_update_cnt != 1 ? "s" : "", 654 ftrace_update_cnt != 1 ? "s" : "",
629 ftrace_update_tot_cnt, 655 ftrace_update_tot_cnt,
630 usecs, usecs != 1 ? "s" : ""); 656 usecs, usecs != 1 ? "s" : "");
657 ftrace_disabled = 1;
631 WARN_ON_ONCE(1); 658 WARN_ON_ONCE(1);
632 } 659 }
633 ftraced_trigger = 0; 660 ftraced_trigger = 0;
@@ -785,6 +812,9 @@ ftrace_avail_open(struct inode *inode, struct file *file)
785 struct ftrace_iterator *iter; 812 struct ftrace_iterator *iter;
786 int ret; 813 int ret;
787 814
815 if (unlikely(ftrace_disabled))
816 return -ENODEV;
817
788 iter = kzalloc(sizeof(*iter), GFP_KERNEL); 818 iter = kzalloc(sizeof(*iter), GFP_KERNEL);
789 if (!iter) 819 if (!iter)
790 return -ENOMEM; 820 return -ENOMEM;
@@ -843,6 +873,9 @@ ftrace_filter_open(struct inode *inode, struct file *file)
843 struct ftrace_iterator *iter; 873 struct ftrace_iterator *iter;
844 int ret = 0; 874 int ret = 0;
845 875
876 if (unlikely(ftrace_disabled))
877 return -ENODEV;
878
846 iter = kzalloc(sizeof(*iter), GFP_KERNEL); 879 iter = kzalloc(sizeof(*iter), GFP_KERNEL);
847 if (!iter) 880 if (!iter)
848 return -ENOMEM; 881 return -ENOMEM;
@@ -1063,6 +1096,9 @@ ftrace_filter_write(struct file *file, const char __user *ubuf,
1063 */ 1096 */
1064notrace void ftrace_set_filter(unsigned char *buf, int len, int reset) 1097notrace void ftrace_set_filter(unsigned char *buf, int len, int reset)
1065{ 1098{
1099 if (unlikely(ftrace_disabled))
1100 return;
1101
1066 mutex_lock(&ftrace_filter_lock); 1102 mutex_lock(&ftrace_filter_lock);
1067 if (reset) 1103 if (reset)
1068 ftrace_filter_reset(); 1104 ftrace_filter_reset();
@@ -1133,7 +1169,7 @@ int ftrace_force_update(void)
1133 DECLARE_WAITQUEUE(wait, current); 1169 DECLARE_WAITQUEUE(wait, current);
1134 int ret = 0; 1170 int ret = 0;
1135 1171
1136 if (!ftraced_task) 1172 if (unlikely(ftrace_disabled))
1137 return -ENODEV; 1173 return -ENODEV;
1138 1174
1139 mutex_lock(&ftraced_lock); 1175 mutex_lock(&ftraced_lock);
@@ -1142,6 +1178,11 @@ int ftrace_force_update(void)
1142 set_current_state(TASK_INTERRUPTIBLE); 1178 set_current_state(TASK_INTERRUPTIBLE);
1143 add_wait_queue(&ftraced_waiters, &wait); 1179 add_wait_queue(&ftraced_waiters, &wait);
1144 1180
1181 if (unlikely(!ftraced_task)) {
1182 ret = -ENODEV;
1183 goto out;
1184 }
1185
1145 do { 1186 do {
1146 mutex_unlock(&ftraced_lock);