aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_functions_graph.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace/trace_functions_graph.c')
-rw-r--r--kernel/trace/trace_functions_graph.c197
1 files changed, 133 insertions, 64 deletions
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index 3fc2a575664..dd11c830eb8 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -9,6 +9,7 @@
9#include <linux/debugfs.h> 9#include <linux/debugfs.h>
10#include <linux/uaccess.h> 10#include <linux/uaccess.h>
11#include <linux/ftrace.h> 11#include <linux/ftrace.h>
12#include <linux/slab.h>
12#include <linux/fs.h> 13#include <linux/fs.h>
13 14
14#include "trace.h" 15#include "trace.h"
@@ -39,7 +40,7 @@ struct fgraph_data {
39#define TRACE_GRAPH_PRINT_OVERHEAD 0x4 40#define TRACE_GRAPH_PRINT_OVERHEAD 0x4
40#define TRACE_GRAPH_PRINT_PROC 0x8 41#define TRACE_GRAPH_PRINT_PROC 0x8
41#define TRACE_GRAPH_PRINT_DURATION 0x10 42#define TRACE_GRAPH_PRINT_DURATION 0x10
42#define TRACE_GRAPH_PRINT_ABS_TIME 0X20 43#define TRACE_GRAPH_PRINT_ABS_TIME 0x20
43 44
44static struct tracer_opt trace_opts[] = { 45static struct tracer_opt trace_opts[] = {
45 /* Display overruns? (for self-debug purpose) */ 46 /* Display overruns? (for self-debug purpose) */
@@ -178,7 +179,7 @@ unsigned long ftrace_return_to_handler(unsigned long frame_pointer)
178 return ret; 179 return ret;
179} 180}
180 181
181static int __trace_graph_entry(struct trace_array *tr, 182int __trace_graph_entry(struct trace_array *tr,
182 struct ftrace_graph_ent *trace, 183 struct ftrace_graph_ent *trace,
183 unsigned long flags, 184 unsigned long flags,
184 int pc) 185 int pc)
@@ -237,7 +238,15 @@ int trace_graph_entry(struct ftrace_graph_ent *trace)
237 return ret; 238 return ret;
238} 239}
239 240
240static void __trace_graph_return(struct trace_array *tr, 241int trace_graph_thresh_entry(struct ftrace_graph_ent *trace)
242{
243 if (tracing_thresh)
244 return 1;
245 else
246 return trace_graph_entry(trace);
247}
248
249void __trace_graph_return(struct trace_array *tr,
241 struct ftrace_graph_ret *trace, 250 struct ftrace_graph_ret *trace,
242 unsigned long flags, 251 unsigned long flags,
243 int pc) 252 int pc)
@@ -290,13 +299,26 @@ void set_graph_array(struct trace_array *tr)
290 smp_mb(); 299 smp_mb();
291} 300}
292 301
302void trace_graph_thresh_return(struct ftrace_graph_ret *trace)
303{
304 if (tracing_thresh &&
305 (trace->rettime - trace->calltime < tracing_thresh))
306 return;
307 else
308 trace_graph_return(trace);
309}
310
293static int graph_trace_init(struct trace_array *tr) 311static int graph_trace_init(struct trace_array *tr)
294{ 312{
295 int ret; 313 int ret;
296 314
297 set_graph_array(tr); 315 set_graph_array(tr);
298 ret = register_ftrace_graph(&trace_graph_return, 316 if (tracing_thresh)
299 &trace_graph_entry); 317 ret = register_ftrace_graph(&trace_graph_thresh_return,
318 &trace_graph_thresh_entry);
319 else
320 ret = register_ftrace_graph(&trace_graph_return,
321 &trace_graph_entry);
300 if (ret) 322 if (ret)
301 return ret; 323 return ret;
302 tracing_start_cmdline_record(); 324 tracing_start_cmdline_record();
@@ -468,9 +490,10 @@ get_return_for_leaf(struct trace_iterator *iter,
468 * We need to consume the current entry to see 490 * We need to consume the current entry to see
469 * the next one. 491 * the next one.
470 */ 492 */
471 ring_buffer_consume(iter->tr->buffer, iter->cpu, NULL); 493 ring_buffer_consume(iter->tr->buffer, iter->cpu,
494 NULL, NULL);
472 event = ring_buffer_peek(iter->tr->buffer, iter->cpu, 495 event = ring_buffer_peek(iter->tr->buffer, iter->cpu,
473 NULL); 496 NULL, NULL);
474 } 497 }
475 498
476 if (!event) 499 if (!event)
@@ -504,17 +527,18 @@ get_return_for_leaf(struct trace_iterator *iter,
504 527
505/* Signal a overhead of time execution to the output */ 528/* Signal a overhead of time execution to the output */
506static int 529static int
507print_graph_overhead(unsigned long long duration, struct trace_seq *s) 530print_graph_overhead(unsigned long long duration, struct trace_seq *s,
531 u32 flags)
508{ 532{
509 /* If duration disappear, we don't need anything */ 533 /* If duration disappear, we don't need anything */
510 if (!(tracer_flags.val & TRACE_GRAPH_PRINT_DURATION)) 534 if (!(flags & TRACE_GRAPH_PRINT_DURATION))
511 return 1; 535 return 1;
512 536
513 /* Non nested entry or return */ 537 /* Non nested entry or return */
514 if (duration == -1) 538 if (duration == -1)
515 return trace_seq_printf(s, " "); 539 return trace_seq_printf(s, " ");
516 540
517 if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERHEAD) { 541 if (flags & TRACE_GRAPH_PRINT_OVERHEAD) {
518 /* Duration exceeded 100 msecs */ 542 /* Duration exceeded 100 msecs */
519 if (duration > 100000ULL) 543 if (duration > 100000ULL)
520 return trace_seq_printf(s, "! "); 544 return trace_seq_printf(s, "! ");
@@ -540,7 +564,7 @@ static int print_graph_abs_time(u64 t, struct trace_seq *s)
540 564
541static enum print_line_t 565static enum print_line_t
542print_graph_irq(struct trace_iterator *iter, unsigned long addr, 566print_graph_irq(struct trace_iterator *iter, unsigned long addr,
543 enum trace_type type, int cpu, pid_t pid) 567 enum trace_type type, int cpu, pid_t pid, u32 flags)
544{ 568{
545 int ret; 569 int ret;
546 struct trace_seq *s = &iter->seq; 570 struct trace_seq *s = &iter->seq;
@@ -550,21 +574,21 @@ print_graph_irq(struct trace_iterator *iter, unsigned long addr,
550 return TRACE_TYPE_UNHANDLED; 574 return TRACE_TYPE_UNHANDLED;
551 575
552 /* Absolute time */ 576 /* Absolute time */
553 if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) { 577 if (flags & TRACE_GRAPH_PRINT_ABS_TIME) {
554 ret = print_graph_abs_time(iter->ts, s); 578 ret = print_graph_abs_time(iter->ts, s);
555 if (!ret) 579 if (!ret)
556 return TRACE_TYPE_PARTIAL_LINE; 580 return TRACE_TYPE_PARTIAL_LINE;
557 } 581 }
558 582
559 /* Cpu */ 583 /* Cpu */
560 if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) { 584 if (flags & TRACE_GRAPH_PRINT_CPU) {
561 ret = print_graph_cpu(s, cpu); 585 ret = print_graph_cpu(s, cpu);
562 if (ret == TRACE_TYPE_PARTIAL_LINE) 586 if (ret == TRACE_TYPE_PARTIAL_LINE)
563 return TRACE_TYPE_PARTIAL_LINE; 587 return TRACE_TYPE_PARTIAL_LINE;
564 } 588 }
565 589
566 /* Proc */ 590 /* Proc */
567 if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) { 591 if (flags & TRACE_GRAPH_PRINT_PROC) {
568 ret = print_graph_proc(s, pid); 592 ret = print_graph_proc(s, pid);
569 if (ret == TRACE_TYPE_PARTIAL_LINE) 593 if (ret == TRACE_TYPE_PARTIAL_LINE)
570 return TRACE_TYPE_PARTIAL_LINE; 594 return TRACE_TYPE_PARTIAL_LINE;
@@ -574,7 +598,7 @@ print_graph_irq(struct trace_iterator *iter, unsigned long addr,
574 } 598 }
575 599
576 /* No overhead */ 600 /* No overhead */
577 ret = print_graph_overhead(-1, s); 601 ret = print_graph_overhead(-1, s, flags);
578 if (!ret) 602 if (!ret)
579 return TRACE_TYPE_PARTIAL_LINE; 603 return TRACE_TYPE_PARTIAL_LINE;
580 604
@@ -587,7 +611,7 @@ print_graph_irq(struct trace_iterator *iter, unsigned long addr,
587 return TRACE_TYPE_PARTIAL_LINE; 611 return TRACE_TYPE_PARTIAL_LINE;
588 612
589 /* Don't close the duration column if haven't one */ 613 /* Don't close the duration column if haven't one */
590 if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) 614 if (flags & TRACE_GRAPH_PRINT_DURATION)
591 trace_seq_printf(s, " |"); 615 trace_seq_printf(s, " |");
592 ret = trace_seq_printf(s, "\n"); 616 ret = trace_seq_printf(s, "\n");
593 617
@@ -657,7 +681,8 @@ print_graph_duration(unsigned long long duration, struct trace_seq *s)
657static enum print_line_t 681static enum print_line_t
658print_graph_entry_leaf(struct trace_iterator *iter, 682print_graph_entry_leaf(struct trace_iterator *iter,
659 struct ftrace_graph_ent_entry *entry, 683 struct ftrace_graph_ent_entry *entry,
660 struct ftrace_graph_ret_entry *ret_entry, struct trace_seq *s) 684 struct ftrace_graph_ret_entry *ret_entry,
685 struct trace_seq *s, u32 flags)
661{ 686{
662 struct fgraph_data *data = iter->private; 687 struct fgraph_data *data = iter->private;
663 struct ftrace_graph_ret *graph_ret; 688 struct ftrace_graph_ret *graph_ret;
@@ -689,12 +714,12 @@ print_graph_entry_leaf(struct trace_iterator *iter,
689 } 714 }
690 715
691 /* Overhead */ 716 /* Overhead */
692 ret = print_graph_overhead(duration, s); 717 ret = print_graph_overhead(duration, s, flags);
693 if (!ret) 718 if (!ret)
694 return TRACE_TYPE_PARTIAL_LINE; 719 return TRACE_TYPE_PARTIAL_LINE;
695 720
696 /* Duration */ 721 /* Duration */
697 if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) { 722 if (flags & TRACE_GRAPH_PRINT_DURATION) {
698 ret = print_graph_duration(duration, s); 723 ret = print_graph_duration(duration, s);
699 if (ret == TRACE_TYPE_PARTIAL_LINE) 724 if (ret == TRACE_TYPE_PARTIAL_LINE)
700 return TRACE_TYPE_PARTIAL_LINE; 725 return TRACE_TYPE_PARTIAL_LINE;
@@ -717,7 +742,7 @@ print_graph_entry_leaf(struct trace_iterator *iter,
717static enum print_line_t 742static enum print_line_t
718print_graph_entry_nested(struct trace_iterator *iter, 743print_graph_entry_nested(struct trace_iterator *iter,
719 struct ftrace_graph_ent_entry *entry, 744 struct ftrace_graph_ent_entry *entry,
720 struct trace_seq *s, int cpu) 745 struct trace_seq *s, int cpu, u32 flags)
721{ 746{
722 struct ftrace_graph_ent *call = &entry->graph_ent; 747 struct ftrace_graph_ent *call = &entry->graph_ent;
723 struct fgraph_data *data = iter->private; 748 struct fgraph_data *data = iter->private;
@@ -737,12 +762,12 @@ print_graph_entry_nested(struct trace_iterator *iter,
737 } 762 }
738 763
739 /* No overhead */ 764 /* No overhead */
740 ret = print_graph_overhead(-1, s); 765 ret = print_graph_overhead(-1, s, flags);
741 if (!ret) 766 if (!ret)
742 return TRACE_TYPE_PARTIAL_LINE; 767 return TRACE_TYPE_PARTIAL_LINE;
743 768
744 /* No time */ 769 /* No time */
745 if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) { 770 if (flags & TRACE_GRAPH_PRINT_DURATION) {
746 ret = trace_seq_printf(s, " | "); 771 ret = trace_seq_printf(s, " | ");
747 if (!ret) 772 if (!ret)
748 return TRACE_TYPE_PARTIAL_LINE; 773 return TRACE_TYPE_PARTIAL_LINE;
@@ -768,7 +793,7 @@ print_graph_entry_nested(struct trace_iterator *iter,
768 793
769static enum print_line_t 794static enum print_line_t
770print_graph_prologue(struct trace_iterator *iter, struct trace_seq *s, 795print_graph_prologue(struct trace_iterator *iter, struct trace_seq *s,
771 int type, unsigned long addr) 796 int type, unsigned long addr, u32 flags)
772{ 797{
773 struct fgraph_data *data = iter->private; 798 struct fgraph_data *data = iter->private;
774 struct trace_entry *ent = iter->ent; 799 struct trace_entry *ent = iter->ent;
@@ -781,27 +806,27 @@ print_graph_prologue(struct trace_iterator *iter, struct trace_seq *s,
781 806
782 if (type) { 807 if (type) {
783 /* Interrupt */ 808 /* Interrupt */
784 ret = print_graph_irq(iter, addr, type, cpu, ent->pid); 809 ret = print_graph_irq(iter, addr, type, cpu, ent->pid, flags);
785 if (ret == TRACE_TYPE_PARTIAL_LINE) 810 if (ret == TRACE_TYPE_PARTIAL_LINE)
786 return TRACE_TYPE_PARTIAL_LINE; 811 return TRACE_TYPE_PARTIAL_LINE;
787 } 812 }
788 813
789 /* Absolute time */ 814 /* Absolute time */
790 if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) { 815 if (flags & TRACE_GRAPH_PRINT_ABS_TIME) {
791 ret = print_graph_abs_time(iter->ts, s); 816 ret = print_graph_abs_time(iter->ts, s);
792 if (!ret) 817 if (!ret)
793 return TRACE_TYPE_PARTIAL_LINE; 818 return TRACE_TYPE_PARTIAL_LINE;
794 } 819 }
795 820
796 /* Cpu */ 821 /* Cpu */
797 if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) { 822 if (flags & TRACE_GRAPH_PRINT_CPU) {
798 ret = print_graph_cpu(s, cpu); 823 ret = print_graph_cpu(s, cpu);
799 if (ret == TRACE_TYPE_PARTIAL_LINE) 824 if (ret == TRACE_TYPE_PARTIAL_LINE)
800 return TRACE_TYPE_PARTIAL_LINE; 825 return TRACE_TYPE_PARTIAL_LINE;
801 } 826 }
802 827
803 /* Proc */ 828 /* Proc */
804 if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) { 829 if (flags & TRACE_GRAPH_PRINT_PROC) {
805 ret = print_graph_proc(s, ent->pid); 830 ret = print_graph_proc(s, ent->pid);
806 if (ret == TRACE_TYPE_PARTIAL_LINE) 831 if (ret == TRACE_TYPE_PARTIAL_LINE)
807 return TRACE_TYPE_PARTIAL_LINE; 832 return TRACE_TYPE_PARTIAL_LINE;
@@ -823,7 +848,7 @@ print_graph_prologue(struct trace_iterator *iter, struct trace_seq *s,
823 848
824static enum print_line_t 849static enum print_line_t
825print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s, 850print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s,
826 struct trace_iterator *iter) 851 struct trace_iterator *iter, u32 flags)
827{ 852{
828 struct fgraph_data *data = iter->private; 853 struct fgraph_data *data = iter->private;
829 struct ftrace_graph_ent *call = &field->graph_ent; 854 struct ftrace_graph_ent *call = &field->graph_ent;
@@ -831,14 +856,14 @@ print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s,
831 static enum print_line_t ret; 856 static enum print_line_t ret;
832 int cpu = iter->cpu; 857 int cpu = iter->cpu;
833 858
834 if (print_graph_prologue(iter, s, TRACE_GRAPH_ENT, call->func)) 859 if (print_graph_prologue(iter, s, TRACE_GRAPH_ENT, call->func, flags))
835 return TRACE_TYPE_PARTIAL_LINE; 860 return TRACE_TYPE_PARTIAL_LINE;
836 861
837 leaf_ret = get_return_for_leaf(iter, field); 862 leaf_ret = get_return_for_leaf(iter, field);
838 if (leaf_ret) 863 if (leaf_ret)
839 ret = print_graph_entry_leaf(iter, field, leaf_ret, s); 864 ret = print_graph_entry_leaf(iter, field, leaf_ret, s, flags);
840 else 865 else
841 ret = print_graph_entry_nested(iter, field, s, cpu); 866 ret = print_graph_entry_nested(iter, field, s, cpu, flags);
842 867
843 if (data) { 868 if (data) {
844 /* 869 /*
@@ -857,7 +882,8 @@ print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s,
857 882
858static enum print_line_t 883static enum print_line_t
859print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s, 884print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
860 struct trace_entry *ent, struct trace_iterator *iter) 885 struct trace_entry *ent, struct trace_iterator *iter,
886 u32 flags)
861{ 887{
862 unsigned long long duration = trace->rettime - trace->calltime; 888 unsigned long long duration = trace->rettime - trace->calltime;
863 struct fgraph_data *data = iter->private; 889 struct fgraph_data *data = iter->private;
@@ -887,16 +913,16 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
887 } 913 }
888 } 914 }
889 915
890 if (print_graph_prologue(iter, s, 0, 0)) 916 if (print_graph_prologue(iter, s, 0, 0, flags))
891 return TRACE_TYPE_PARTIAL_LINE; 917 return TRACE_TYPE_PARTIAL_LINE;
892 918
893 /* Overhead */ 919 /* Overhead */
894 ret = print_graph_overhead(duration, s); 920 ret = print_graph_overhead(duration, s, flags);
895 if (!ret) 921 if (!ret)
896 return TRACE_TYPE_PARTIAL_LINE; 922 return TRACE_TYPE_PARTIAL_LINE;
897 923
898 /* Duration */ 924 /* Duration */
899 if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) { 925 if (flags & TRACE_GRAPH_PRINT_DURATION) {
900 ret = print_graph_duration(duration, s); 926 ret = print_graph_duration(duration, s);
901 if (ret == TRACE_TYPE_PARTIAL_LINE) 927 if (ret == TRACE_TYPE_PARTIAL_LINE)
902 return TRACE_TYPE_PARTIAL_LINE; 928 return TRACE_TYPE_PARTIAL_LINE;
@@ -920,20 +946,21 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
920 if (!ret) 946 if (!ret)
921 return TRACE_TYPE_PARTIAL_LINE; 947 return TRACE_TYPE_PARTIAL_LINE;
922 } else { 948 } else {
923 ret = trace_seq_printf(s, "} (%ps)\n", (void *)trace->func); 949 ret = trace_seq_printf(s, "} /* %ps */\n", (void *)trace->func);
924 if (!ret) 950 if (!ret)
925 return TRACE_TYPE_PARTIAL_LINE; 951 return TRACE_TYPE_PARTIAL_LINE;
926 } 952 }
927 953
928 /* Overrun */ 954 /* Overrun */
929 if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERRUN) { 955 if (flags & TRACE_GRAPH_PRINT_OVERRUN) {
930 ret = trace_seq_printf(s, " (Overruns: %lu)\n", 956 ret = trace_seq_printf(s, " (Overruns: %lu)\n",
931 trace->overrun); 957 trace->overrun);
932 if (!ret) 958 if (!ret)
933 return TRACE_TYPE_PARTIAL_LINE; 959 return TRACE_TYPE_PARTIAL_LINE;
934 } 960 }
935 961
936 ret = print_graph_irq(iter, trace->func, TRACE_GRAPH_RET, cpu, pid); 962 ret = print_graph_irq(iter, trace->func, TRACE_GRAPH_RET,
963 cpu, pid, flags);
937 if (ret == TRACE_TYPE_PARTIAL_LINE) 964 if (ret == TRACE_TYPE_PARTIAL_LINE)
938 return TRACE_TYPE_PARTIAL_LINE; 965 return TRACE_TYPE_PARTIAL_LINE;
939 966
@@ -941,8 +968,8 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
941} 968}
942 969
943static enum print_line_t 970static enum print_line_t
944print_graph_comment(struct trace_seq *s, struct trace_entry *ent, 971print_graph_comment(struct trace_seq *s, struct trace_entry *ent,
945 struct trace_iterator *iter) 972 struct trace_iterator *iter, u32 flags)
946{ 973{
947 unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK); 974 unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK);
948 struct fgraph_data *data = iter->private; 975 struct fgraph_data *data = iter->private;
@@ -954,16 +981,16 @@ print_graph_comment(struct trace_seq *s, struct trace_entry *ent,
954 if (data) 981 if (data)
955 depth = per_cpu_ptr(data->cpu_data, iter->cpu)->depth; 982 depth = per_cpu_ptr(data->cpu_data, iter->cpu)->depth;
956 983
957 if (print_graph_prologue(iter, s, 0, 0)) 984 if (print_graph_prologue(iter, s, 0, 0, flags))
958 return TRACE_TYPE_PARTIAL_LINE; 985 return TRACE_TYPE_PARTIAL_LINE;
959 986
960 /* No overhead */ 987 /* No overhead */
961 ret = print_graph_overhead(-1, s); 988 ret = print_graph_overhead(-1, s, flags);
962 if (!ret) 989 if (!ret)
963 return TRACE_TYPE_PARTIAL_LINE; 990 return TRACE_TYPE_PARTIAL_LINE;
964 991
965 /* No time */ 992 /* No time */
966 if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) { 993 if (flags & TRACE_GRAPH_PRINT_DURATION) {
967 ret = trace_seq_printf(s, " | "); 994 ret = trace_seq_printf(s, " | ");
968 if (!ret) 995 if (!ret)
969 return TRACE_TYPE_PARTIAL_LINE; 996 return TRACE_TYPE_PARTIAL_LINE;
@@ -1018,7 +1045,7 @@ print_graph_comment(struct trace_seq *s, struct trace_entry *ent,
1018 1045
1019 1046
1020enum print_line_t 1047enum print_line_t
1021print_graph_function(struct trace_iterator *iter) 1048print_graph_function_flags(struct trace_iterator *iter, u32 flags)
1022{ 1049{
1023 struct ftrace_graph_ent_entry *field; 1050 struct ftrace_graph_ent_entry *field;
1024 struct fgraph_data *data = iter->private; 1051 struct fgraph_data *data = iter->private;
@@ -1039,7 +1066,7 @@ print_graph_function(struct trace_iterator *iter)
1039 if (data && data->failed) { 1066 if (data && data->failed) {
1040 field = &data->ent; 1067 field = &data->ent;
1041 iter->cpu = data->cpu; 1068 iter->cpu = data->cpu;
1042 ret = print_graph_entry(field, s, iter); 1069 ret = print_graph_entry(field, s, iter, flags);
1043 if (ret == TRACE_TYPE_HANDLED && iter->cpu != cpu) { 1070 if (ret == TRACE_TYPE_HANDLED && iter->cpu != cpu) {
1044 per_cpu_ptr(data->cpu_data, iter->cpu)->ignore = 1; 1071 per_cpu_ptr(data->cpu_data, iter->cpu)->ignore = 1;
1045 ret = TRACE_TYPE_NO_CONSUME; 1072 ret = TRACE_TYPE_NO_CONSUME;
@@ -1059,32 +1086,49 @@ print_graph_function(struct trace_iterator *iter)
1059 struct ftrace_graph_ent_entry saved; 1086 struct ftrace_graph_ent_entry saved;
1060 trace_assign_type(field, entry); 1087 trace_assign_type(field, entry);
1061 saved = *field; 1088 saved = *field;
1062 return print_graph_entry(&saved, s, iter); 1089 return print_graph_entry(&saved, s, iter, flags);
1063 } 1090 }
1064 case TRACE_GRAPH_RET: { 1091 case TRACE_GRAPH_RET: {
1065 struct ftrace_graph_ret_entry *field; 1092 struct ftrace_graph_ret_entry *field;
1066 trace_assign_type(field, entry); 1093 trace_assign_type(field, entry);
1067 return print_graph_return(&field->ret, s, entry, iter); 1094 return print_graph_return(&field->ret, s, entry, iter, flags);
1068 } 1095 }
1096 case TRACE_STACK:
1097 case TRACE_FN:
1098 /* dont trace stack and functions as comments */
1099 return TRACE_TYPE_UNHANDLED;
1100
1069 default: 1101 default:
1070 return print_graph_comment(s, entry, iter); 1102 return print_graph_comment(s, entry, iter, flags);
1071 } 1103 }
1072 1104
1073 return TRACE_TYPE_HANDLED; 1105 return TRACE_TYPE_HANDLED;
1074} 1106}
1075 1107
1076static void print_lat_header(struct seq_file *s) 1108static enum print_line_t
1109print_graph_function(struct trace_iterator *iter)
1110{
1111 return print_graph_function_flags(iter, tracer_flags.val);
1112}
1113
1114static enum print_line_t
1115print_graph_function_event(struct trace_iterator *iter, int flags)
1116{
1117 return print_graph_function(iter);
1118}
1119
1120static void print_lat_header(struct seq_file *s, u32 flags)
1077{ 1121{
1078 static const char spaces[] = " " /* 16 spaces */ 1122 static const char spaces[] = " " /* 16 spaces */
1079 " " /* 4 spaces */ 1123 " " /* 4 spaces */
1080 " "; /* 17 spaces */ 1124 " "; /* 17 spaces */
1081 int size = 0; 1125 int size = 0;
1082 1126
1083 if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) 1127 if (flags & TRACE_GRAPH_PRINT_ABS_TIME)
1084 size += 16; 1128 size += 16;
1085 if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) 1129 if (flags & TRACE_GRAPH_PRINT_CPU)
1086 size += 4; 1130 size += 4;
1087 if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) 1131 if (flags & TRACE_GRAPH_PRINT_PROC)
1088 size += 17; 1132 size += 17;
1089 1133
1090 seq_printf(s, "#%.*s _-----=> irqs-off \n", size, spaces); 1134 seq_printf(s, "#%.*s _-----=> irqs-off \n", size, spaces);
@@ -1095,43 +1139,48 @@ static void print_lat_header(struct seq_file *s)
1095 seq_printf(s, "#%.*s|||| / \n", size, spaces); 1139 seq_printf(s, "#%.*s|||| / \n", size, spaces);
1096} 1140}
1097 1141
1098static void print_graph_headers(struct seq_file *s) 1142void print_graph_headers_flags(struct seq_file *s, u32 flags)
1099{ 1143{
1100 int lat = trace_flags & TRACE_ITER_LATENCY_FMT; 1144 int lat = trace_flags & TRACE_ITER_LATENCY_FMT;
1101 1145
1102 if (lat) 1146 if (lat)
1103 print_lat_header(s); 1147 print_lat_header(s, flags);
1104 1148
1105 /* 1st line */ 1149 /* 1st line */
1106 seq_printf(s, "#"); 1150 seq_printf(s, "#");
1107 if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) 1151 if (flags & TRACE_GRAPH_PRINT_ABS_TIME)
1108 seq_printf(s, " TIME "); 1152 seq_printf(s, " TIME ");
1109 if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) 1153 if (flags & TRACE_GRAPH_PRINT_CPU)
1110 seq_printf(s, " CPU"); 1154 seq_printf(s, " CPU");
1111 if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) 1155 if (flags & TRACE_GRAPH_PRINT_PROC)
1112 seq_printf(s, " TASK/PID "); 1156 seq_printf(s, " TASK/PID ");
1113 if (lat) 1157 if (lat)
1114 seq_printf(s, "|||||"); 1158 seq_printf(s, "|||||");
1115 if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) 1159 if (flags & TRACE_GRAPH_PRINT_DURATION)
1116 seq_printf(s, " DURATION "); 1160 seq_printf(s, " DURATION ");
1117 seq_printf(s, " FUNCTION CALLS\n"); 1161 seq_printf(s, " FUNCTION CALLS\n");
1118 1162
1119 /* 2nd line */ 1163 /* 2nd line */
1120 seq_printf(s, "#"); 1164 seq_printf(s, "#");
1121 if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) 1165 if (flags & TRACE_GRAPH_PRINT_ABS_TIME)
1122 seq_printf(s, " | "); 1166 seq_printf(s, " | ");
1123 if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) 1167 if (flags & TRACE_GRAPH_PRINT_CPU)
1124 seq_printf(s, " | "); 1168 seq_printf(s, " | ");
1125 if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) 1169 if (flags & TRACE_GRAPH_PRINT_PROC)
1126 seq_printf(s, " | | "); 1170 seq_printf(s, " | | ");
1127 if (lat) 1171 if (lat)
1128 seq_printf(s, "|||||"); 1172 seq_printf(s, "|||||");
1129 if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) 1173 if (flags & TRACE_GRAPH_PRINT_DURATION)
1130 seq_printf(s, " | | "); 1174 seq_printf(s, " | | ");
1131 seq_printf(s, " | | | |\n"); 1175 seq_printf(s, " | | | |\n");
1132} 1176}
1133 1177
1134static void graph_trace_open(struct trace_iterator *iter) 1178void print_graph_headers(struct seq_file *s)
1179{
1180 print_graph_headers_flags(s, tracer_flags.val);
1181}
1182
1183void graph_trace_open(struct trace_iterator *iter)
1135{ 1184{
1136 /* pid and depth on the last trace processed */ 1185 /* pid and depth on the last trace processed */
1137 struct fgraph_data *data; 1186 struct fgraph_data *data;
@@ -1166,7 +1215,7 @@ static void graph_trace_open(struct trace_iterator *iter)
1166 pr_warning("function graph tracer: not enough memory\n"); 1215 pr_warning("function graph tracer: not enough memory\n");
1167} 1216}
1168 1217
1169static void graph_trace_close(struct trace_iterator *iter) 1218void graph_trace_close(struct trace_iterator *iter)
1170{ 1219{
1171 struct fgraph_data *data = iter->private; 1220 struct fgraph_data *data = iter->private;
1172 1221
@@ -1176,6 +1225,16 @@ static void graph_trace_close(struct trace_iterator *iter)
1176 } 1225 }
1177} 1226}
1178 1227
1228static struct trace_event graph_trace_entry_event = {
1229 .type = TRACE_GRAPH_ENT,
1230 .trace = print_graph_function_event,
1231};
1232
1233static struct trace_event graph_trace_ret_event = {
1234 .type = TRACE_GRAPH_RET,
1235 .trace = print_graph_function_event,
1236};
1237
1179static struct tracer graph_trace __read_mostly = { 1238static struct tracer graph_trace __read_mostly = {
1180 .name = "function_graph", 1239 .name = "function_graph",
1181 .open = graph_trace_open, 1240 .open = graph_trace_open,
@@ -1197,6 +1256,16 @@ static __init int init_graph_trace(void)
1197{ 1256{
1198 max_bytes_for_cpu = snprintf(NULL, 0, "%d", nr_cpu_ids - 1); 1257 max_bytes_for_cpu = snprintf(NULL, 0, "%d", nr_cpu_ids - 1);
1199 1258
1259 if (!register_ftrace_event(&graph_trace_entry_event)) {
1260 pr_warning("Warning: could not register graph trace events\n");
1261 return 1;
1262 }
1263
1264 if (!register_ftrace_event(&graph_trace_ret_event)) {
1265 pr_warning("Warning: could not register graph trace events\n");
1266 return 1;
1267 }
1268
1200 return register_tracer(&graph_trace); 1269 return register_tracer(&graph_trace);
1201} 1270}
1202 1271