Commit 8781915ad2716adcd8cd5cc52cee791fc8b00fdf

Authored by Ezequiel Garcia
Committed by Steven Rostedt
1 parent 5224c3a315

trace: Move trace event enable from fs_initcall to core_initcall

This patch splits trace event initialization in two stages:
 * ftrace enable
 * sysfs event entry creation

This allows to capture trace events from an earlier point
by using 'trace_event' kernel parameter and is important
to trace boot-up allocations.

Note that, in order to enable events at core_initcall,
it's necessary to move init_ftrace_syscalls() from
core_initcall to early_initcall.

Link: http://lkml.kernel.org/r/1347461277-25302-1-git-send-email-elezegarcia@gmail.com

Signed-off-by: Ezequiel Garcia <elezegarcia@gmail.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>

Showing 2 changed files with 73 additions and 37 deletions Side-by-side Diff

kernel/trace/trace_events.c
... ... @@ -1199,6 +1199,31 @@
1199 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 1227 static int
1203 1228 __trace_add_event_call(struct ftrace_event_call *call, struct module *mod,
1204 1229 const struct file_operations *id,
1205 1230  
... ... @@ -1209,20 +1234,10 @@
1209 1234 struct dentry *d_events;
1210 1235 int ret;
1211 1236  
1212   - /* The linker may leave blanks */
1213   - if (!call->name)
1214   - return -EINVAL;
  1237 + ret = event_init(call);
  1238 + if (ret < 0)
  1239 + return ret;
1215 1240  
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   -
1226 1241 d_events = event_trace_events_dir();
1227 1242 if (!d_events)
1228 1243 return -ENOENT;
1229 1244  
... ... @@ -1272,13 +1287,10 @@
1272 1287 */
1273 1288 static void __trace_remove_event_call(struct ftrace_event_call *call)
1274 1289 {
1275   - ftrace_event_enable_disable(call, 0);
1276   - if (call->event.funcs)
1277   - __unregister_ftrace_event(&call->event);
1278   - debugfs_remove_recursive(call->dir);
1279   - list_del(&call->list);
  1290 + event_remove(call);
1280 1291 trace_destroy_fields(call);
1281 1292 destroy_preds(call);
  1293 + debugfs_remove_recursive(call->dir);
1282 1294 remove_subsystem_dir(call->class->system);
1283 1295 }
1284 1296  
1285 1297  
1286 1298  
... ... @@ -1450,15 +1462,43 @@
1450 1462 }
1451 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 1495 static __init int event_trace_init(void)
1454 1496 {
1455   - struct ftrace_event_call **call;
  1497 + struct ftrace_event_call *call;
1456 1498 struct dentry *d_tracer;
1457 1499 struct dentry *entry;
1458 1500 struct dentry *d_events;
1459 1501 int ret;
1460   - char *buf = bootup_event_buf;
1461   - char *token;
1462 1502  
1463 1503 d_tracer = tracing_init_dentry();
1464 1504 if (!d_tracer)
1465 1505  
1466 1506  
1467 1507  
... ... @@ -1497,32 +1537,28 @@
1497 1537 if (trace_define_common_fields())
1498 1538 pr_warning("tracing: Failed to allocate common fields");
1499 1539  
1500   - for_each_event(call, __start_ftrace_events, __stop_ftrace_events) {
1501   - __trace_add_event_call(*call, NULL, &ftrace_event_id_fops,
  1540 + /*
  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 1548 &ftrace_enable_fops,
1503 1549 &ftrace_event_filter_fops,
1504 1550 &ftrace_event_format_fops);
  1551 + if (ret < 0)
  1552 + event_remove(call);
1505 1553 }
1506 1554  
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   - }
1519   -
1520 1555 ret = register_module_notifier(&trace_module_nb);
1521 1556 if (ret)
1522 1557 pr_warning("Failed to register trace events module notifier\n");
1523 1558  
1524 1559 return 0;
1525 1560 }
  1561 +core_initcall(event_trace_enable);
1526 1562 fs_initcall(event_trace_init);
1527 1563  
1528 1564 #ifdef CONFIG_FTRACE_STARTUP_TEST
kernel/trace/trace_syscalls.c
... ... @@ -487,7 +487,7 @@
487 487  
488 488 return 0;
489 489 }
490   -core_initcall(init_ftrace_syscalls);
  490 +early_initcall(init_ftrace_syscalls);
491 491  
492 492 #ifdef CONFIG_PERF_EVENTS
493 493