diff options
| -rw-r--r-- | include/linux/ftrace.h | 12 | ||||
| -rw-r--r-- | kernel/trace/Kconfig | 2 | ||||
| -rw-r--r-- | kernel/trace/ftrace.c | 102 | ||||
| -rw-r--r-- | kernel/trace/trace.c | 69 | ||||
| -rw-r--r-- | kernel/trace/trace.h | 25 | ||||
| -rw-r--r-- | kernel/trace/trace_functions.c | 32 | ||||
| -rw-r--r-- | kernel/trace/trace_functions_graph.c | 1 | ||||
| -rw-r--r-- | kernel/trace/trace_irqsoff.c | 2 | ||||
| -rw-r--r-- | kernel/trace/trace_sched_switch.c | 3 | ||||
| -rw-r--r-- | kernel/trace/trace_sched_wakeup.c | 3 | ||||
| -rw-r--r-- | kernel/trace/trace_selftest.c | 35 | ||||
| -rw-r--r-- | kernel/trace/trace_stat.c | 2 | ||||
| -rw-r--r-- | kernel/trace/trace_sysprof.c | 2 |
13 files changed, 183 insertions, 107 deletions
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 63281228ce3e..9d224c43e634 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h | |||
| @@ -108,7 +108,7 @@ struct ftrace_func_command { | |||
| 108 | 108 | ||
| 109 | struct seq_file; | 109 | struct seq_file; |
| 110 | 110 | ||
| 111 | struct ftrace_hook_ops { | 111 | struct ftrace_probe_ops { |
| 112 | void (*func)(unsigned long ip, | 112 | void (*func)(unsigned long ip, |
| 113 | unsigned long parent_ip, | 113 | unsigned long parent_ip, |
| 114 | void **data); | 114 | void **data); |
| @@ -116,19 +116,19 @@ struct ftrace_hook_ops { | |||
| 116 | void (*free)(void **data); | 116 | void (*free)(void **data); |
| 117 | int (*print)(struct seq_file *m, | 117 | int (*print)(struct seq_file *m, |
| 118 | unsigned long ip, | 118 | unsigned long ip, |
| 119 | struct ftrace_hook_ops *ops, | 119 | struct ftrace_probe_ops *ops, |
| 120 | void *data); | 120 | void *data); |
| 121 | }; | 121 | }; |
| 122 | 122 | ||
| 123 | extern int | 123 | extern int |
| 124 | register_ftrace_function_hook(char *glob, struct ftrace_hook_ops *ops, | 124 | register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, |
| 125 | void *data); | 125 | void *data); |
| 126 | extern void | 126 | extern void |
| 127 | unregister_ftrace_function_hook(char *glob, struct ftrace_hook_ops *ops, | 127 | unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, |
| 128 | void *data); | 128 | void *data); |
| 129 | extern void | 129 | extern void |
| 130 | unregister_ftrace_function_hook_func(char *glob, struct ftrace_hook_ops *ops); | 130 | unregister_ftrace_function_probe_func(char *glob, struct ftrace_probe_ops *ops); |
| 131 | extern void unregister_ftrace_function_hook_all(char *glob); | 131 | extern void unregister_ftrace_function_probe_all(char *glob); |
| 132 | 132 | ||
| 133 | enum { | 133 | enum { |
| 134 | FTRACE_FL_FREE = (1 << 0), | 134 | FTRACE_FL_FREE = (1 << 0), |
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 6ff928acd453..07877f4b5233 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig | |||
| @@ -60,6 +60,7 @@ config FUNCTION_TRACER | |||
| 60 | depends on HAVE_FUNCTION_TRACER | 60 | depends on HAVE_FUNCTION_TRACER |
| 61 | depends on DEBUG_KERNEL | 61 | depends on DEBUG_KERNEL |
| 62 | select FRAME_POINTER | 62 | select FRAME_POINTER |
| 63 | select KALLSYMS | ||
| 63 | select TRACING | 64 | select TRACING |
| 64 | select CONTEXT_SWITCH_TRACER | 65 | select CONTEXT_SWITCH_TRACER |
| 65 | help | 66 | help |
| @@ -246,6 +247,7 @@ config STACK_TRACER | |||
| 246 | depends on DEBUG_KERNEL | 247 | depends on DEBUG_KERNEL |
| 247 | select FUNCTION_TRACER | 248 | select FUNCTION_TRACER |
| 248 | select STACKTRACE | 249 | select STACKTRACE |
| 250 | select KALLSYMS | ||
| 249 | help | 251 | help |
| 250 | This special tracer records the maximum stack footprint of the | 252 | This special tracer records the maximum stack footprint of the |
| 251 | kernel and displays it in debugfs/tracing/stack_trace. | 253 | kernel and displays it in debugfs/tracing/stack_trace. |
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index aee95aea57e4..7dd5a2bef9cd 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
| @@ -255,9 +255,9 @@ static struct pid * const ftrace_swapper_pid = &init_struct_pid; | |||
| 255 | 255 | ||
| 256 | static struct hlist_head ftrace_func_hash[FTRACE_FUNC_HASHSIZE] __read_mostly; | 256 | static struct hlist_head ftrace_func_hash[FTRACE_FUNC_HASHSIZE] __read_mostly; |
| 257 | 257 | ||
| 258 | struct ftrace_func_hook { | 258 | struct ftrace_func_probe { |
| 259 | struct hlist_node node; | 259 | struct hlist_node node; |
| 260 | struct ftrace_hook_ops *ops; | 260 | struct ftrace_probe_ops *ops; |
| 261 | unsigned long flags; | 261 | unsigned long flags; |
| 262 | unsigned long ip; | 262 | unsigned long ip; |
| 263 | void *data; | 263 | void *data; |
| @@ -460,8 +460,8 @@ static void ftrace_bug(int failed, unsigned long ip) | |||
| 460 | static int | 460 | static int |
| 461 | __ftrace_replace_code(struct dyn_ftrace *rec, int enable) | 461 | __ftrace_replace_code(struct dyn_ftrace *rec, int enable) |
| 462 | { | 462 | { |
| 463 | unsigned long ip, fl; | ||
| 464 | unsigned long ftrace_addr; | 463 | unsigned long ftrace_addr; |
| 464 | unsigned long ip, fl; | ||
| 465 | 465 | ||
| 466 | ftrace_addr = (unsigned long)FTRACE_ADDR; | 466 | ftrace_addr = (unsigned long)FTRACE_ADDR; |
| 467 | 467 | ||
| @@ -530,9 +530,9 @@ __ftrace_replace_code(struct dyn_ftrace *rec, int enable) | |||
| 530 | 530 | ||
| 531 | static void ftrace_replace_code(int enable) | 531 | static void ftrace_replace_code(int enable) |
| 532 | { | 532 | { |
| 533 | int failed; | ||
| 534 | struct dyn_ftrace *rec; | 533 | struct dyn_ftrace *rec; |
| 535 | struct ftrace_page *pg; | 534 | struct ftrace_page *pg; |
| 535 | int failed; | ||
| 536 | 536 | ||
| 537 | do_for_each_ftrace_rec(pg, rec) { | 537 | do_for_each_ftrace_rec(pg, rec) { |
| 538 | /* | 538 | /* |
| @@ -830,11 +830,11 @@ static void *t_hash_start(struct seq_file *m, loff_t *pos) | |||
| 830 | 830 | ||
| 831 | static int t_hash_show(struct seq_file *m, void *v) | 831 | static int t_hash_show(struct seq_file *m, void *v) |
| 832 | { | 832 | { |
| 833 | struct ftrace_func_hook *rec; | 833 | struct ftrace_func_probe *rec; |
| 834 | struct hlist_node *hnd = v; | 834 | struct hlist_node *hnd = v; |
| 835 | char str[KSYM_SYMBOL_LEN]; | 835 | char str[KSYM_SYMBOL_LEN]; |
| 836 | 836 | ||
| 837 | rec = hlist_entry(hnd, struct ftrace_func_hook, node); | 837 | rec = hlist_entry(hnd, struct ftrace_func_probe, node); |
| 838 | 838 | ||
| 839 | if (rec->ops->print) | 839 | if (rec->ops->print) |
| 840 | return rec->ops->print(m, rec->ip, rec->ops, rec->data); | 840 | return rec->ops->print(m, rec->ip, rec->ops, rec->data); |
| @@ -1208,14 +1208,15 @@ ftrace_match_record(struct dyn_ftrace *rec, char *regex, int len, int type) | |||
| 1208 | 1208 | ||
| 1209 | static void ftrace_match_records(char *buff, int len, int enable) | 1209 | static void ftrace_match_records(char *buff, int len, int enable) |
| 1210 | { | 1210 | { |
| 1211 | char *search; | 1211 | unsigned int search_len; |
| 1212 | struct ftrace_page *pg; | 1212 | struct ftrace_page *pg; |
| 1213 | struct dyn_ftrace *rec; | 1213 | struct dyn_ftrace *rec; |
| 1214 | unsigned long flag; | ||
| 1215 | char *search; | ||
| 1214 | int type; | 1216 | int type; |
| 1215 | unsigned long flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE; | ||
| 1216 | unsigned search_len; | ||
| 1217 | int not; | 1217 | int not; |
| 1218 | 1218 | ||
| 1219 | flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE; | ||
| 1219 | type = ftrace_setup_glob(buff, len, &search, ¬); | 1220 | type = ftrace_setup_glob(buff, len, &search, ¬); |
| 1220 | 1221 | ||
| 1221 | search_len = strlen(search); | 1222 | search_len = strlen(search); |
| @@ -1263,14 +1264,16 @@ ftrace_match_module_record(struct dyn_ftrace *rec, char *mod, | |||
| 1263 | 1264 | ||
| 1264 | static void ftrace_match_module_records(char *buff, char *mod, int enable) | 1265 | static void ftrace_match_module_records(char *buff, char *mod, int enable) |
| 1265 | { | 1266 | { |
| 1266 | char *search = buff; | 1267 | unsigned search_len = 0; |
| 1267 | struct ftrace_page *pg; | 1268 | struct ftrace_page *pg; |
| 1268 | struct dyn_ftrace *rec; | 1269 | struct dyn_ftrace *rec; |
| 1269 | int type = MATCH_FULL; | 1270 | int type = MATCH_FULL; |
| 1270 | unsigned long flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE; | 1271 | char *search = buff; |
| 1271 | unsigned search_len = 0; | 1272 | unsigned long flag; |
| 1272 | int not = 0; | 1273 | int not = 0; |
| 1273 | 1274 | ||
| 1275 | flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE; | ||
| 1276 | |||
| 1274 | /* blank or '*' mean the same */ | 1277 | /* blank or '*' mean the same */ |
| 1275 | if (strcmp(buff, "*") == 0) | 1278 | if (strcmp(buff, "*") == 0) |
| 1276 | buff[0] = 0; | 1279 | buff[0] = 0; |
| @@ -1348,9 +1351,9 @@ static int __init ftrace_mod_cmd_init(void) | |||
| 1348 | device_initcall(ftrace_mod_cmd_init); | 1351 | device_initcall(ftrace_mod_cmd_init); |
| 1349 | 1352 | ||
| 1350 | static void | 1353 | static void |
| 1351 | function_trace_hook_call(unsigned long ip, unsigned long parent_ip) | 1354 | function_trace_probe_call(unsigned long ip, unsigned long parent_ip) |
| 1352 | { | 1355 | { |
| 1353 | struct ftrace_func_hook *entry; | 1356 | struct ftrace_func_probe *entry; |
| 1354 | struct hlist_head *hhd; | 1357 | struct hlist_head *hhd; |
| 1355 | struct hlist_node *n; | 1358 | struct hlist_node *n; |
| 1356 | unsigned long key; | 1359 | unsigned long key; |
| @@ -1376,18 +1379,18 @@ function_trace_hook_call(unsigned long ip, unsigned long parent_ip) | |||
| 1376 | ftrace_preempt_enable(resched); | 1379 | ftrace_preempt_enable(resched); |
| 1377 | } | 1380 | } |
| 1378 | 1381 | ||
| 1379 | static struct ftrace_ops trace_hook_ops __read_mostly = | 1382 | static struct ftrace_ops trace_probe_ops __read_mostly = |
| 1380 | { | 1383 | { |
| 1381 | .func = function_trace_hook_call, | 1384 | .func = function_trace_probe_call, |
| 1382 | }; | 1385 | }; |
| 1383 | 1386 | ||
| 1384 | static int ftrace_hook_registered; | 1387 | static int ftrace_probe_registered; |
| 1385 | 1388 | ||
| 1386 | static void __enable_ftrace_function_hook(void) | 1389 | static void __enable_ftrace_function_probe(void) |
| 1387 | { | 1390 | { |
| 1388 | int i; | 1391 | int i; |
| 1389 | 1392 | ||
| 1390 | if (ftrace_hook_registered) | 1393 | if (ftrace_probe_registered) |
| 1391 | return; | 1394 | return; |
| 1392 | 1395 | ||
| 1393 | for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) { | 1396 | for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) { |
| @@ -1399,16 +1402,16 @@ static void __enable_ftrace_function_hook(void) | |||
| 1399 | if (i == FTRACE_FUNC_HASHSIZE) | 1402 | if (i == FTRACE_FUNC_HASHSIZE) |
| 1400 | return; | 1403 | return; |
| 1401 | 1404 | ||
| 1402 | __register_ftrace_function(&trace_hook_ops); | 1405 | __register_ftrace_function(&trace_probe_ops); |
| 1403 | ftrace_startup(0); | 1406 | ftrace_startup(0); |
| 1404 | ftrace_hook_registered = 1; | 1407 | ftrace_probe_registered = 1; |
| 1405 | } | 1408 | } |
| 1406 | 1409 | ||
| 1407 | static void __disable_ftrace_function_hook(void) | 1410 | static void __disable_ftrace_function_probe(void) |
| 1408 | { | 1411 | { |
| 1409 | int i; | 1412 | int i; |
| 1410 | 1413 | ||
| 1411 | if (!ftrace_hook_registered) | 1414 | if (!ftrace_probe_registered) |
| 1412 | return; | 1415 | return; |
| 1413 | 1416 | ||
| 1414 | for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) { | 1417 | for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) { |
| @@ -1418,16 +1421,16 @@ static void __disable_ftrace_function_hook(void) | |||
| 1418 | } | 1421 | } |
| 1419 | 1422 | ||
| 1420 | /* no more funcs left */ | 1423 | /* no more funcs left */ |
| 1421 | __unregister_ftrace_function(&trace_hook_ops); | 1424 | __unregister_ftrace_function(&trace_probe_ops); |
| 1422 | ftrace_shutdown(0); | 1425 | ftrace_shutdown(0); |
| 1423 | ftrace_hook_registered = 0; | 1426 | ftrace_probe_registered = 0; |
| 1424 | } | 1427 | } |
| 1425 | 1428 | ||
| 1426 | 1429 | ||
| 1427 | static void ftrace_free_entry_rcu(struct rcu_head *rhp) | 1430 | static void ftrace_free_entry_rcu(struct rcu_head *rhp) |
| 1428 | { | 1431 | { |
| 1429 | struct ftrace_func_hook *entry = | 1432 | struct ftrace_func_probe *entry = |
| 1430 | container_of(rhp, struct ftrace_func_hook, rcu); | 1433 | container_of(rhp, struct ftrace_func_probe, rcu); |
| 1431 | 1434 | ||
| 1432 | if (entry->ops->free) | 1435 | if (entry->ops->free) |
| 1433 | entry->ops->free(&entry->data); | 1436 | entry->ops->free(&entry->data); |
| @@ -1436,21 +1439,21 @@ static void ftrace_free_entry_rcu(struct rcu_head *rhp) | |||
| 1436 | 1439 | ||
| 1437 | 1440 | ||
| 1438 | int | 1441 | int |
| 1439 | register_ftrace_function_hook(char *glob, struct ftrace_hook_ops *ops, | 1442 | register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, |
| 1440 | void *data) | 1443 | void *data) |
| 1441 | { | 1444 | { |
| 1442 | struct ftrace_func_hook *entry; | 1445 | struct ftrace_func_probe *entry; |
| 1443 | struct ftrace_page *pg; | 1446 | struct ftrace_page *pg; |
| 1444 | struct dyn_ftrace *rec; | 1447 | struct dyn_ftrace *rec; |
| 1445 | unsigned long key; | ||
| 1446 | int type, len, not; | 1448 | int type, len, not; |
| 1449 | unsigned long key; | ||
| 1447 | int count = 0; | 1450 | int count = 0; |
| 1448 | char *search; | 1451 | char *search; |
| 1449 | 1452 | ||
| 1450 | type = ftrace_setup_glob(glob, strlen(glob), &search, ¬); | 1453 | type = ftrace_setup_glob(glob, strlen(glob), &search, ¬); |
| 1451 | len = strlen(search); | 1454 | len = strlen(search); |
| 1452 | 1455 | ||
| 1453 | /* we do not support '!' for function hooks */ | 1456 | /* we do not support '!' for function probes */ |
| 1454 | if (WARN_ON(not)) | 1457 | if (WARN_ON(not)) |
| 1455 | return -EINVAL; | 1458 | return -EINVAL; |
| 1456 | 1459 | ||
| @@ -1465,7 +1468,7 @@ register_ftrace_function_hook(char *glob, struct ftrace_hook_ops *ops, | |||
| 1465 | 1468 | ||
| 1466 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | 1469 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); |
| 1467 | if (!entry) { | 1470 | if (!entry) { |
| 1468 | /* If we did not hook to any, then return error */ | 1471 | /* If we did not process any, then return error */ |
| 1469 | if (!count) | 1472 | if (!count) |
| 1470 | count = -ENOMEM; | 1473 | count = -ENOMEM; |
| 1471 | goto out_unlock; | 1474 | goto out_unlock; |
| @@ -1495,7 +1498,7 @@ register_ftrace_function_hook(char *glob, struct ftrace_hook_ops *ops, | |||
| 1495 | hlist_add_head_rcu(&entry->node, &ftrace_func_hash[key]); | 1498 | hlist_add_head_rcu(&entry->node, &ftrace_func_hash[key]); |
| 1496 | 1499 | ||
| 1497 | } while_for_each_ftrace_rec(); | 1500 | } while_for_each_ftrace_rec(); |
| 1498 | __enable_ftrace_function_hook(); | 1501 | __enable_ftrace_function_probe(); |
| 1499 | 1502 | ||
| 1500 | out_unlock: | 1503 | out_unlock: |
| 1501 | mutex_unlock(&ftrace_lock); | 1504 | mutex_unlock(&ftrace_lock); |
| @@ -1504,15 +1507,15 @@ register_ftrace_function_hook(char *glob, struct ftrace_hook_ops *ops, | |||
| 1504 | } | 1507 | } |
| 1505 | 1508 | ||
| 1506 | enum { | 1509 | enum { |
| 1507 | HOOK_TEST_FUNC = 1, | 1510 | PROBE_TEST_FUNC = 1, |
| 1508 | HOOK_TEST_DATA = 2 | 1511 | PROBE_TEST_DATA = 2 |
| 1509 | }; | 1512 | }; |
| 1510 | 1513 | ||
| 1511 | static void | 1514 | static void |
| 1512 | __unregister_ftrace_function_hook(char *glob, struct ftrace_hook_ops *ops, | 1515 | __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, |
| 1513 | void *data, int flags) | 1516 | void *data, int flags) |
| 1514 | { | 1517 | { |
| 1515 | struct ftrace_func_hook *entry; | 1518 | struct ftrace_func_probe *entry; |
| 1516 | struct hlist_node *n, *tmp; | 1519 | struct hlist_node *n, *tmp; |
| 1517 | char str[KSYM_SYMBOL_LEN]; | 1520 | char str[KSYM_SYMBOL_LEN]; |
| 1518 | int type = MATCH_FULL; | 1521 | int type = MATCH_FULL; |
| @@ -1527,7 +1530,7 @@ __unregister_ftrace_function_hook(char *glob, struct ftrace_hook_ops *ops, | |||
| 1527 | type = ftrace_setup_glob(glob, strlen(glob), &search, ¬); | 1530 | type = ftrace_setup_glob(glob, strlen(glob), &search, ¬); |
| 1528 | len = strlen(search); | 1531 | len = strlen(search); |
| 1529 | 1532 | ||
| 1530 | /* we do not support '!' for function hooks */ | 1533 | /* we do not support '!' for function probes */ |
| 1531 | if (WARN_ON(not)) | 1534 | if (WARN_ON(not)) |
| 1532 | return; | 1535 | return; |
| 1533 | } | 1536 | } |
| @@ -1539,10 +1542,10 @@ __unregister_ftrace_function_hook(char *glob, struct ftrace_hook_ops *ops, | |||
| 1539 | hlist_for_each_entry_safe(entry, n, tmp, hhd, node) { | 1542 | hlist_for_each_entry_safe(entry, n, tmp, hhd, node) { |
| 1540 | 1543 | ||
| 1541 | /* break up if statements for readability */ | 1544 | /* break up if statements for readability */ |
| 1542 | if ((flags & HOOK_TEST_FUNC) && entry->ops != ops) | 1545 | if ((flags & PROBE_TEST_FUNC) && entry->ops != ops) |
| 1543 | continue; | 1546 | continue; |
| 1544 | 1547 | ||
| 1545 | if ((flags & HOOK_TEST_DATA) && entry->data != data) | 1548 | if ((flags & PROBE_TEST_DATA) && entry->data != data) |
| 1546 | continue; | 1549 | continue; |
| 1547 | 1550 | ||
| 1548 | /* do this last, since it is the most expensive */ | 1551 | /* do this last, since it is the most expensive */ |
| @@ -1557,27 +1560,27 @@ __unregister_ftrace_function_hook(char *glob, struct ftrace_hook_ops *ops, | |||
| 1557 | call_rcu(&entry->rcu, ftrace_free_entry_rcu); | 1560 | call_rcu(&entry->rcu, ftrace_free_entry_rcu); |
| 1558 | } | 1561 | } |
| 1559 | } | 1562 | } |
| 1560 | __disable_ftrace_function_hook(); | 1563 | __disable_ftrace_function_probe(); |
| 1561 | mutex_unlock(&ftrace_lock); | 1564 | mutex_unlock(&ftrace_lock); |
| 1562 | } | 1565 | } |
| 1563 | 1566 | ||
| 1564 | void | 1567 | void |
| 1565 | unregister_ftrace_function_hook(char *glob, struct ftrace_hook_ops *ops, | 1568 | unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, |
| 1566 | void *data) | 1569 | void *data) |
| 1567 | { | 1570 | { |
| 1568 | __unregister_ftrace_function_hook(glob, ops, data, | 1571 | __unregister_ftrace_function_probe(glob, ops, data, |
| 1569 | HOOK_TEST_FUNC | HOOK_TEST_DATA); | 1572 | PROBE_TEST_FUNC | PROBE_TEST_DATA); |
| 1570 | } | 1573 | } |
| 1571 | 1574 | ||
| 1572 | void | 1575 | void |
| 1573 | unregister_ftrace_function_hook_func(char *glob, struct ftrace_hook_ops *ops) | 1576 | unregister_ftrace_function_probe_func(char *glob, struct ftrace_probe_ops *ops) |
| 1574 | { | 1577 | { |
| 1575 | __unregister_ftrace_function_hook(glob, ops, NULL, HOOK_TEST_FUNC); | 1578 | __unregister_ftrace_function_probe(glob, ops, NULL, PROBE_TEST_FUNC); |
| 1576 | } | 1579 | } |
| 1577 | 1580 | ||
| 1578 | void unregister_ftrace_function_hook_all(char *glob) | 1581 | void unregister_ftrace_function_probe_all(char *glob) |
| 1579 | { | 1582 | { |
| 1580 | __unregister_ftrace_function_hook(glob, NULL, NULL, 0); | 1583 | __unregister_ftrace_function_probe(glob, NULL, NULL, 0); |
| 1581 | } | 1584 | } |
| 1582 | 1585 | ||
| 1583 | static LIST_HEAD(ftrace_commands); | 1586 | static LIST_HEAD(ftrace_commands); |
| @@ -1623,8 +1626,8 @@ int unregister_ftrace_command(struct ftrace_func_command *cmd) | |||
| 1623 | 1626 | ||
| 1624 | static int ftrace_process_regex(char *buff, int len, int enable) | 1627 | static int ftrace_process_regex(char *buff, int len, int enable) |
| 1625 | { | 1628 | { |
| 1626 | struct ftrace_func_command *p; | ||
| 1627 | char *func, *command, *next = buff; | 1629 | char *func, *command, *next = buff; |
| 1630 | struct ftrace_func_command *p; | ||
| 1628 | int ret = -EINVAL; | 1631 | int ret = -EINVAL; |
| 1629 | 1632 | ||
| 1630 | func = strsep(&next, ":"); | 1633 | func = strsep(&next, ":"); |
| @@ -2392,7 +2395,6 @@ static __init int ftrace_init_debugfs(void) | |||
| 2392 | "'set_ftrace_pid' entry\n"); | 2395 | "'set_ftrace_pid' entry\n"); |
| 2393 | return 0; | 2396 | return 0; |
| 2394 | } | 2397 | } |
| 2395 | |||
| 2396 | fs_initcall(ftrace_init_debugfs); | 2398 | fs_initcall(ftrace_init_debugfs); |
| 2397 | 2399 | ||
| 2398 | /** | 2400 | /** |
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 95f99a7abf2f..e1f3b99a2e52 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
| @@ -336,7 +336,7 @@ __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu) | |||
| 336 | data->rt_priority = tsk->rt_priority; | 336 | data->rt_priority = tsk->rt_priority; |
| 337 | 337 | ||
| 338 | /* record this tasks comm */ | 338 | /* record this tasks comm */ |
| 339 | tracing_record_cmdline(current); | 339 | tracing_record_cmdline(tsk); |
| 340 | } | 340 | } |
| 341 | 341 | ||
| 342 | static void | 342 | static void |
| @@ -499,6 +499,9 @@ __acquires(kernel_lock) | |||
| 499 | else | 499 | else |
| 500 | if (!type->flags->opts) | 500 | if (!type->flags->opts) |
| 501 | type->flags->opts = dummy_tracer_opt; | 501 | type->flags->opts = dummy_tracer_opt; |
| 502 | if (!type->wait_pipe) | ||
| 503 | type->wait_pipe = default_wait_pipe; | ||
| 504 | |||
| 502 | 505 | ||
| 503 | #ifdef CONFIG_FTRACE_STARTUP_TEST | 506 | #ifdef CONFIG_FTRACE_STARTUP_TEST |
| 504 | if (type->selftest && !tracing_selftest_disabled) { | 507 | if (type->selftest && !tracing_selftest_disabled) { |
| @@ -1064,7 +1067,10 @@ tracing_sched_wakeup_trace(struct trace_array *tr, | |||
| 1064 | entry->next_prio = wakee->prio; | 1067 | entry->next_prio = wakee->prio; |
| 1065 | entry->next_state = wakee->state; | 1068 | entry->next_state = wakee->state; |
| 1066 | entry->next_cpu = task_cpu(wakee); | 1069 | entry->next_cpu = task_cpu(wakee); |
| 1067 | trace_buffer_unlock_commit(tr, event, flags, pc); | 1070 | |
| 1071 | ring_buffer_unlock_commit(tr->buffer, event); | ||
| 1072 | ftrace_trace_stack(tr, flags, 6, pc); | ||
| 1073 | ftrace_trace_userstack(tr, flags, pc); | ||
| 1068 | } | 1074 | } |
| 1069 | 1075 | ||
| 1070 | void | 1076 | void |
| @@ -2392,6 +2398,38 @@ tracing_poll_pipe(struct file *filp, poll_table *poll_table) | |||
| 2392 | } | 2398 | } |
| 2393 | } | 2399 | } |
| 2394 | 2400 | ||
| 2401 | |||
| 2402 | void default_wait_pipe(struct trace_iterator *iter) | ||
| 2403 | { | ||
| 2404 | DEFINE_WAIT(wait); | ||
| 2405 | |||
| 2406 | prepare_to_wait(&trace_wait, &wait, TASK_INTERRUPTIBLE); | ||
| 2407 | |||
| 2408 | if (trace_empty(iter)) | ||
| 2409 | schedule(); | ||
| 2410 | |||
| 2411 | finish_wait(&trace_wait, &wait); | ||
| 2412 | } | ||
| 2413 | |||
| 2414 | /* | ||
| 2415 | * This is a make-shift waitqueue. | ||
| 2416 | * A tracer might use this callback on some rare cases: | ||
| 2417 | * | ||
| 2418 | * 1) the current tracer might hold the runqueue lock when it wakes up | ||
| 2419 | * a reader, hence a deadlock (sched, function, and function graph tracers) | ||
| 2420 | * 2) the function tracers, trace all functions, we don't want | ||
| 2421 | * the overhead of calling wake_up and friends | ||
| 2422 | * (and tracing them too) | ||
| 2423 | * | ||
| 2424 | * Anyway, this is really very primitive wakeup. | ||
| 2425 | */ | ||
| 2426 | void poll_wait_pipe(struct trace_iterator *iter) | ||
| 2427 | { | ||
| 2428 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 2429 | /* sleep for 100 msecs, and try again. */ | ||
| 2430 | schedule_timeout(HZ / 10); | ||
| 2431 | } | ||
| 2432 | |||
| 2395 | /* Must be called with trace_types_lock mutex held. */ | 2433 | /* Must be called with trace_types_lock mutex held. */ |
| 2396 | static int tracing_wait_pipe(struct file *filp) | 2434 | static int tracing_wait_pipe(struct file *filp) |
| 2397 | { | 2435 | { |
| @@ -2403,30 +2441,14 @@ static int tracing_wait_pipe(struct file *filp) | |||
| 2403 | return -EAGAIN; | 2441 | return -EAGAIN; |
| 2404 | } | 2442 | } |
| 2405 | 2443 | ||
| 2406 | /* | ||
| 2407 | * This is a make-shift waitqueue. The reason we don't use | ||
| 2408 | * an actual wait queue is because: | ||
| 2409 | * 1) we only ever have one waiter | ||
| 2410 | * 2) the tracing, traces all functions, we don't want | ||
| 2411 | * the overhead of calling wake_up and friends | ||
| 2412 | * (and tracing them too) | ||
| 2413 | * Anyway, this is really very primitive wakeup. | ||
| 2414 | */ | ||
| 2415 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 2416 | iter->tr->waiter = current; | ||
| 2417 | |||
| 2418 | mutex_unlock(&trace_types_lock); | 2444 | mutex_unlock(&trace_types_lock); |
| 2419 | 2445 | ||
| 2420 | /* sleep for 100 msecs, and try again. */ | 2446 | iter->trace->wait_pipe(iter); |
| 2421 | schedule_timeout(HZ/10); | ||
| 2422 | 2447 | ||
| 2423 | mutex_lock(&trace_types_lock); | 2448 | mutex_lock(&trace_types_lock); |
| 2424 | 2449 | ||
| 2425 | iter->tr->waiter = NULL; | 2450 | if (signal_pending(current)) |
| 2426 | |||
| 2427 | if (signal_pending(current)) { | ||
| 2428 | return -EINTR; | 2451 | return -EINTR; |
| 2429 | } | ||
| 2430 | 2452 | ||
| 2431 | if (iter->trace != current_trace) | 2453 | if (iter->trace != current_trace) |
| 2432 | return 0; | 2454 | return 0; |
| @@ -2442,8 +2464,6 @@ static int tracing_wait_pipe(struct file *filp) | |||
| 2442 | */ | 2464 | */ |
| 2443 | if (!tracer_enabled && iter->pos) | 2465 | if (!tracer_enabled && iter->pos) |
| 2444 | break; | 2466 | break; |
| 2445 | |||
| 2446 | continue; | ||
| 2447 | } | 2467 | } |
| 2448 | 2468 | ||
| 2449 | return 1; | 2469 | return 1; |
| @@ -2551,8 +2571,7 @@ static struct pipe_buf_operations tracing_pipe_buf_ops = { | |||
| 2551 | }; | 2571 | }; |
| 2552 | 2572 | ||
| 2553 | static size_t | 2573 | static size_t |
| 2554 | tracing_fill_pipe_page(struct page *pages, size_t rem, | 2574 | tracing_fill_pipe_page(size_t rem, struct trace_iterator *iter) |
| 2555 | struct trace_iterator *iter) | ||
| 2556 | { | 2575 | { |
| 2557 | size_t count; | 2576 | size_t count; |
| 2558 | int ret; | 2577 | int ret; |
| @@ -2629,7 +2648,7 @@ static ssize_t tracing_splice_read_pipe(struct file *filp, | |||
| 2629 | if (!pages[i]) | 2648 | if (!pages[i]) |
| 2630 | break; | 2649 | break; |
| 2631 | 2650 | ||
| 2632 | rem = tracing_fill_pipe_page(pages[i], rem, iter); | 2651 | rem = tracing_fill_pipe_page(rem, iter); |
| 2633 | 2652 | ||
| 2634 | /* Copy the data into the page, so we can start over. */ | 2653 | /* Copy the data into the page, so we can start over. */ |
| 2635 | ret = trace_seq_to_buffer(&iter->seq, | 2654 | ret = trace_seq_to_buffer(&iter->seq, |
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index dbff0207b213..eed732c151fc 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
| @@ -337,18 +337,34 @@ struct tracer_flags { | |||
| 337 | #define TRACER_OPT(s, b) .name = #s, .bit = b | 337 | #define TRACER_OPT(s, b) .name = #s, .bit = b |
| 338 | 338 | ||
| 339 | 339 | ||
| 340 | /* | 340 | /** |
| 341 | * A specific tracer, represented by methods that operate on a trace array: | 341 | * struct tracer - a specific tracer and its callbacks to interact with debugfs |
| 342 | * @name: the name chosen to select it on the available_tracers file | ||
| 343 | * @init: called when one switches to this tracer (echo name > current_tracer) | ||
| 344 | * @reset: called when one switches to another tracer | ||
| 345 | * @start: called when tracing is unpaused (echo 1 > tracing_enabled) | ||
| 346 | * @stop: called when tracing is paused (echo 0 > tracing_enabled) | ||
| 347 | * @open: called when the trace file is opened | ||
| 348 | * @pipe_open: called when the trace_pipe file is opened | ||
| 349 | * @wait_pipe: override how the user waits for traces on trace_pipe | ||
| 350 | * @close: called when the trace file is released | ||
| 351 | * @read: override the default read callback on trace_pipe | ||
| 352 | * @splice_read: override the default splice_read callback on trace_pipe | ||
| 353 | * @selftest: selftest to run on boot (see trace_selftest.c) | ||
| 354 | * @print_headers: override the first lines that describe your columns | ||
| 355 | * @print_line: callback that prints a trace | ||
| 356 | * @set_flag: signals one of your private flags changed (trace_options file) | ||
| 357 | * @flags: your private flags | ||
| 342 | */ | 358 | */ |
| 343 | struct tracer { | 359 | struct tracer { |
| 344 | const char *name; | 360 | const char *name; |
| 345 | /* Your tracer should raise a warning if init fails */ | ||
| 346 | int (*init)(struct trace_array *tr); | 361 | int (*init)(struct trace_array *tr); |
| 347 | void (*reset)(struct trace_array *tr); | 362 | void (*reset)(struct trace_array *tr); |
| 348 | void (*start)(struct trace_array *tr); | 363 | void (*start)(struct trace_array *tr); |
| 349 | void (*stop)(struct trace_array *tr); | 364 | void (*stop)(struct trace_array *tr); |
| 350 | void (*open)(struct trace_iterator *iter); | 365 | void (*open)(struct trace_iterator *iter); |
| 351 | void (*pipe_open)(struct trace_iterator *iter); | 366 | void (*pipe_open)(struct trace_iterator *iter); |
| 367 | void (*wait_pipe)(struct trace_iterator *iter); | ||
| 352 | void (*close)(struct trace_iterator *iter); | 368 | void (*close)(struct trace_iterator *iter); |
| 353 | ssize_t (*read)(struct trace_iterator *iter, | 369 | ssize_t (*read)(struct trace_iterator *iter, |
| 354 | struct file *filp, char __user *ubuf, | 370 | struct file *filp, char __user *ubuf, |
| @@ -432,6 +448,9 @@ void tracing_generic_entry_update(struct trace_entry *entry, | |||
| 432 | unsigned long flags, | 448 | unsigned long flags, |
| 433 | int pc); | 449 | int pc); |
| 434 | 450 | ||
| 451 | void default_wait_pipe(struct trace_iterator *iter); | ||
| 452 | void poll_wait_pipe(struct trace_iterator *iter); | ||
| 453 | |||
| 435 | void ftrace(struct trace_array *tr, | 454 | void ftrace(struct trace_array *tr, |
| 436 | struct trace_array_cpu *data, | 455 | struct trace_array_cpu *data, |
| 437 | unsigned long ip, | 456 | unsigned long ip, |
diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c index f520aa419dff..c9a0b7df44ff 100644 --- a/kernel/trace/trace_functions.c +++ b/kernel/trace/trace_functions.c | |||
| @@ -225,6 +225,7 @@ static struct tracer function_trace __read_mostly = | |||
| 225 | .init = function_trace_init, | 225 | .init = function_trace_init, |
| 226 | .reset = function_trace_reset, | 226 | .reset = function_trace_reset, |
| 227 | .start = function_trace_start, | 227 | .start = function_trace_start, |
| 228 | .wait_pipe = poll_wait_pipe, | ||
| 228 | .flags = &func_flags, | 229 | .flags = &func_flags, |
| 229 | .set_flag = func_set_flag, | 230 | .set_flag = func_set_flag, |
| 230 | #ifdef CONFIG_FTRACE_SELFTEST | 231 | #ifdef CONFIG_FTRACE_SELFTEST |
| @@ -269,21 +270,21 @@ ftrace_traceoff(unsigned long ip, unsigned long parent_ip, void **data) | |||
| 269 | 270 | ||
| 270 | static int | 271 | static int |
| 271 | ftrace_trace_onoff_print(struct seq_file *m, unsigned long ip, | 272 | ftrace_trace_onoff_print(struct seq_file *m, unsigned long ip, |
| 272 | struct ftrace_hook_ops *ops, void *data); | 273 | struct ftrace_probe_ops *ops, void *data); |
| 273 | 274 | ||
| 274 | static struct ftrace_hook_ops traceon_hook_ops = { | 275 | static struct ftrace_probe_ops traceon_probe_ops = { |
| 275 | .func = ftrace_traceon, | 276 | .func = ftrace_traceon, |
| 276 | .print = ftrace_trace_onoff_print, | 277 | .print = ftrace_trace_onoff_print, |
| 277 | }; | 278 | }; |
| 278 | 279 | ||
| 279 | static struct ftrace_hook_ops traceoff_hook_ops = { | 280 | static struct ftrace_probe_ops traceoff_probe_ops = { |
| 280 | .func = ftrace_traceoff, | 281 | .func = ftrace_traceoff, |
| 281 | .print = ftrace_trace_onoff_print, | 282 | .print = ftrace_trace_onoff_print, |
| 282 | }; | 283 | }; |
| 283 | 284 | ||
| 284 | static int | 285 | static int |
| 285 | ftrace_trace_onoff_print(struct seq_file *m, unsigned long ip, | 286 | ftrace_trace_onoff_print(struct seq_file *m, unsigned long ip, |
| 286 | struct ftrace_hook_ops *ops, void *data) | 287 | struct ftrace_probe_ops *ops, void *data) |
| 287 | { | 288 | { |
| 288 | char str[KSYM_SYMBOL_LEN]; | 289 | char str[KSYM_SYMBOL_LEN]; |
| 289 | long count = (long)data; | 290 | long count = (long)data; |
| @@ -291,12 +292,14 @@ ftrace_trace_onoff_print(struct seq_file *m, unsigned long ip, | |||
| 291 | kallsyms_lookup(ip, NULL, NULL, NULL, str); | 292 | kallsyms_lookup(ip, NULL, NULL, NULL, str); |
| 292 | seq_printf(m, "%s:", str); | 293 | seq_printf(m, "%s:", str); |
| 293 | 294 | ||
| 294 | if (ops == &traceon_hook_ops) | 295 | if (ops == &traceon_probe_ops) |
| 295 | seq_printf(m, "traceon"); | 296 | seq_printf(m, "traceon"); |
| 296 | else | 297 | else |
| 297 | seq_printf(m, "traceoff"); | 298 | seq_printf(m, "traceoff"); |
| 298 | 299 | ||
| 299 | if (count != -1) | 300 | if (count == -1) |
| 301 | seq_printf(m, ":unlimited\n"); | ||
| 302 | else | ||
| 300 | seq_printf(m, ":count=%ld", count); | 303 | seq_printf(m, ":count=%ld", count); |
| 301 | seq_putc(m, '\n'); | 304 | seq_putc(m, '\n'); |
| 302 | 305 | ||
| @@ -306,15 +309,15 @@ ftrace_trace_onoff_print(struct seq_file *m, unsigned long ip, | |||
| 306 | static int | 309 | static int |
| 307 | ftrace_trace_onoff_unreg(char *glob, char *cmd, char *param) | 310 | ftrace_trace_onoff_unreg(char *glob, char *cmd, char *param) |
| 308 | { | 311 | { |
| 309 | struct ftrace_hook_ops *ops; | 312 | struct ftrace_probe_ops *ops; |
| 310 | 313 | ||
| 311 | /* we register both traceon and traceoff to this callback */ | 314 | /* we register both traceon and traceoff to this callback */ |
| 312 | if (strcmp(cmd, "traceon") == 0) | 315 | if (strcmp(cmd, "traceon") == 0) |
| 313 | ops = &traceon_hook_ops; | 316 | ops = &traceon_probe_ops; |
| 314 | else | 317 | else |
| 315 | ops = &traceoff_hook_ops; | 318 | ops = &traceoff_probe_ops; |
| 316 | 319 | ||
| 317 | unregister_ftrace_function_hook_func(glob, ops); | 320 | unregister_ftrace_function_probe_func(glob, ops); |
| 318 | 321 | ||
| 319 | return 0; | 322 | return 0; |
| 320 | } | 323 | } |
| @@ -322,7 +325,7 @@ ftrace_trace_onoff_unreg(char *glob, char *cmd, char *param) | |||
| 322 | static int | 325 | static int |
| 323 | ftrace_trace_onoff_callback(char *glob, char *cmd, char *param, int enable) | 326 | ftrace_trace_onoff_callback(char *glob, char *cmd, char *param, int enable) |
| 324 | { | 327 | { |
| 325 | struct ftrace_hook_ops *ops; | 328 | struct ftrace_probe_ops *ops; |
| 326 | void *count = (void *)-1; | 329 | void *count = (void *)-1; |
| 327 | char *number; | 330 | char *number; |
| 328 | int ret; | 331 | int ret; |
| @@ -336,9 +339,9 @@ ftrace_trace_onoff_callback(char *glob, char *cmd, char *param, int enable) | |||
| 336 | 339 | ||
| 337 | /* we register both traceon and traceoff to this callback */ | 340 | /* we register both traceon and traceoff to this callback */ |
| 338 | if (strcmp(cmd, "traceon") == 0) | 341 | if (strcmp(cmd, "traceon") == 0) |
| 339 | ops = &traceon_hook_ops; | 342 | ops = &traceon_probe_ops; |
| 340 | else | 343 | else |
| 341 | ops = &traceoff_hook_ops; | 344 | ops = &traceoff_probe_ops; |
| 342 | 345 | ||
| 343 | if (!param) | 346 | if (!param) |
| 344 | goto out_reg; | 347 | goto out_reg; |
| @@ -357,7 +360,7 @@ ftrace_trace_onoff_callback(char *glob, char *cmd, char *param, int enable) | |||
| 357 | return ret; | 360 | return ret; |
| 358 | 361 | ||
| 359 | out_reg: | 362 | out_reg: |
| 360 | ret = register_ftrace_function_hook(glob, ops, count); | 363 | ret = register_ftrace_function_probe(glob, ops, count); |
| 361 | 364 | ||
| 362 | return ret; | 365 | return ret; |
| 363 | } | 366 | } |
| @@ -397,6 +400,5 @@ static __init int init_function_trace(void) | |||
| 397 | init_func_cmd_traceon(); | 400 | init_func_cmd_traceon(); |
| 398 | return register_tracer(&function_trace); | 401 | return register_tracer(&function_trace); |
| 399 | } | 402 | } |
| 400 | |||
| 401 | device_initcall(init_function_trace); | 403 | device_initcall(init_function_trace); |
| 402 | 404 | ||
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index 519a0cab1530..0ff5cb661900 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c | |||
| @@ -757,6 +757,7 @@ static struct tracer graph_trace __read_mostly = { | |||
| 757 | .name = "function_graph", | 757 | .name = "function_graph", |
| 758 | .open = graph_trace_open, | 758 | .open = graph_trace_open, |
| 759 | .close = graph_trace_close, | 759 | .close = graph_trace_close, |
| 760 | .wait_pipe = poll_wait_pipe, | ||
| 760 | .init = graph_trace_init, | 761 | .init = graph_trace_init, |
| 761 | .reset = graph_trace_reset, | 762 | .reset = graph_trace_reset, |
| 762 | .print_line = print_graph_function, | 763 | .print_line = print_graph_function, |
diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c index c6b442d88de8..9e5ebd844158 100644 --- a/kernel/trace/trace_irqsoff.c +++ b/kernel/trace/trace_irqsoff.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * trace irqs off criticall timings | 2 | * trace irqs off critical timings |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com> | 4 | * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com> |
| 5 | * Copyright (C) 2008 Ingo Molnar <mingo@redhat.com> | 5 | * Copyright (C) 2008 Ingo Molnar <mingo@redhat.com> |
diff --git a/kernel/trace/trace_sched_switch.c b/kernel/trace/trace_sched_switch.c index 30e14fe85896..77132c2cf3d9 100644 --- a/kernel/trace/trace_sched_switch.c +++ b/kernel/trace/trace_sched_switch.c | |||
| @@ -93,7 +93,7 @@ static int tracing_sched_register(void) | |||
| 93 | ret = register_trace_sched_switch(probe_sched_switch); | 93 | ret = register_trace_sched_switch(probe_sched_switch); |
| 94 | if (ret) { | 94 | if (ret) { |
| 95 | pr_info("sched trace: Couldn't activate tracepoint" | 95 | pr_info("sched trace: Couldn't activate tracepoint" |
| 96 | " probe to kernel_sched_schedule\n"); | 96 | " probe to kernel_sched_switch\n"); |
| 97 | goto fail_deprobe_wake_new; | 97 | goto fail_deprobe_wake_new; |
| 98 | } | 98 | } |
| 99 | 99 | ||
| @@ -221,6 +221,7 @@ static struct tracer sched_switch_trace __read_mostly = | |||
| 221 | .reset = sched_switch_trace_reset, | 221 | .reset = sched_switch_trace_reset, |
| 222 | .start = sched_switch_trace_start, | 222 | .start = sched_switch_trace_start, |
| 223 | .stop = sched_switch_trace_stop, | 223 | .stop = sched_switch_trace_stop, |
| 224 | .wait_pipe = poll_wait_pipe, | ||
| 224 | #ifdef CONFIG_FTRACE_SELFTEST | 225 | #ifdef CONFIG_FTRACE_SELFTEST |
| 225 | .selftest = trace_selftest_startup_sched_switch, | 226 | .selftest = trace_selftest_startup_sched_switch, |
| 226 | #endif | 227 | #endif |
diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c index 96d716485898..db55f7aaa640 100644 --- a/kernel/trace/trace_sched_wakeup.c +++ b/kernel/trace/trace_sched_wakeup.c | |||
| @@ -284,7 +284,7 @@ static void start_wakeup_tracer(struct trace_array *tr) | |||
| 284 | ret = register_trace_sched_switch(probe_wakeup_sched_switch); | 284 | ret = register_trace_sched_switch(probe_wakeup_sched_switch); |
| 285 | if (ret) { | 285 | if (ret) { |
| 286 | pr_info("sched trace: Couldn't activate tracepoint" | 286 | pr_info("sched trace: Couldn't activate tracepoint" |
| 287 | " probe to kernel_sched_schedule\n"); | 287 | " probe to kernel_sched_switch\n"); |
| 288 | goto fail_deprobe_wake_new; | 288 | goto fail_deprobe_wake_new; |
| 289 | } | 289 | } |
| 290 | 290 | ||
| @@ -380,6 +380,7 @@ static struct tracer wakeup_rt_tracer __read_mostly = | |||
| 380 | .reset = wakeup_tracer_reset, | 380 | .reset = wakeup_tracer_reset, |
| 381 | .start = wakeup_tracer_start, | 381 | .start = wakeup_tracer_start, |
| 382 | .stop = wakeup_tracer_stop, | 382 | .stop = wakeup_tracer_stop, |
| 383 | .wait_pipe = poll_wait_pipe, | ||
| 383 | .print_max = 1, | 384 | .print_max = 1, |
| 384 | #ifdef CONFIG_FTRACE_SELFTEST | 385 | #ifdef CONFIG_FTRACE_SELFTEST |
| 385 | .selftest = trace_selftest_startup_wakeup, | 386 | .selftest = trace_selftest_startup_wakeup, |
diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c index 0c9aa1457e51..7238646b8723 100644 --- a/kernel/trace/trace_selftest.c +++ b/kernel/trace/trace_selftest.c | |||
| @@ -24,10 +24,20 @@ static int trace_test_buffer_cpu(struct trace_array *tr, int cpu) | |||
| 24 | { | 24 | { |
| 25 | struct ring_buffer_event *event; | 25 | struct ring_buffer_event *event; |
| 26 | struct trace_entry *entry; | 26 | struct trace_entry *entry; |
| 27 | unsigned int loops = 0; | ||
| 27 | 28 | ||
| 28 | while ((event = ring_buffer_consume(tr->buffer, cpu, NULL))) { | 29 | while ((event = ring_buffer_consume(tr->buffer, cpu, NULL))) { |
| 29 | entry = ring_buffer_event_data(event); | 30 | entry = ring_buffer_event_data(event); |
| 30 | 31 | ||
| 32 | /* | ||
| 33 | * The ring buffer is a size of trace_buf_size, if | ||
| 34 | * we loop more than the size, there's something wrong | ||
| 35 | * with the ring buffer. | ||
| 36 | */ | ||
| 37 | if (loops++ > trace_buf_size) { | ||
| 38 | printk(KERN_CONT ".. bad ring buffer "); | ||
| 39 | goto failed; | ||
| 40 | } | ||
| 31 | if (!trace_valid_entry(entry)) { | 41 | if (!trace_valid_entry(entry)) { |
| 32 | printk(KERN_CONT ".. invalid entry %d ", | 42 | printk(KERN_CONT ".. invalid entry %d ", |
| 33 | entry->type); | 43 | entry->type); |
| @@ -58,11 +68,20 @@ static int trace_test_buffer(struct trace_array *tr, unsigned long *count) | |||
| 58 | 68 | ||
| 59 | cnt = ring_buffer_entries(tr->buffer); | 69 | cnt = ring_buffer_entries(tr->buffer); |
| 60 | 70 | ||
| 71 | /* | ||
| 72 | * The trace_test_buffer_cpu runs a while loop to consume all data. | ||
| 73 | * If the calling tracer is broken, and is constantly filling | ||
| 74 | * the buffer, this will run forever, and hard lock the box. | ||
| 75 | * We disable the ring buffer while we do this test to prevent | ||
| 76 | * a hard lock up. | ||
| 77 | */ | ||
| 78 | tracing_off(); | ||
| 61 | for_each_possible_cpu(cpu) { | 79 | for_each_possible_cpu(cpu) { |
| 62 | ret = trace_test_buffer_cpu(tr, cpu); | 80 | ret = trace_test_buffer_cpu(tr, cpu); |
| 63 | if (ret) | 81 | if (ret) |
| 64 | break; | 82 | break; |
| 65 | } | 83 | } |
| 84 | tracing_on(); | ||
| 66 | __raw_spin_unlock(&ftrace_max_lock); | 85 | __raw_spin_unlock(&ftrace_max_lock); |
| 67 | local_irq_restore(flags); | 86 | local_irq_restore(flags); |
| 68 | 87 | ||
| @@ -107,9 +126,9 @@ int trace_selftest_startup_dynamic_tracing(struct tracer *trace, | |||
| 107 | func(); | 126 | func(); |
| 108 | 127 | ||
| 109 | /* | 128 | /* |
| 110 | * Some archs *cough*PowerPC*cough* add charachters to the | 129 | * Some archs *cough*PowerPC*cough* add characters to the |
| 111 | * start of the function names. We simply put a '*' to | 130 | * start of the function names. We simply put a '*' to |
| 112 | * accomodate them. | 131 | * accommodate them. |
| 113 | */ | 132 | */ |
| 114 | func_name = "*" STR(DYN_FTRACE_TEST_NAME); | 133 | func_name = "*" STR(DYN_FTRACE_TEST_NAME); |
| 115 | 134 | ||
| @@ -622,7 +641,7 @@ trace_selftest_startup_sysprof(struct tracer *trace, struct trace_array *tr) | |||
| 622 | ret = tracer_init(trace, tr); | 641 | ret = tracer_init(trace, tr); |
| 623 | if (ret) { | 642 | if (ret) { |
| 624 | warn_failed_init_tracer(trace, ret); | 643 | warn_failed_init_tracer(trace, ret); |
| 625 | return 0; | 644 | return ret; |
| 626 | } | 645 | } |
| 627 | 646 | ||
| 628 | /* Sleep for a 1/10 of a second */ | 647 | /* Sleep for a 1/10 of a second */ |
| @@ -634,6 +653,11 @@ trace_selftest_startup_sysprof(struct tracer *trace, struct trace_array *tr) | |||
| 634 | trace->reset(tr); | 653 | trace->reset(tr); |
| 635 | tracing_start(); | 654 | tracing_start(); |
| 636 | 655 | ||
| 656 | if (!ret && !count) { | ||
| 657 | printk(KERN_CONT ".. no entries found .."); | ||
| 658 | ret = -1; | ||
| 659 | } | ||
| 660 | |||
| 637 | return ret; | 661 | return ret; |
| 638 | } | 662 | } |
| 639 | #endif /* CONFIG_SYSPROF_TRACER */ | 663 | #endif /* CONFIG_SYSPROF_TRACER */ |
| @@ -661,6 +685,11 @@ trace_selftest_startup_branch(struct tracer *trace, struct trace_array *tr) | |||
| 661 | trace->reset(tr); | 685 | trace->reset(tr); |
| 662 | tracing_start(); | 686 | tracing_start(); |
| 663 | 687 | ||
| 688 | if (!ret && !count) { | ||
| 689 | printk(KERN_CONT ".. no entries found .."); | ||
| 690 | ret = -1; | ||
| 691 | } | ||
| 692 | |||
| 664 | return ret; | 693 | return ret; |
| 665 | } | 694 | } |
| 666 | #endif /* CONFIG_BRANCH_TRACER */ | 695 | #endif /* CONFIG_BRANCH_TRACER */ |
diff --git a/kernel/trace/trace_stat.c b/kernel/trace/trace_stat.c index eae9cef39291..39310e3434ee 100644 --- a/kernel/trace/trace_stat.c +++ b/kernel/trace/trace_stat.c | |||
| @@ -30,7 +30,7 @@ struct tracer_stat_session { | |||
| 30 | struct dentry *file; | 30 | struct dentry *file; |
| 31 | }; | 31 | }; |
| 32 | 32 | ||
| 33 | /* All of the sessions currently in use. Each stat file embeed one session */ | 33 | /* All of the sessions currently in use. Each stat file embed one session */ |
| 34 | static LIST_HEAD(all_stat_sessions); | 34 | static LIST_HEAD(all_stat_sessions); |
| 35 | static DEFINE_MUTEX(all_stat_sessions_mutex); | 35 | static DEFINE_MUTEX(all_stat_sessions_mutex); |
| 36 | 36 | ||
diff --git a/kernel/trace/trace_sysprof.c b/kernel/trace/trace_sysprof.c index 7c9a2d82a7d8..c771af4e8f1a 100644 --- a/kernel/trace/trace_sysprof.c +++ b/kernel/trace/trace_sysprof.c | |||
| @@ -327,5 +327,5 @@ void init_tracer_sysprof_debugfs(struct dentry *d_tracer) | |||
| 327 | d_tracer, NULL, &sysprof_sample_fops); | 327 | d_tracer, NULL, &sysprof_sample_fops); |
| 328 | if (entry) | 328 | if (entry) |
| 329 | return; | 329 | return; |
| 330 | pr_warning("Could not create debugfs 'dyn_ftrace_total_info' entry\n"); | 330 | pr_warning("Could not create debugfs 'sysprof_sample_period' entry\n"); |
| 331 | } | 331 | } |
