diff options
Diffstat (limited to 'kernel/trace/trace_events.c')
-rw-r--r-- | kernel/trace/trace_events.c | 89 |
1 files changed, 44 insertions, 45 deletions
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 4c758f146328..686ec399f2a8 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
@@ -27,6 +27,12 @@ | |||
27 | 27 | ||
28 | DEFINE_MUTEX(event_mutex); | 28 | DEFINE_MUTEX(event_mutex); |
29 | 29 | ||
30 | DEFINE_MUTEX(event_storage_mutex); | ||
31 | EXPORT_SYMBOL_GPL(event_storage_mutex); | ||
32 | |||
33 | char event_storage[EVENT_STORAGE_SIZE]; | ||
34 | EXPORT_SYMBOL_GPL(event_storage); | ||
35 | |||
30 | LIST_HEAD(ftrace_events); | 36 | LIST_HEAD(ftrace_events); |
31 | LIST_HEAD(ftrace_common_fields); | 37 | LIST_HEAD(ftrace_common_fields); |
32 | 38 | ||
@@ -110,7 +116,7 @@ static int trace_define_common_fields(void) | |||
110 | __common_field(unsigned char, flags); | 116 | __common_field(unsigned char, flags); |
111 | __common_field(unsigned char, preempt_count); | 117 | __common_field(unsigned char, preempt_count); |
112 | __common_field(int, pid); | 118 | __common_field(int, pid); |
113 | __common_field(int, lock_depth); | 119 | __common_field(int, padding); |
114 | 120 | ||
115 | return ret; | 121 | return ret; |
116 | } | 122 | } |
@@ -320,6 +326,7 @@ int trace_set_clr_event(const char *system, const char *event, int set) | |||
320 | { | 326 | { |
321 | return __ftrace_set_clr_event(NULL, system, event, set); | 327 | return __ftrace_set_clr_event(NULL, system, event, set); |
322 | } | 328 | } |
329 | EXPORT_SYMBOL_GPL(trace_set_clr_event); | ||
323 | 330 | ||
324 | /* 128 should be much more than enough */ | 331 | /* 128 should be much more than enough */ |
325 | #define EVENT_BUF_SIZE 127 | 332 | #define EVENT_BUF_SIZE 127 |
@@ -600,21 +607,29 @@ out: | |||
600 | 607 | ||
601 | enum { | 608 | enum { |
602 | FORMAT_HEADER = 1, | 609 | FORMAT_HEADER = 1, |
603 | FORMAT_PRINTFMT = 2, | 610 | FORMAT_FIELD_SEPERATOR = 2, |
611 | FORMAT_PRINTFMT = 3, | ||
604 | }; | 612 | }; |
605 | 613 | ||
606 | static void *f_next(struct seq_file *m, void *v, loff_t *pos) | 614 | static void *f_next(struct seq_file *m, void *v, loff_t *pos) |
607 | { | 615 | { |
608 | struct ftrace_event_call *call = m->private; | 616 | struct ftrace_event_call *call = m->private; |
609 | struct ftrace_event_field *field; | 617 | struct ftrace_event_field *field; |
610 | struct list_head *head; | 618 | struct list_head *common_head = &ftrace_common_fields; |
619 | struct list_head *head = trace_get_fields(call); | ||
611 | 620 | ||
612 | (*pos)++; | 621 | (*pos)++; |
613 | 622 | ||
614 | switch ((unsigned long)v) { | 623 | switch ((unsigned long)v) { |
615 | case FORMAT_HEADER: | 624 | case FORMAT_HEADER: |
616 | head = &ftrace_common_fields; | 625 | if (unlikely(list_empty(common_head))) |
626 | return NULL; | ||
617 | 627 | ||
628 | field = list_entry(common_head->prev, | ||
629 | struct ftrace_event_field, link); | ||
630 | return field; | ||
631 | |||
632 | case FORMAT_FIELD_SEPERATOR: | ||
618 | if (unlikely(list_empty(head))) | 633 | if (unlikely(list_empty(head))) |
619 | return NULL; | 634 | return NULL; |
620 | 635 | ||
@@ -626,31 +641,10 @@ static void *f_next(struct seq_file *m, void *v, loff_t *pos) | |||
626 | return NULL; | 641 | return NULL; |
627 | } | 642 | } |
628 | 643 | ||
629 | head = trace_get_fields(call); | ||
630 | |||
631 | /* | ||
632 | * To separate common fields from event fields, the | ||
633 | * LSB is set on the first event field. Clear it in case. | ||
634 | */ | ||
635 | v = (void *)((unsigned long)v & ~1L); | ||
636 | |||
637 | field = v; | 644 | field = v; |
638 | /* | 645 | if (field->link.prev == common_head) |
639 | * If this is a common field, and at the end of the list, then | 646 | return (void *)FORMAT_FIELD_SEPERATOR; |
640 | * continue with main list. | 647 | else if (field->link.prev == head) |
641 | */ | ||
642 | if (field->link.prev == &ftrace_common_fields) { | ||
643 | if (unlikely(list_empty(head))) | ||
644 | return NULL; | ||
645 | field = list_entry(head->prev, struct ftrace_event_field, link); | ||
646 | /* Set the LSB to notify f_show to print an extra newline */ | ||
647 | field = (struct ftrace_event_field *) | ||
648 | ((unsigned long)field | 1); | ||
649 | return field; | ||
650 | } | ||
651 | |||
652 | /* If we are done tell f_show to print the format */ | ||
653 | if (field->link.prev == head) | ||
654 | return (void *)FORMAT_PRINTFMT; | 648 | return (void *)FORMAT_PRINTFMT; |
655 | 649 | ||
656 | field = list_entry(field->link.prev, struct ftrace_event_field, link); | 650 | field = list_entry(field->link.prev, struct ftrace_event_field, link); |
@@ -688,22 +682,16 @@ static int f_show(struct seq_file *m, void *v) | |||
688 | seq_printf(m, "format:\n"); | 682 | seq_printf(m, "format:\n"); |
689 | return 0; | 683 | return 0; |
690 | 684 | ||
685 | case FORMAT_FIELD_SEPERATOR: | ||
686 | seq_putc(m, '\n'); | ||
687 | return 0; | ||
688 | |||
691 | case FORMAT_PRINTFMT: | 689 | case FORMAT_PRINTFMT: |
692 | seq_printf(m, "\nprint fmt: %s\n", | 690 | seq_printf(m, "\nprint fmt: %s\n", |
693 | call->print_fmt); | 691 | call->print_fmt); |
694 | return 0; | 692 | return 0; |
695 | } | 693 | } |
696 | 694 | ||
697 | /* | ||
698 | * To separate common fields from event fields, the | ||
699 | * LSB is set on the first event field. Clear it and | ||
700 | * print a newline if it is set. | ||
701 | */ | ||
702 | if ((unsigned long)v & 1) { | ||
703 | seq_putc(m, '\n'); | ||
704 | v = (void *)((unsigned long)v & ~1L); | ||
705 | } | ||
706 | |||
707 | field = v; | 695 | field = v; |
708 | 696 | ||
709 | /* | 697 | /* |
@@ -951,6 +939,7 @@ static const struct file_operations ftrace_enable_fops = { | |||
951 | .open = tracing_open_generic, | 939 | .open = tracing_open_generic, |
952 | .read = event_enable_read, | 940 | .read = event_enable_read, |
953 | .write = event_enable_write, | 941 | .write = event_enable_write, |
942 | .llseek = default_llseek, | ||
954 | }; | 943 | }; |
955 | 944 | ||
956 | static const struct file_operations ftrace_event_format_fops = { | 945 | static const struct file_operations ftrace_event_format_fops = { |
@@ -963,29 +952,34 @@ static const struct file_operations ftrace_event_format_fops = { | |||
963 | static const struct file_operations ftrace_event_id_fops = { | 952 | static const struct file_operations ftrace_event_id_fops = { |
964 | .open = tracing_open_generic, | 953 | .open = tracing_open_generic, |
965 | .read = event_id_read, | 954 | .read = event_id_read, |
955 | .llseek = default_llseek, | ||
966 | }; | 956 | }; |
967 | 957 | ||
968 | static const struct file_operations ftrace_event_filter_fops = { | 958 | static const struct file_operations ftrace_event_filter_fops = { |
969 | .open = tracing_open_generic, | 959 | .open = tracing_open_generic, |
970 | .read = event_filter_read, | 960 | .read = event_filter_read, |
971 | .write = event_filter_write, | 961 | .write = event_filter_write, |
962 | .llseek = default_llseek, | ||
972 | }; | 963 | }; |
973 | 964 | ||
974 | static const struct file_operations ftrace_subsystem_filter_fops = { | 965 | static const struct file_operations ftrace_subsystem_filter_fops = { |
975 | .open = tracing_open_generic, | 966 | .open = tracing_open_generic, |
976 | .read = subsystem_filter_read, | 967 | .read = subsystem_filter_read, |
977 | .write = subsystem_filter_write, | 968 | .write = subsystem_filter_write, |
969 | .llseek = default_llseek, | ||
978 | }; | 970 | }; |
979 | 971 | ||
980 | static const struct file_operations ftrace_system_enable_fops = { | 972 | static const struct file_operations ftrace_system_enable_fops = { |
981 | .open = tracing_open_generic, | 973 | .open = tracing_open_generic, |
982 | .read = system_enable_read, | 974 | .read = system_enable_read, |
983 | .write = system_enable_write, | 975 | .write = system_enable_write, |
976 | .llseek = default_llseek, | ||
984 | }; | 977 | }; |
985 | 978 | ||
986 | static const struct file_operations ftrace_show_header_fops = { | 979 | static const struct file_operations ftrace_show_header_fops = { |
987 | .open = tracing_open_generic, | 980 | .open = tracing_open_generic, |
988 | .read = show_header, | 981 | .read = show_header, |
982 | .llseek = default_llseek, | ||
989 | }; | 983 | }; |
990 | 984 | ||
991 | static struct dentry *event_trace_events_dir(void) | 985 | static struct dentry *event_trace_events_dir(void) |
@@ -1291,7 +1285,7 @@ trace_create_file_ops(struct module *mod) | |||
1291 | static void trace_module_add_events(struct module *mod) | 1285 | static void trace_module_add_events(struct module *mod) |
1292 | { | 1286 | { |
1293 | struct ftrace_module_file_ops *file_ops = NULL; | 1287 | struct ftrace_module_file_ops *file_ops = NULL; |
1294 | struct ftrace_event_call *call, *start, *end; | 1288 | struct ftrace_event_call **call, **start, **end; |
1295 | 1289 | ||
1296 | start = mod->trace_events; | 1290 | start = mod->trace_events; |
1297 | end = mod->trace_events + mod->num_trace_events; | 1291 | end = mod->trace_events + mod->num_trace_events; |
@@ -1304,7 +1298,7 @@ static void trace_module_add_events(struct module *mod) | |||
1304 | return; | 1298 | return; |
1305 | 1299 | ||
1306 | for_each_event(call, start, end) { | 1300 | for_each_event(call, start, end) { |
1307 | __trace_add_event_call(call, mod, | 1301 | __trace_add_event_call(*call, mod, |
1308 | &file_ops->id, &file_ops->enable, | 1302 | &file_ops->id, &file_ops->enable, |
1309 | &file_ops->filter, &file_ops->format); | 1303 | &file_ops->filter, &file_ops->format); |
1310 | } | 1304 | } |
@@ -1374,8 +1368,8 @@ static struct notifier_block trace_module_nb = { | |||
1374 | .priority = 0, | 1368 | .priority = 0, |
1375 | }; | 1369 | }; |
1376 | 1370 | ||
1377 | extern struct ftrace_event_call __start_ftrace_events[]; | 1371 | extern struct ftrace_event_call *__start_ftrace_events[]; |
1378 | extern struct ftrace_event_call __stop_ftrace_events[]; | 1372 | extern struct ftrace_event_call *__stop_ftrace_events[]; |
1379 | 1373 | ||
1380 | static char bootup_event_buf[COMMAND_LINE_SIZE] __initdata; | 1374 | static char bootup_event_buf[COMMAND_LINE_SIZE] __initdata; |
1381 | 1375 | ||
@@ -1391,7 +1385,7 @@ __setup("trace_event=", setup_trace_event); | |||
1391 | 1385 | ||
1392 | static __init int event_trace_init(void) | 1386 | static __init int event_trace_init(void) |
1393 | { | 1387 | { |
1394 | struct ftrace_event_call *call; | 1388 | struct ftrace_event_call **call; |
1395 | struct dentry *d_tracer; | 1389 | struct dentry *d_tracer; |
1396 | struct dentry *entry; | 1390 | struct dentry *entry; |
1397 | struct dentry *d_events; | 1391 | struct dentry *d_events; |
@@ -1437,7 +1431,7 @@ static __init int event_trace_init(void) | |||
1437 | pr_warning("tracing: Failed to allocate common fields"); | 1431 | pr_warning("tracing: Failed to allocate common fields"); |
1438 | 1432 | ||
1439 | for_each_event(call, __start_ftrace_events, __stop_ftrace_events) { | 1433 | for_each_event(call, __start_ftrace_events, __stop_ftrace_events) { |
1440 | __trace_add_event_call(call, NULL, &ftrace_event_id_fops, | 1434 | __trace_add_event_call(*call, NULL, &ftrace_event_id_fops, |
1441 | &ftrace_enable_fops, | 1435 | &ftrace_enable_fops, |
1442 | &ftrace_event_filter_fops, | 1436 | &ftrace_event_filter_fops, |
1443 | &ftrace_event_format_fops); | 1437 | &ftrace_event_format_fops); |
@@ -1663,7 +1657,12 @@ static struct ftrace_ops trace_ops __initdata = | |||
1663 | 1657 | ||
1664 | static __init void event_trace_self_test_with_function(void) | 1658 | static __init void event_trace_self_test_with_function(void) |
1665 | { | 1659 | { |
1666 | register_ftrace_function(&trace_ops); | 1660 | int ret; |
1661 | ret = register_ftrace_function(&trace_ops); | ||
1662 | if (WARN_ON(ret < 0)) { | ||
1663 | pr_info("Failed to enable function tracer for event tests\n"); | ||
1664 | return; | ||
1665 | } | ||
1667 | pr_info("Running tests again, along with the function tracer\n"); | 1666 | pr_info("Running tests again, along with the function tracer\n"); |
1668 | event_trace_self_tests(); | 1667 | event_trace_self_tests(); |
1669 | unregister_ftrace_function(&trace_ops); | 1668 | unregister_ftrace_function(&trace_ops); |