diff options
| -rw-r--r-- | kernel/trace/trace_events.c | 108 | ||||
| -rw-r--r-- | kernel/trace/trace_syscalls.c | 2 |
2 files changed, 73 insertions, 37 deletions
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index bbb0e63d78e9..d608d09d08c0 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
| @@ -1199,6 +1199,31 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events, | |||
| 1199 | return 0; | 1199 | return 0; |
| 1200 | } | 1200 | } |
| 1201 | 1201 | ||
| 1202 | static void event_remove(struct ftrace_event_call *call) | ||
| 1203 | { | ||
| 1204 | ftrace_event_enable_disable(call, 0); | ||
| 1205 | if (call->event.funcs) | ||
| 1206 | __unregister_ftrace_event(&call->event); | ||
| 1207 | list_del(&call->list); | ||
| 1208 | } | ||
| 1209 | |||
| 1210 | static int event_init(struct ftrace_event_call *call) | ||
| 1211 | { | ||
| 1212 | int ret = 0; | ||
| 1213 | |||
| 1214 | if (WARN_ON(!call->name)) | ||
| 1215 | return -EINVAL; | ||
| 1216 | |||
| 1217 | if (call->class->raw_init) { | ||
| 1218 | ret = call->class->raw_init(call); | ||
| 1219 | if (ret < 0 && ret != -ENOSYS) | ||
| 1220 | pr_warn("Could not initialize trace events/%s\n", | ||
| 1221 | call->name); | ||
| 1222 | } | ||
| 1223 | |||
| 1224 | return ret; | ||
| 1225 | } | ||
| 1226 | |||
| 1202 | static int | 1227 | static int |
| 1203 | __trace_add_event_call(struct ftrace_event_call *call, struct module *mod, | 1228 | __trace_add_event_call(struct ftrace_event_call *call, struct module *mod, |
| 1204 | const struct file_operations *id, | 1229 | const struct file_operations *id, |
| @@ -1209,19 +1234,9 @@ __trace_add_event_call(struct ftrace_event_call *call, struct module *mod, | |||
| 1209 | struct dentry *d_events; | 1234 | struct dentry *d_events; |
| 1210 | int ret; | 1235 | int ret; |
| 1211 | 1236 | ||
| 1212 | /* The linker may leave blanks */ | 1237 | ret = event_init(call); |
| 1213 | if (!call->name) | 1238 | if (ret < 0) |
| 1214 | return -EINVAL; | 1239 | return ret; |
| 1215 | |||
| 1216 | if (call->class->raw_init) { | ||
| 1217 | ret = call->class->raw_init(call); | ||
| 1218 | if (ret < 0) { | ||
| 1219 | if (ret != -ENOSYS) | ||
| 1220 | pr_warning("Could not initialize trace events/%s\n", | ||
| 1221 | call->name); | ||
| 1222 | return ret; | ||
| 1223 | } | ||
| 1224 | } | ||
| 1225 | 1240 | ||
| 1226 | d_events = event_trace_events_dir(); | 1241 | d_events = event_trace_events_dir(); |
| 1227 | if (!d_events) | 1242 | if (!d_events) |
| @@ -1272,13 +1287,10 @@ static void remove_subsystem_dir(const char *name) | |||
| 1272 | */ | 1287 | */ |
| 1273 | static void __trace_remove_event_call(struct ftrace_event_call *call) | 1288 | static void __trace_remove_event_call(struct ftrace_event_call *call) |
| 1274 | { | 1289 | { |
| 1275 | ftrace_event_enable_disable(call, 0); | 1290 | event_remove(call); |
| 1276 | if (call->event.funcs) | ||
| 1277 | __unregister_ftrace_event(&call->event); | ||
| 1278 | debugfs_remove_recursive(call->dir); | ||
| 1279 | list_del(&call->list); | ||
| 1280 | trace_destroy_fields(call); | 1291 | trace_destroy_fields(call); |
| 1281 | destroy_preds(call); | 1292 | destroy_preds(call); |
| 1293 | debugfs_remove_recursive(call->dir); | ||
| 1282 | remove_subsystem_dir(call->class->system); | 1294 | remove_subsystem_dir(call->class->system); |
| 1283 | } | 1295 | } |
| 1284 | 1296 | ||
| @@ -1450,15 +1462,43 @@ static __init int setup_trace_event(char *str) | |||
| 1450 | } | 1462 | } |
| 1451 | __setup("trace_event=", setup_trace_event); | 1463 | __setup("trace_event=", setup_trace_event); |
| 1452 | 1464 | ||
| 1465 | static __init int event_trace_enable(void) | ||
| 1466 | { | ||
| 1467 | struct ftrace_event_call **iter, *call; | ||
| 1468 | char *buf = bootup_event_buf; | ||
| 1469 | char *token; | ||
| 1470 | int ret; | ||
| 1471 | |||
| 1472 | for_each_event(iter, __start_ftrace_events, __stop_ftrace_events) { | ||
| 1473 | |||
| 1474 | call = *iter; | ||
| 1475 | ret = event_init(call); | ||
| 1476 | if (!ret) | ||
| 1477 | list_add(&call->list, &ftrace_events); | ||
| 1478 | } | ||
| 1479 | |||
| 1480 | while (true) { | ||
| 1481 | token = strsep(&buf, ","); | ||
| 1482 | |||
| 1483 | if (!token) | ||
| 1484 | break; | ||
| 1485 | if (!*token) | ||
| 1486 | continue; | ||
| 1487 | |||
| 1488 | ret = ftrace_set_clr_event(token, 1); | ||
| 1489 | if (ret) | ||
| 1490 | pr_warn("Failed to enable trace event: %s\n", token); | ||
| 1491 | } | ||
| 1492 | return 0; | ||
| 1493 | } | ||
| 1494 | |||
| 1453 | static __init int event_trace_init(void) | 1495 | static __init int event_trace_init(void) |
| 1454 | { | 1496 | { |
| 1455 | struct ftrace_event_call **call; | 1497 | struct ftrace_event_call *call; |
| 1456 | struct dentry *d_tracer; | 1498 | struct dentry *d_tracer; |
| 1457 | struct dentry *entry; | 1499 | struct dentry *entry; |
| 1458 | struct dentry *d_events; | 1500 | struct dentry *d_events; |
| 1459 | int ret; | 1501 | int ret; |
| 1460 | char *buf = bootup_event_buf; | ||
| 1461 | char *token; | ||
| 1462 | 1502 | ||
| 1463 | d_tracer = tracing_init_dentry(); | 1503 | d_tracer = tracing_init_dentry(); |
| 1464 | if (!d_tracer) | 1504 | if (!d_tracer) |
| @@ -1497,24 +1537,19 @@ static __init int event_trace_init(void) | |||
| 1497 | if (trace_define_common_fields()) | 1537 | if (trace_define_common_fields()) |
| 1498 | pr_warning("tracing: Failed to allocate common fields"); | 1538 | pr_warning("tracing: Failed to allocate common fields"); |
| 1499 | 1539 | ||
| 1500 | for_each_event(call, __start_ftrace_events, __stop_ftrace_events) { | 1540 | /* |
| 1501 | __trace_add_event_call(*call, NULL, &ftrace_event_id_fops, | 1541 | * Early initialization already enabled ftrace event. |
| 1542 | * Now it's only necessary to create the event directory. | ||
| 1543 | */ | ||
| 1544 | list_for_each_entry(call, &ftrace_events, list) { | ||
| 1545 | |||
| 1546 | ret = event_create_dir(call, d_events, | ||
| 1547 | &ftrace_event_id_fops, | ||
| 1502 | &ftrace_enable_fops, | 1548 | &ftrace_enable_fops, |
| 1503 | &ftrace_event_filter_fops, | 1549 | &ftrace_event_filter_fops, |
| 1504 | &ftrace_event_format_fops); | 1550 | &ftrace_event_format_fops); |
| 1505 | } | 1551 | if (ret < 0) |
| 1506 | 1552 | event_remove(call); | |
| 1507 | while (true) { | ||
| 1508 | token = strsep(&buf, ","); | ||
| 1509 | |||
| 1510 | if (!token) | ||
| 1511 | break; | ||
| 1512 | if (!*token) | ||
| 1513 | continue; | ||
| 1514 | |||
| 1515 | ret = ftrace_set_clr_event(token, 1); | ||
| 1516 | if (ret) | ||
| 1517 | pr_warning("Failed to enable trace event: %s\n", token); | ||
| 1518 | } | 1553 | } |
| 1519 | 1554 | ||
| 1520 | ret = register_module_notifier(&trace_module_nb); | 1555 | ret = register_module_notifier(&trace_module_nb); |
| @@ -1523,6 +1558,7 @@ static __init int event_trace_init(void) | |||
| 1523 | 1558 | ||
| 1524 | return 0; | 1559 | return 0; |
| 1525 | } | 1560 | } |
| 1561 | core_initcall(event_trace_enable); | ||
| 1526 | fs_initcall(event_trace_init); | 1562 | fs_initcall(event_trace_init); |
| 1527 | 1563 | ||
| 1528 | #ifdef CONFIG_FTRACE_STARTUP_TEST | 1564 | #ifdef CONFIG_FTRACE_STARTUP_TEST |
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index 6b245f64c8dd..2485a7d09b11 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c | |||
| @@ -487,7 +487,7 @@ int __init init_ftrace_syscalls(void) | |||
| 487 | 487 | ||
| 488 | return 0; | 488 | return 0; |
| 489 | } | 489 | } |
| 490 | core_initcall(init_ftrace_syscalls); | 490 | early_initcall(init_ftrace_syscalls); |
| 491 | 491 | ||
| 492 | #ifdef CONFIG_PERF_EVENTS | 492 | #ifdef CONFIG_PERF_EVENTS |
| 493 | 493 | ||
