diff options
Diffstat (limited to 'kernel/trace/trace_events.c')
-rw-r--r-- | kernel/trace/trace_events.c | 184 |
1 files changed, 62 insertions, 122 deletions
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 880073d0b94..c212a7f934e 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
@@ -147,8 +147,7 @@ int trace_event_raw_init(struct ftrace_event_call *call) | |||
147 | } | 147 | } |
148 | EXPORT_SYMBOL_GPL(trace_event_raw_init); | 148 | EXPORT_SYMBOL_GPL(trace_event_raw_init); |
149 | 149 | ||
150 | int ftrace_event_reg(struct ftrace_event_call *call, | 150 | int ftrace_event_reg(struct ftrace_event_call *call, enum trace_reg type) |
151 | enum trace_reg type, void *data) | ||
152 | { | 151 | { |
153 | switch (type) { | 152 | switch (type) { |
154 | case TRACE_REG_REGISTER: | 153 | case TRACE_REG_REGISTER: |
@@ -171,11 +170,6 @@ int ftrace_event_reg(struct ftrace_event_call *call, | |||
171 | call->class->perf_probe, | 170 | call->class->perf_probe, |
172 | call); | 171 | call); |
173 | return 0; | 172 | return 0; |
174 | case TRACE_REG_PERF_OPEN: | ||
175 | case TRACE_REG_PERF_CLOSE: | ||
176 | case TRACE_REG_PERF_ADD: | ||
177 | case TRACE_REG_PERF_DEL: | ||
178 | return 0; | ||
179 | #endif | 173 | #endif |
180 | } | 174 | } |
181 | return 0; | 175 | return 0; |
@@ -215,7 +209,7 @@ static int ftrace_event_enable_disable(struct ftrace_event_call *call, | |||
215 | tracing_stop_cmdline_record(); | 209 | tracing_stop_cmdline_record(); |
216 | call->flags &= ~TRACE_EVENT_FL_RECORDED_CMD; | 210 | call->flags &= ~TRACE_EVENT_FL_RECORDED_CMD; |
217 | } | 211 | } |
218 | call->class->reg(call, TRACE_REG_UNREGISTER, NULL); | 212 | call->class->reg(call, TRACE_REG_UNREGISTER); |
219 | } | 213 | } |
220 | break; | 214 | break; |
221 | case 1: | 215 | case 1: |
@@ -224,7 +218,7 @@ static int ftrace_event_enable_disable(struct ftrace_event_call *call, | |||
224 | tracing_start_cmdline_record(); | 218 | tracing_start_cmdline_record(); |
225 | call->flags |= TRACE_EVENT_FL_RECORDED_CMD; | 219 | call->flags |= TRACE_EVENT_FL_RECORDED_CMD; |
226 | } | 220 | } |
227 | ret = call->class->reg(call, TRACE_REG_REGISTER, NULL); | 221 | ret = call->class->reg(call, TRACE_REG_REGISTER); |
228 | if (ret) { | 222 | if (ret) { |
229 | tracing_stop_cmdline_record(); | 223 | tracing_stop_cmdline_record(); |
230 | pr_info("event trace: Could not enable event " | 224 | pr_info("event trace: Could not enable event " |
@@ -294,9 +288,6 @@ static int __ftrace_set_clr_event(const char *match, const char *sub, | |||
294 | if (!call->name || !call->class || !call->class->reg) | 288 | if (!call->name || !call->class || !call->class->reg) |
295 | continue; | 289 | continue; |
296 | 290 | ||
297 | if (call->flags & TRACE_EVENT_FL_IGNORE_ENABLE) | ||
298 | continue; | ||
299 | |||
300 | if (match && | 291 | if (match && |
301 | strcmp(match, call->name) != 0 && | 292 | strcmp(match, call->name) != 0 && |
302 | strcmp(match, call->class->system) != 0) | 293 | strcmp(match, call->class->system) != 0) |
@@ -491,6 +482,19 @@ static void t_stop(struct seq_file *m, void *p) | |||
491 | mutex_unlock(&event_mutex); | 482 | mutex_unlock(&event_mutex); |
492 | } | 483 | } |
493 | 484 | ||
485 | static int | ||
486 | ftrace_event_seq_open(struct inode *inode, struct file *file) | ||
487 | { | ||
488 | const struct seq_operations *seq_ops; | ||
489 | |||
490 | if ((file->f_mode & FMODE_WRITE) && | ||
491 | (file->f_flags & O_TRUNC)) | ||
492 | ftrace_clear_events(); | ||
493 | |||
494 | seq_ops = inode->i_private; | ||
495 | return seq_open(file, seq_ops); | ||
496 | } | ||
497 | |||
494 | static ssize_t | 498 | static ssize_t |
495 | event_enable_read(struct file *filp, char __user *ubuf, size_t cnt, | 499 | event_enable_read(struct file *filp, char __user *ubuf, size_t cnt, |
496 | loff_t *ppos) | 500 | loff_t *ppos) |
@@ -967,9 +971,6 @@ show_header(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) | |||
967 | return r; | 971 | return r; |
968 | } | 972 | } |
969 | 973 | ||
970 | static int ftrace_event_avail_open(struct inode *inode, struct file *file); | ||
971 | static int ftrace_event_set_open(struct inode *inode, struct file *file); | ||
972 | |||
973 | static const struct seq_operations show_event_seq_ops = { | 974 | static const struct seq_operations show_event_seq_ops = { |
974 | .start = t_start, | 975 | .start = t_start, |
975 | .next = t_next, | 976 | .next = t_next, |
@@ -985,14 +986,14 @@ static const struct seq_operations show_set_event_seq_ops = { | |||
985 | }; | 986 | }; |
986 | 987 | ||
987 | static const struct file_operations ftrace_avail_fops = { | 988 | static const struct file_operations ftrace_avail_fops = { |
988 | .open = ftrace_event_avail_open, | 989 | .open = ftrace_event_seq_open, |
989 | .read = seq_read, | 990 | .read = seq_read, |
990 | .llseek = seq_lseek, | 991 | .llseek = seq_lseek, |
991 | .release = seq_release, | 992 | .release = seq_release, |
992 | }; | 993 | }; |
993 | 994 | ||
994 | static const struct file_operations ftrace_set_event_fops = { | 995 | static const struct file_operations ftrace_set_event_fops = { |
995 | .open = ftrace_event_set_open, | 996 | .open = ftrace_event_seq_open, |
996 | .read = seq_read, | 997 | .read = seq_read, |
997 | .write = ftrace_event_write, | 998 | .write = ftrace_event_write, |
998 | .llseek = seq_lseek, | 999 | .llseek = seq_lseek, |
@@ -1068,26 +1069,6 @@ static struct dentry *event_trace_events_dir(void) | |||
1068 | return d_events; | 1069 | return d_events; |
1069 | } | 1070 | } |
1070 | 1071 | ||
1071 | static int | ||
1072 | ftrace_event_avail_open(struct inode *inode, struct file *file) | ||
1073 | { | ||
1074 | const struct seq_operations *seq_ops = &show_event_seq_ops; | ||
1075 | |||
1076 | return seq_open(file, seq_ops); | ||
1077 | } | ||
1078 | |||
1079 | static int | ||
1080 | ftrace_event_set_open(struct inode *inode, struct file *file) | ||
1081 | { | ||
1082 | const struct seq_operations *seq_ops = &show_set_event_seq_ops; | ||
1083 | |||
1084 | if ((file->f_mode & FMODE_WRITE) && | ||
1085 | (file->f_flags & O_TRUNC)) | ||
1086 | ftrace_clear_events(); | ||
1087 | |||
1088 | return seq_open(file, seq_ops); | ||
1089 | } | ||
1090 | |||
1091 | static struct dentry * | 1072 | static struct dentry * |
1092 | event_subsystem_dir(const char *name, struct dentry *d_events) | 1073 | event_subsystem_dir(const char *name, struct dentry *d_events) |
1093 | { | 1074 | { |
@@ -1177,7 +1158,7 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events, | |||
1177 | return -1; | 1158 | return -1; |
1178 | } | 1159 | } |
1179 | 1160 | ||
1180 | if (call->class->reg && !(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE)) | 1161 | if (call->class->reg) |
1181 | trace_create_file("enable", 0644, call->dir, call, | 1162 | trace_create_file("enable", 0644, call->dir, call, |
1182 | enable); | 1163 | enable); |
1183 | 1164 | ||
@@ -1209,31 +1190,6 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events, | |||
1209 | return 0; | 1190 | return 0; |
1210 | } | 1191 | } |
1211 | 1192 | ||
1212 | static void event_remove(struct ftrace_event_call *call) | ||
1213 | { | ||
1214 | ftrace_event_enable_disable(call, 0); | ||
1215 | if (call->event.funcs) | ||
1216 | __unregister_ftrace_event(&call->event); | ||
1217 | list_del(&call->list); | ||
1218 | } | ||
1219 | |||
1220 | static int event_init(struct ftrace_event_call *call) | ||
1221 | { | ||
1222 | int ret = 0; | ||
1223 | |||
1224 | if (WARN_ON(!call->name)) | ||
1225 | return -EINVAL; | ||
1226 | |||
1227 | if (call->class->raw_init) { | ||
1228 | ret = call->class->raw_init(call); | ||
1229 | if (ret < 0 && ret != -ENOSYS) | ||
1230 | pr_warn("Could not initialize trace events/%s\n", | ||
1231 | call->name); | ||
1232 | } | ||
1233 | |||
1234 | return ret; | ||
1235 | } | ||
1236 | |||
1237 | static int | 1193 | static int |
1238 | __trace_add_event_call(struct ftrace_event_call *call, struct module *mod, | 1194 | __trace_add_event_call(struct ftrace_event_call *call, struct module *mod, |
1239 | const struct file_operations *id, | 1195 | const struct file_operations *id, |
@@ -1244,9 +1200,19 @@ __trace_add_event_call(struct ftrace_event_call *call, struct module *mod, | |||
1244 | struct dentry *d_events; | 1200 | struct dentry *d_events; |
1245 | int ret; | 1201 | int ret; |
1246 | 1202 | ||
1247 | ret = event_init(call); | 1203 | /* The linker may leave blanks */ |
1248 | if (ret < 0) | 1204 | if (!call->name) |
1249 | return ret; | 1205 | return -EINVAL; |
1206 | |||
1207 | if (call->class->raw_init) { | ||
1208 | ret = call->class->raw_init(call); | ||
1209 | if (ret < 0) { | ||
1210 | if (ret != -ENOSYS) | ||
1211 | pr_warning("Could not initialize trace events/%s\n", | ||
1212 | call->name); | ||
1213 | return ret; | ||
1214 | } | ||
1215 | } | ||
1250 | 1216 | ||
1251 | d_events = event_trace_events_dir(); | 1217 | d_events = event_trace_events_dir(); |
1252 | if (!d_events) | 1218 | if (!d_events) |
@@ -1297,10 +1263,13 @@ static void remove_subsystem_dir(const char *name) | |||
1297 | */ | 1263 | */ |
1298 | static void __trace_remove_event_call(struct ftrace_event_call *call) | 1264 | static void __trace_remove_event_call(struct ftrace_event_call *call) |
1299 | { | 1265 | { |
1300 | event_remove(call); | 1266 | ftrace_event_enable_disable(call, 0); |
1267 | if (call->event.funcs) | ||
1268 | __unregister_ftrace_event(&call->event); | ||
1269 | debugfs_remove_recursive(call->dir); | ||
1270 | list_del(&call->list); | ||
1301 | trace_destroy_fields(call); | 1271 | trace_destroy_fields(call); |
1302 | destroy_preds(call); | 1272 | destroy_preds(call); |
1303 | debugfs_remove_recursive(call->dir); | ||
1304 | remove_subsystem_dir(call->class->system); | 1273 | remove_subsystem_dir(call->class->system); |
1305 | } | 1274 | } |
1306 | 1275 | ||
@@ -1472,59 +1441,30 @@ static __init int setup_trace_event(char *str) | |||
1472 | } | 1441 | } |
1473 | __setup("trace_event=", setup_trace_event); | 1442 | __setup("trace_event=", setup_trace_event); |
1474 | 1443 | ||
1475 | static __init int event_trace_enable(void) | ||
1476 | { | ||
1477 | struct ftrace_event_call **iter, *call; | ||
1478 | char *buf = bootup_event_buf; | ||
1479 | char *token; | ||
1480 | int ret; | ||
1481 | |||
1482 | for_each_event(iter, __start_ftrace_events, __stop_ftrace_events) { | ||
1483 | |||
1484 | call = *iter; | ||
1485 | ret = event_init(call); | ||
1486 | if (!ret) | ||
1487 | list_add(&call->list, &ftrace_events); | ||
1488 | } | ||
1489 | |||
1490 | while (true) { | ||
1491 | token = strsep(&buf, ","); | ||
1492 | |||
1493 | if (!token) | ||
1494 | break; | ||
1495 | if (!*token) | ||
1496 | continue; | ||
1497 | |||
1498 | ret = ftrace_set_clr_event(token, 1); | ||
1499 | if (ret) | ||
1500 | pr_warn("Failed to enable trace event: %s\n", token); | ||
1501 | } | ||
1502 | |||
1503 | trace_printk_start_comm(); | ||
1504 | |||
1505 | return 0; | ||
1506 | } | ||
1507 | |||
1508 | static __init int event_trace_init(void) | 1444 | static __init int event_trace_init(void) |
1509 | { | 1445 | { |
1510 | struct ftrace_event_call *call; | 1446 | struct ftrace_event_call **call; |
1511 | struct dentry *d_tracer; | 1447 | struct dentry *d_tracer; |
1512 | struct dentry *entry; | 1448 | struct dentry *entry; |
1513 | struct dentry *d_events; | 1449 | struct dentry *d_events; |
1514 | int ret; | 1450 | int ret; |
1451 | char *buf = bootup_event_buf; | ||
1452 | char *token; | ||
1515 | 1453 | ||
1516 | d_tracer = tracing_init_dentry(); | 1454 | d_tracer = tracing_init_dentry(); |
1517 | if (!d_tracer) | 1455 | if (!d_tracer) |
1518 | return 0; | 1456 | return 0; |
1519 | 1457 | ||
1520 | entry = debugfs_create_file("available_events", 0444, d_tracer, | 1458 | entry = debugfs_create_file("available_events", 0444, d_tracer, |
1521 | NULL, &ftrace_avail_fops); | 1459 | (void *)&show_event_seq_ops, |
1460 | &ftrace_avail_fops); | ||
1522 | if (!entry) | 1461 | if (!entry) |
1523 | pr_warning("Could not create debugfs " | 1462 | pr_warning("Could not create debugfs " |
1524 | "'available_events' entry\n"); | 1463 | "'available_events' entry\n"); |
1525 | 1464 | ||
1526 | entry = debugfs_create_file("set_event", 0644, d_tracer, | 1465 | entry = debugfs_create_file("set_event", 0644, d_tracer, |
1527 | NULL, &ftrace_set_event_fops); | 1466 | (void *)&show_set_event_seq_ops, |
1467 | &ftrace_set_event_fops); | ||
1528 | if (!entry) | 1468 | if (!entry) |
1529 | pr_warning("Could not create debugfs " | 1469 | pr_warning("Could not create debugfs " |
1530 | "'set_event' entry\n"); | 1470 | "'set_event' entry\n"); |
@@ -1548,19 +1488,24 @@ static __init int event_trace_init(void) | |||
1548 | if (trace_define_common_fields()) | 1488 | if (trace_define_common_fields()) |
1549 | pr_warning("tracing: Failed to allocate common fields"); | 1489 | pr_warning("tracing: Failed to allocate common fields"); |
1550 | 1490 | ||
1551 | /* | 1491 | for_each_event(call, __start_ftrace_events, __stop_ftrace_events) { |
1552 | * Early initialization already enabled ftrace event. | 1492 | __trace_add_event_call(*call, NULL, &ftrace_event_id_fops, |
1553 | * Now it's only necessary to create the event directory. | ||
1554 | */ | ||
1555 | list_for_each_entry(call, &ftrace_events, list) { | ||
1556 | |||
1557 | ret = event_create_dir(call, d_events, | ||
1558 | &ftrace_event_id_fops, | ||
1559 | &ftrace_enable_fops, | 1493 | &ftrace_enable_fops, |
1560 | &ftrace_event_filter_fops, | 1494 | &ftrace_event_filter_fops, |
1561 | &ftrace_event_format_fops); | 1495 | &ftrace_event_format_fops); |
1562 | if (ret < 0) | 1496 | } |
1563 | event_remove(call); | 1497 | |
1498 | while (true) { | ||
1499 | token = strsep(&buf, ","); | ||
1500 | |||
1501 | if (!token) | ||
1502 | break; | ||
1503 | if (!*token) | ||
1504 | continue; | ||
1505 | |||
1506 | ret = ftrace_set_clr_event(token, 1); | ||
1507 | if (ret) | ||
1508 | pr_warning("Failed to enable trace event: %s\n", token); | ||
1564 | } | 1509 | } |
1565 | 1510 | ||
1566 | ret = register_module_notifier(&trace_module_nb); | 1511 | ret = register_module_notifier(&trace_module_nb); |
@@ -1569,7 +1514,6 @@ static __init int event_trace_init(void) | |||
1569 | 1514 | ||
1570 | return 0; | 1515 | return 0; |
1571 | } | 1516 | } |
1572 | core_initcall(event_trace_enable); | ||
1573 | fs_initcall(event_trace_init); | 1517 | fs_initcall(event_trace_init); |
1574 | 1518 | ||
1575 | #ifdef CONFIG_FTRACE_STARTUP_TEST | 1519 | #ifdef CONFIG_FTRACE_STARTUP_TEST |
@@ -1693,11 +1637,9 @@ static __init void event_trace_self_tests(void) | |||
1693 | event_test_stuff(); | 1637 | event_test_stuff(); |
1694 | 1638 | ||
1695 | ret = __ftrace_set_clr_event(NULL, system->name, NULL, 0); | 1639 | ret = __ftrace_set_clr_event(NULL, system->name, NULL, 0); |
1696 | if (WARN_ON_ONCE(ret)) { | 1640 | if (WARN_ON_ONCE(ret)) |
1697 | pr_warning("error disabling system %s\n", | 1641 | pr_warning("error disabling system %s\n", |
1698 | system->name); | 1642 | system->name); |
1699 | continue; | ||
1700 | } | ||
1701 | 1643 | ||
1702 | pr_cont("OK\n"); | 1644 | pr_cont("OK\n"); |
1703 | } | 1645 | } |
@@ -1730,8 +1672,7 @@ static __init void event_trace_self_tests(void) | |||
1730 | static DEFINE_PER_CPU(atomic_t, ftrace_test_event_disable); | 1672 | static DEFINE_PER_CPU(atomic_t, ftrace_test_event_disable); |
1731 | 1673 | ||
1732 | static void | 1674 | static void |
1733 | function_test_events_call(unsigned long ip, unsigned long parent_ip, | 1675 | function_test_events_call(unsigned long ip, unsigned long parent_ip) |
1734 | struct ftrace_ops *op, struct pt_regs *pt_regs) | ||
1735 | { | 1676 | { |
1736 | struct ring_buffer_event *event; | 1677 | struct ring_buffer_event *event; |
1737 | struct ring_buffer *buffer; | 1678 | struct ring_buffer *buffer; |
@@ -1760,7 +1701,7 @@ function_test_events_call(unsigned long ip, unsigned long parent_ip, | |||
1760 | entry->ip = ip; | 1701 | entry->ip = ip; |
1761 | entry->parent_ip = parent_ip; | 1702 | entry->parent_ip = parent_ip; |
1762 | 1703 | ||
1763 | trace_buffer_unlock_commit(buffer, event, flags, pc); | 1704 | trace_nowake_buffer_unlock_commit(buffer, event, flags, pc); |
1764 | 1705 | ||
1765 | out: | 1706 | out: |
1766 | atomic_dec(&per_cpu(ftrace_test_event_disable, cpu)); | 1707 | atomic_dec(&per_cpu(ftrace_test_event_disable, cpu)); |
@@ -1770,7 +1711,6 @@ function_test_events_call(unsigned long ip, unsigned long parent_ip, | |||
1770 | static struct ftrace_ops trace_ops __initdata = | 1711 | static struct ftrace_ops trace_ops __initdata = |
1771 | { | 1712 | { |
1772 | .func = function_test_events_call, | 1713 | .func = function_test_events_call, |
1773 | .flags = FTRACE_OPS_FL_RECURSION_SAFE, | ||
1774 | }; | 1714 | }; |
1775 | 1715 | ||
1776 | static __init void event_trace_self_test_with_function(void) | 1716 | static __init void event_trace_self_test_with_function(void) |