aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
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/trace
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/trace')
-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); 1187 mutex_unlock(&ftraced_lock);
1147 wake_up_process(ftraced_task); 1188 wake_up_process(ftraced_task);
@@ -1154,6 +1195,7 @@ int ftrace_force_update(void)
1154 set_current_state(TASK_INTERRUPTIBLE); 1195 set_current_state(TASK_INTERRUPTIBLE);
1155 } while (last_counter == ftraced_iteration_counter); 1196 } while (last_counter == ftraced_iteration_counter);
1156 1197
1198 out:
1157 mutex_unlock(&ftraced_lock); 1199 mutex_unlock(&ftraced_lock);
1158 remove_wait_queue(&ftraced_waiters, &wait); 1200 remove_wait_queue(&ftraced_waiters, &wait);
1159 set_current_state(TASK_RUNNING); 1201 set_current_state(TASK_RUNNING);
@@ -1161,6 +1203,22 @@ int ftrace_force_update(void)
1161 return ret; 1203 return ret;
1162} 1204}
1163 1205
1206static void ftrace_force_shutdown(void)
1207{
1208 struct task_struct *task;
1209 int command = FTRACE_DISABLE_CALLS | FTRACE_UPDATE_TRACE_FUNC;
1210
1211 mutex_lock(&ftraced_lock);
1212 task = ftraced_task;
1213 ftraced_task = NULL;
1214 ftraced_suspend = -1;
1215 ftrace_run_update_code(command);
1216 mutex_unlock(&ftraced_lock);
1217
1218 if (task)
1219 kthread_stop(task);
1220}
1221
1164static __init int ftrace_init_debugfs(void) 1222static __init int ftrace_init_debugfs(void)
1165{ 1223{
1166 struct dentry *d_tracer; 1224 struct dentry *d_tracer;
@@ -1194,21 +1252,29 @@ static int __init notrace ftrace_dynamic_init(void)
1194 stop_machine_run(ftrace_dyn_arch_init, &addr, NR_CPUS); 1252 stop_machine_run(ftrace_dyn_arch_init, &addr, NR_CPUS);
1195 1253
1196 /* ftrace_dyn_arch_init places the return code in addr */ 1254 /* ftrace_dyn_arch_init places the return code in addr */
1197 if (addr) 1255 if (addr) {
1198 return addr; 1256 ret = (int)addr;
1257 goto failed;
1258 }
1199 1259
1200 ret = ftrace_dyn_table_alloc(); 1260 ret = ftrace_dyn_table_alloc();
1201 if (ret) 1261 if (ret)
1202 return ret; 1262 goto failed;
1203 1263
1204 p = kthread_run(ftraced, NULL, "ftraced"); 1264 p = kthread_run(ftraced, NULL, "ftraced");
1205 if (IS_ERR(p)) 1265 if (IS_ERR(p)) {
1206 return -1; 1266 ret = -1;
1267 goto failed;
1268 }
1207 1269
1208 last_ftrace_enabled = ftrace_enabled = 1; 1270 last_ftrace_enabled = ftrace_enabled = 1;
1209 ftraced_task = p; 1271 ftraced_task = p;
1210 1272
1211 return 0; 1273 return 0;
1274
1275 failed:
1276 ftrace_disabled = 1;
1277 return ret;
1212} 1278}
1213 1279
1214core_initcall(ftrace_dynamic_init); 1280core_initcall(ftrace_dynamic_init);
@@ -1217,9 +1283,31 @@ core_initcall(ftrace_dynamic_init);
1217# define ftrace_shutdown() do { } while (0) 1283# define ftrace_shutdown() do { } while (0)
1218# define ftrace_startup_sysctl() do { } while (0) 1284# define ftrace_startup_sysctl() do { } while (0)
1219# define ftrace_shutdown_sysctl() do { } while (0) 1285# define ftrace_shutdown_sysctl() do { } while (0)
1286# define ftrace_force_shutdown() do { } while (0)
1220#endif /* CONFIG_DYNAMIC_FTRACE */ 1287#endif /* CONFIG_DYNAMIC_FTRACE */
1221 1288
1222/** 1289/**
1290 * ftrace_kill - totally shutdown ftrace
1291 *
1292 * This is a safety measure. If something was detected that seems
1293 * wrong, calling this function will keep ftrace from doing
1294 * any more modifications, and updates.
1295 * used when something went wrong.
1296 */
1297void ftrace_kill(void)
1298{
1299 mutex_lock(&ftrace_sysctl_lock);
1300 ftrace_disabled = 1;
1301 ftrace_enabled = 0;
1302
1303 clear_ftrace_function();
1304 mutex_unlock(&ftrace_sysctl_lock);
1305
1306 /* Try to totally disable ftrace */
1307 ftrace_force_shutdown();
1308}
1309
1310/**
1223 * register_ftrace_function - register a function for profiling 1311 * register_ftrace_function - register a function for profiling
1224 * @ops - ops structure that holds the function for profiling. 1312 * @ops - ops structure that holds the function for profiling.
1225 * 1313 *
@@ -1234,6 +1322,9 @@ int register_ftrace_function(struct ftrace_ops *ops)
1234{ 1322{
1235 int ret; 1323 int ret;
1236 1324
1325 if (unlikely(ftrace_disabled))
1326 return -1;
1327
1237 mutex_lock(&ftrace_sysctl_lock); 1328 mutex_lock(&ftrace_sysctl_lock);
1238 ret = __register_ftrace_function(ops); 1329 ret = __register_ftrace_function(ops);
1239 ftrace_startup(); 1330 ftrace_startup();
@@ -1267,6 +1358,9 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,
1267{ 1358{
1268 int ret; 1359 int ret;
1269 1360
1361 if (unlikely(ftrace_disabled))
1362 return -ENODEV;
1363
1270 mutex_lock(&ftrace_sysctl_lock); 1364 mutex_lock(&ftrace_sysctl_lock);
1271 1365
1272 ret = proc_dointvec(table, write, file, buffer, lenp, ppos); 1366 ret = proc_dointvec(table, write, file, buffer, lenp, ppos);
diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c
index a6f1ed75f836..85715b86a342 100644
--- a/kernel/trace/trace_selftest.c
+++ b/kernel/trace/trace_selftest.c
@@ -248,6 +248,10 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr)
248 ftrace_enabled = save_ftrace_enabled; 248 ftrace_enabled = save_ftrace_enabled;
249 tracer_enabled = save_tracer_enabled; 249 tracer_enabled = save_tracer_enabled;
250 250
251 /* kill ftrace totally if we failed */
252 if (ret)
253 ftrace_kill();
254
251 return ret; 255 return ret;
252} 256}
253#endif /* CONFIG_FTRACE */ 257#endif /* CONFIG_FTRACE */