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.c466
1 files changed, 175 insertions, 291 deletions
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index 4de3e57f723c..ba476009e5de 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -15,6 +15,33 @@
15#include "trace.h" 15#include "trace.h"
16#include "trace_output.h" 16#include "trace_output.h"
17 17
18static bool kill_ftrace_graph;
19
20/**
21 * ftrace_graph_is_dead - returns true if ftrace_graph_stop() was called
22 *
23 * ftrace_graph_stop() is called when a severe error is detected in
24 * the function graph tracing. This function is called by the critical
25 * paths of function graph to keep those paths from doing any more harm.
26 */
27bool ftrace_graph_is_dead(void)
28{
29 return kill_ftrace_graph;
30}
31
32/**
33 * ftrace_graph_stop - set to permanently disable function graph tracincg
34 *
35 * In case of an error int function graph tracing, this is called
36 * to try to keep function graph tracing from causing any more harm.
37 * Usually this is pretty severe and this is called to try to at least
38 * get a warning out to the user.
39 */
40void ftrace_graph_stop(void)
41{
42 kill_ftrace_graph = true;
43}
44
18/* When set, irq functions will be ignored */ 45/* When set, irq functions will be ignored */
19static int ftrace_graph_skip_irqs; 46static int ftrace_graph_skip_irqs;
20 47
@@ -80,7 +107,7 @@ enum {
80 FLAGS_FILL_END = 3 << TRACE_GRAPH_PRINT_FILL_SHIFT, 107 FLAGS_FILL_END = 3 << TRACE_GRAPH_PRINT_FILL_SHIFT,
81}; 108};
82 109
83static enum print_line_t 110static void
84print_graph_duration(unsigned long long duration, struct trace_seq *s, 111print_graph_duration(unsigned long long duration, struct trace_seq *s,
85 u32 flags); 112 u32 flags);
86 113
@@ -92,6 +119,9 @@ ftrace_push_return_trace(unsigned long ret, unsigned long func, int *depth,
92 unsigned long long calltime; 119 unsigned long long calltime;
93 int index; 120 int index;
94 121
122 if (unlikely(ftrace_graph_is_dead()))
123 return -EBUSY;
124
95 if (!current->ret_stack) 125 if (!current->ret_stack)
96 return -EBUSY; 126 return -EBUSY;
97 127
@@ -323,7 +353,7 @@ int trace_graph_entry(struct ftrace_graph_ent *trace)
323 return ret; 353 return ret;
324} 354}
325 355
326int trace_graph_thresh_entry(struct ftrace_graph_ent *trace) 356static int trace_graph_thresh_entry(struct ftrace_graph_ent *trace)
327{ 357{
328 if (tracing_thresh) 358 if (tracing_thresh)
329 return 1; 359 return 1;
@@ -412,7 +442,7 @@ void set_graph_array(struct trace_array *tr)
412 smp_mb(); 442 smp_mb();
413} 443}
414 444
415void trace_graph_thresh_return(struct ftrace_graph_ret *trace) 445static void trace_graph_thresh_return(struct ftrace_graph_ret *trace)
416{ 446{
417 if (tracing_thresh && 447 if (tracing_thresh &&
418 (trace->rettime - trace->calltime < tracing_thresh)) 448 (trace->rettime - trace->calltime < tracing_thresh))
@@ -445,35 +475,32 @@ static void graph_trace_reset(struct trace_array *tr)
445 unregister_ftrace_graph(); 475 unregister_ftrace_graph();
446} 476}
447 477
478static int graph_trace_update_thresh(struct trace_array *tr)
479{
480 graph_trace_reset(tr);
481 return graph_trace_init(tr);
482}
483
448static int max_bytes_for_cpu; 484static int max_bytes_for_cpu;
449 485
450static enum print_line_t 486static void print_graph_cpu(struct trace_seq *s, int cpu)
451print_graph_cpu(struct trace_seq *s, int cpu)
452{ 487{
453 int ret;
454
455 /* 488 /*
456 * Start with a space character - to make it stand out 489 * Start with a space character - to make it stand out
457 * to the right a bit when trace output is pasted into 490 * to the right a bit when trace output is pasted into
458 * email: 491 * email:
459 */ 492 */
460 ret = trace_seq_printf(s, " %*d) ", max_bytes_for_cpu, cpu); 493 trace_seq_printf(s, " %*d) ", max_bytes_for_cpu, cpu);
461 if (!ret)
462 return TRACE_TYPE_PARTIAL_LINE;
463
464 return TRACE_TYPE_HANDLED;
465} 494}
466 495
467#define TRACE_GRAPH_PROCINFO_LENGTH 14 496#define TRACE_GRAPH_PROCINFO_LENGTH 14
468 497
469static enum print_line_t 498static void print_graph_proc(struct trace_seq *s, pid_t pid)
470print_graph_proc(struct trace_seq *s, pid_t pid)
471{ 499{
472 char comm[TASK_COMM_LEN]; 500 char comm[TASK_COMM_LEN];
473 /* sign + log10(MAX_INT) + '\0' */ 501 /* sign + log10(MAX_INT) + '\0' */
474 char pid_str[11]; 502 char pid_str[11];
475 int spaces = 0; 503 int spaces = 0;
476 int ret;
477 int len; 504 int len;
478 int i; 505 int i;
479 506
@@ -488,56 +515,43 @@ print_graph_proc(struct trace_seq *s, pid_t pid)
488 spaces = TRACE_GRAPH_PROCINFO_LENGTH - len; 515 spaces = TRACE_GRAPH_PROCINFO_LENGTH - len;
489 516
490 /* First spaces to align center */ 517 /* First spaces to align center */
491 for (i = 0; i < spaces / 2; i++) { 518 for (i = 0; i < spaces / 2; i++)
492 ret = trace_seq_putc(s, ' '); 519 trace_seq_putc(s, ' ');
493 if (!ret)
494 return TRACE_TYPE_PARTIAL_LINE;
495 }
496 520
497 ret = trace_seq_printf(s, "%s-%s", comm, pid_str); 521 trace_seq_printf(s, "%s-%s", comm, pid_str);
498 if (!ret)
499 return TRACE_TYPE_PARTIAL_LINE;
500 522
501 /* Last spaces to align center */ 523 /* Last spaces to align center */
502 for (i = 0; i < spaces - (spaces / 2); i++) { 524 for (i = 0; i < spaces - (spaces / 2); i++)
503 ret = trace_seq_putc(s, ' '); 525 trace_seq_putc(s, ' ');
504 if (!ret)
505 return TRACE_TYPE_PARTIAL_LINE;
506 }
507 return TRACE_TYPE_HANDLED;
508} 526}
509 527
510 528
511static enum print_line_t 529static void print_graph_lat_fmt(struct trace_seq *s, struct trace_entry *entry)
512print_graph_lat_fmt(struct trace_seq *s, struct trace_entry *entry)
513{ 530{
514 if (!trace_seq_putc(s, ' ')) 531 trace_seq_putc(s, ' ');
515 return 0; 532 trace_print_lat_fmt(s, entry);
516
517 return trace_print_lat_fmt(s, entry);
518} 533}
519 534
520/* If the pid changed since the last trace, output this event */ 535/* If the pid changed since the last trace, output this event */
521static enum print_line_t 536static void
522verif_pid(struct trace_seq *s, pid_t pid, int cpu, struct fgraph_data *data) 537verif_pid(struct trace_seq *s, pid_t pid, int cpu, struct fgraph_data *data)
523{ 538{
524 pid_t prev_pid; 539 pid_t prev_pid;
525 pid_t *last_pid; 540 pid_t *last_pid;
526 int ret;
527 541
528 if (!data) 542 if (!data)
529 return TRACE_TYPE_HANDLED; 543 return;
530 544
531 last_pid = &(per_cpu_ptr(data->cpu_data, cpu)->last_pid); 545 last_pid = &(per_cpu_ptr(data->cpu_data, cpu)->last_pid);
532 546
533 if (*last_pid == pid) 547 if (*last_pid == pid)
534 return TRACE_TYPE_HANDLED; 548 return;
535 549
536 prev_pid = *last_pid; 550 prev_pid = *last_pid;
537 *last_pid = pid; 551 *last_pid = pid;
538 552
539 if (prev_pid == -1) 553 if (prev_pid == -1)
540 return TRACE_TYPE_HANDLED; 554 return;
541/* 555/*
542 * Context-switch trace line: 556 * Context-switch trace line:
543 557
@@ -546,33 +560,12 @@ verif_pid(struct trace_seq *s, pid_t pid, int cpu, struct fgraph_data *data)
546 ------------------------------------------ 560 ------------------------------------------
547 561
548 */ 562 */
549 ret = trace_seq_puts(s, 563 trace_seq_puts(s, " ------------------------------------------\n");
550 " ------------------------------------------\n"); 564 print_graph_cpu(s, cpu);
551 if (!ret) 565 print_graph_proc(s, prev_pid);
552 return TRACE_TYPE_PARTIAL_LINE; 566 trace_seq_puts(s, " => ");
553 567 print_graph_proc(s, pid);
554 ret = print_graph_cpu(s, cpu); 568 trace_seq_puts(s, "\n ------------------------------------------\n\n");
555 if (ret == TRACE_TYPE_PARTIAL_LINE)
556 return TRACE_TYPE_PARTIAL_LINE;
557
558 ret = print_graph_proc(s, prev_pid);
559 if (ret == TRACE_TYPE_PARTIAL_LINE)
560 return TRACE_TYPE_PARTIAL_LINE;
561
562 ret = trace_seq_puts(s, " => ");
563 if (!ret)
564 return TRACE_TYPE_PARTIAL_LINE;
565
566 ret = print_graph_proc(s, pid);
567 if (ret == TRACE_TYPE_PARTIAL_LINE)
568 return TRACE_TYPE_PARTIAL_LINE;
569
570 ret = trace_seq_puts(s,
571 "\n ------------------------------------------\n\n");
572 if (!ret)
573 return TRACE_TYPE_PARTIAL_LINE;
574
575 return TRACE_TYPE_HANDLED;
576} 569}
577 570
578static struct ftrace_graph_ret_entry * 571static struct ftrace_graph_ret_entry *
@@ -646,175 +639,122 @@ get_return_for_leaf(struct trace_iterator *iter,
646 return next; 639 return next;
647} 640}
648 641
649static int print_graph_abs_time(u64 t, struct trace_seq *s) 642static void print_graph_abs_time(u64 t, struct trace_seq *s)
650{ 643{
651 unsigned long usecs_rem; 644 unsigned long usecs_rem;
652 645
653 usecs_rem = do_div(t, NSEC_PER_SEC); 646 usecs_rem = do_div(t, NSEC_PER_SEC);
654 usecs_rem /= 1000; 647 usecs_rem /= 1000;
655 648
656 return trace_seq_printf(s, "%5lu.%06lu | ", 649 trace_seq_printf(s, "%5lu.%06lu | ",
657 (unsigned long)t, usecs_rem); 650 (unsigned long)t, usecs_rem);
658} 651}
659 652
660static enum print_line_t 653static void
661print_graph_irq(struct trace_iterator *iter, unsigned long addr, 654print_graph_irq(struct trace_iterator *iter, unsigned long addr,
662 enum trace_type type, int cpu, pid_t pid, u32 flags) 655 enum trace_type type, int cpu, pid_t pid, u32 flags)
663{ 656{
664 int ret;
665 struct trace_seq *s = &iter->seq; 657 struct trace_seq *s = &iter->seq;
658 struct trace_entry *ent = iter->ent;
666 659
667 if (addr < (unsigned long)__irqentry_text_start || 660 if (addr < (unsigned long)__irqentry_text_start ||
668 addr >= (unsigned long)__irqentry_text_end) 661 addr >= (unsigned long)__irqentry_text_end)
669 return TRACE_TYPE_UNHANDLED; 662 return;
670 663
671 if (trace_flags & TRACE_ITER_CONTEXT_INFO) { 664 if (trace_flags & TRACE_ITER_CONTEXT_INFO) {
672 /* Absolute time */ 665 /* Absolute time */
673 if (flags & TRACE_GRAPH_PRINT_ABS_TIME) { 666 if (flags & TRACE_GRAPH_PRINT_ABS_TIME)
674 ret = print_graph_abs_time(iter->ts, s); 667 print_graph_abs_time(iter->ts, s);
675 if (!ret)
676 return TRACE_TYPE_PARTIAL_LINE;
677 }
678 668
679 /* Cpu */ 669 /* Cpu */
680 if (flags & TRACE_GRAPH_PRINT_CPU) { 670 if (flags & TRACE_GRAPH_PRINT_CPU)
681 ret = print_graph_cpu(s, cpu); 671 print_graph_cpu(s, cpu);
682 if (ret == TRACE_TYPE_PARTIAL_LINE)
683 return TRACE_TYPE_PARTIAL_LINE;
684 }
685 672
686 /* Proc */ 673 /* Proc */
687 if (flags & TRACE_GRAPH_PRINT_PROC) { 674 if (flags & TRACE_GRAPH_PRINT_PROC) {
688 ret = print_graph_proc(s, pid); 675 print_graph_proc(s, pid);
689 if (ret == TRACE_TYPE_PARTIAL_LINE) 676 trace_seq_puts(s, " | ");
690 return TRACE_TYPE_PARTIAL_LINE;
691 ret = trace_seq_puts(s, " | ");
692 if (!ret)
693 return TRACE_TYPE_PARTIAL_LINE;
694 } 677 }
678
679 /* Latency format */
680 if (trace_flags & TRACE_ITER_LATENCY_FMT)
681 print_graph_lat_fmt(s, ent);
695 } 682 }
696 683
697 /* No overhead */ 684 /* No overhead */
698 ret = print_graph_duration(0, s, flags | FLAGS_FILL_START); 685 print_graph_duration(0, s, flags | FLAGS_FILL_START);
699 if (ret != TRACE_TYPE_HANDLED)
700 return ret;
701 686
702 if (type == TRACE_GRAPH_ENT) 687 if (type == TRACE_GRAPH_ENT)
703 ret = trace_seq_puts(s, "==========>"); 688 trace_seq_puts(s, "==========>");
704 else 689 else
705 ret = trace_seq_puts(s, "<=========="); 690 trace_seq_puts(s, "<==========");
706
707 if (!ret)
708 return TRACE_TYPE_PARTIAL_LINE;
709 691
710 ret = print_graph_duration(0, s, flags | FLAGS_FILL_END); 692 print_graph_duration(0, s, flags | FLAGS_FILL_END);
711 if (ret != TRACE_TYPE_HANDLED) 693 trace_seq_putc(s, '\n');
712 return ret;
713
714 ret = trace_seq_putc(s, '\n');
715
716 if (!ret)
717 return TRACE_TYPE_PARTIAL_LINE;
718 return TRACE_TYPE_HANDLED;
719} 694}
720 695
721enum print_line_t 696void
722trace_print_graph_duration(unsigned long long duration, struct trace_seq *s) 697trace_print_graph_duration(unsigned long long duration, struct trace_seq *s)
723{ 698{
724 unsigned long nsecs_rem = do_div(duration, 1000); 699 unsigned long nsecs_rem = do_div(duration, 1000);
725 /* log10(ULONG_MAX) + '\0' */ 700 /* log10(ULONG_MAX) + '\0' */
726 char msecs_str[21]; 701 char usecs_str[21];
727 char nsecs_str[5]; 702 char nsecs_str[5];
728 int ret, len; 703 int len;
729 int i; 704 int i;
730 705
731 sprintf(msecs_str, "%lu", (unsigned long) duration); 706 sprintf(usecs_str, "%lu", (unsigned long) duration);
732 707
733 /* Print msecs */ 708 /* Print msecs */
734 ret = trace_seq_printf(s, "%s", msecs_str); 709 trace_seq_printf(s, "%s", usecs_str);
735 if (!ret)
736 return TRACE_TYPE_PARTIAL_LINE;
737 710
738 len = strlen(msecs_str); 711 len = strlen(usecs_str);
739 712
740 /* Print nsecs (we don't want to exceed 7 numbers) */ 713 /* Print nsecs (we don't want to exceed 7 numbers) */
741 if (len < 7) { 714 if (len < 7) {
742 size_t slen = min_t(size_t, sizeof(nsecs_str), 8UL - len); 715 size_t slen = min_t(size_t, sizeof(nsecs_str), 8UL - len);
743 716
744 snprintf(nsecs_str, slen, "%03lu", nsecs_rem); 717 snprintf(nsecs_str, slen, "%03lu", nsecs_rem);
745 ret = trace_seq_printf(s, ".%s", nsecs_str); 718 trace_seq_printf(s, ".%s", nsecs_str);
746 if (!ret)
747 return TRACE_TYPE_PARTIAL_LINE;
748 len += strlen(nsecs_str); 719 len += strlen(nsecs_str);
749 } 720 }
750 721
751 ret = trace_seq_puts(s, " us "); 722 trace_seq_puts(s, " us ");
752 if (!ret)
753 return TRACE_TYPE_PARTIAL_LINE;
754 723
755 /* Print remaining spaces to fit the row's width */ 724 /* Print remaining spaces to fit the row's width */
756 for (i = len; i < 7; i++) { 725 for (i = len; i < 7; i++)
757 ret = trace_seq_putc(s, ' '); 726 trace_seq_putc(s, ' ');
758 if (!ret)
759 return TRACE_TYPE_PARTIAL_LINE;
760 }
761 return TRACE_TYPE_HANDLED;
762} 727}
763 728
764static enum print_line_t 729static void
765print_graph_duration(unsigned long long duration, struct trace_seq *s, 730print_graph_duration(unsigned long long duration, struct trace_seq *s,
766 u32 flags) 731 u32 flags)
767{ 732{
768 int ret = -1;
769
770 if (!(flags & TRACE_GRAPH_PRINT_DURATION) || 733 if (!(flags & TRACE_GRAPH_PRINT_DURATION) ||
771 !(trace_flags & TRACE_ITER_CONTEXT_INFO)) 734 !(trace_flags & TRACE_ITER_CONTEXT_INFO))
772 return TRACE_TYPE_HANDLED; 735 return;
773 736
774 /* No real adata, just filling the column with spaces */ 737 /* No real adata, just filling the column with spaces */
775 switch (flags & TRACE_GRAPH_PRINT_FILL_MASK) { 738 switch (flags & TRACE_GRAPH_PRINT_FILL_MASK) {
776 case FLAGS_FILL_FULL: 739 case FLAGS_FILL_FULL:
777 ret = trace_seq_puts(s, " | "); 740 trace_seq_puts(s, " | ");
778 return ret ? TRACE_TYPE_HANDLED : TRACE_TYPE_PARTIAL_LINE; 741 return;
779 case FLAGS_FILL_START: 742 case FLAGS_FILL_START:
780 ret = trace_seq_puts(s, " "); 743 trace_seq_puts(s, " ");
781 return ret ? TRACE_TYPE_HANDLED : TRACE_TYPE_PARTIAL_LINE; 744 return;
782 case FLAGS_FILL_END: 745 case FLAGS_FILL_END:
783 ret = trace_seq_puts(s, " |"); 746 trace_seq_puts(s, " |");
784 return ret ? TRACE_TYPE_HANDLED : TRACE_TYPE_PARTIAL_LINE; 747 return;
785 } 748 }
786 749
787 /* Signal a overhead of time execution to the output */ 750 /* Signal a overhead of time execution to the output */
788 if (flags & TRACE_GRAPH_PRINT_OVERHEAD) { 751 if (flags & TRACE_GRAPH_PRINT_OVERHEAD)
789 /* Duration exceeded 100 msecs */ 752 trace_seq_printf(s, "%c ", trace_find_mark(duration));
790 if (duration > 100000ULL) 753 else
791 ret = trace_seq_puts(s, "! "); 754 trace_seq_puts(s, " ");
792 /* Duration exceeded 10 msecs */
793 else if (duration > 10000ULL)
794 ret = trace_seq_puts(s, "+ ");
795 }
796
797 /*
798 * The -1 means we either did not exceed the duration tresholds
799 * or we dont want to print out the overhead. Either way we need
800 * to fill out the space.
801 */
802 if (ret == -1)
803 ret = trace_seq_puts(s, " ");
804
805 /* Catching here any failure happenned above */
806 if (!ret)
807 return TRACE_TYPE_PARTIAL_LINE;
808
809 ret = trace_print_graph_duration(duration, s);
810 if (ret != TRACE_TYPE_HANDLED)
811 return ret;
812
813 ret = trace_seq_puts(s, "| ");
814 if (!ret)
815 return TRACE_TYPE_PARTIAL_LINE;
816 755
817 return TRACE_TYPE_HANDLED; 756 trace_print_graph_duration(duration, s);
757 trace_seq_puts(s, "| ");
818} 758}
819 759
820/* Case of a leaf function on its call entry */ 760/* Case of a leaf function on its call entry */
@@ -828,7 +768,6 @@ print_graph_entry_leaf(struct trace_iterator *iter,
828 struct ftrace_graph_ret *graph_ret; 768 struct ftrace_graph_ret *graph_ret;
829 struct ftrace_graph_ent *call; 769 struct ftrace_graph_ent *call;
830 unsigned long long duration; 770 unsigned long long duration;
831 int ret;
832 int i; 771 int i;
833 772
834 graph_ret = &ret_entry->ret; 773 graph_ret = &ret_entry->ret;
@@ -854,22 +793,15 @@ print_graph_entry_leaf(struct trace_iterator *iter,
854 } 793 }
855 794
856 /* Overhead and duration */ 795 /* Overhead and duration */
857 ret = print_graph_duration(duration, s, flags); 796 print_graph_duration(duration, s, flags);
858 if (ret == TRACE_TYPE_PARTIAL_LINE)
859 return TRACE_TYPE_PARTIAL_LINE;
860 797
861 /* Function */ 798 /* Function */
862 for (i = 0; i < call->depth * TRACE_GRAPH_INDENT; i++) { 799 for (i = 0; i < call->depth * TRACE_GRAPH_INDENT; i++)
863 ret = trace_seq_putc(s, ' '); 800 trace_seq_putc(s, ' ');
864 if (!ret)
865 return TRACE_TYPE_PARTIAL_LINE;
866 }
867 801
868 ret = trace_seq_printf(s, "%ps();\n", (void *)call->func); 802 trace_seq_printf(s, "%ps();\n", (void *)call->func);
869 if (!ret)
870 return TRACE_TYPE_PARTIAL_LINE;
871 803
872 return TRACE_TYPE_HANDLED; 804 return trace_handle_return(s);
873} 805}
874 806
875static enum print_line_t 807static enum print_line_t
@@ -879,7 +811,6 @@ print_graph_entry_nested(struct trace_iterator *iter,
879{ 811{
880 struct ftrace_graph_ent *call = &entry->graph_ent; 812 struct ftrace_graph_ent *call = &entry->graph_ent;
881 struct fgraph_data *data = iter->private; 813 struct fgraph_data *data = iter->private;
882 int ret;
883 int i; 814 int i;
884 815
885 if (data) { 816 if (data) {
@@ -895,19 +826,15 @@ print_graph_entry_nested(struct trace_iterator *iter,
895 } 826 }
896 827
897 /* No time */ 828 /* No time */
898 ret = print_graph_duration(0, s, flags | FLAGS_FILL_FULL); 829 print_graph_duration(0, s, flags | FLAGS_FILL_FULL);
899 if (ret != TRACE_TYPE_HANDLED)
900 return ret;
901 830
902 /* Function */ 831 /* Function */
903 for (i = 0; i < call->depth * TRACE_GRAPH_INDENT; i++) { 832 for (i = 0; i < call->depth * TRACE_GRAPH_INDENT; i++)
904 ret = trace_seq_putc(s, ' '); 833 trace_seq_putc(s, ' ');
905 if (!ret) 834
906 return TRACE_TYPE_PARTIAL_LINE; 835 trace_seq_printf(s, "%ps() {\n", (void *)call->func);
907 }
908 836
909 ret = trace_seq_printf(s, "%ps() {\n", (void *)call->func); 837 if (trace_seq_has_overflowed(s))
910 if (!ret)
911 return TRACE_TYPE_PARTIAL_LINE; 838 return TRACE_TYPE_PARTIAL_LINE;
912 839
913 /* 840 /*
@@ -917,62 +844,43 @@ print_graph_entry_nested(struct trace_iterator *iter,
917 return TRACE_TYPE_NO_CONSUME; 844 return TRACE_TYPE_NO_CONSUME;
918} 845}
919 846
920static enum print_line_t 847static void
921print_graph_prologue(struct trace_iterator *iter, struct trace_seq *s, 848print_graph_prologue(struct trace_iterator *iter, struct trace_seq *s,
922 int type, unsigned long addr, u32 flags) 849 int type, unsigned long addr, u32 flags)
923{ 850{
924 struct fgraph_data *data = iter->private; 851 struct fgraph_data *data = iter->private;
925 struct trace_entry *ent = iter->ent; 852 struct trace_entry *ent = iter->ent;
926 int cpu = iter->cpu; 853 int cpu = iter->cpu;
927 int ret;
928 854
929 /* Pid */ 855 /* Pid */
930 if (verif_pid(s, ent->pid, cpu, data) == TRACE_TYPE_PARTIAL_LINE) 856 verif_pid(s, ent->pid, cpu, data);
931 return TRACE_TYPE_PARTIAL_LINE;
932 857
933 if (type) { 858 if (type)
934 /* Interrupt */ 859 /* Interrupt */
935 ret = print_graph_irq(iter, addr, type, cpu, ent->pid, flags); 860 print_graph_irq(iter, addr, type, cpu, ent->pid, flags);
936 if (ret == TRACE_TYPE_PARTIAL_LINE)
937 return TRACE_TYPE_PARTIAL_LINE;
938 }
939 861
940 if (!(trace_flags & TRACE_ITER_CONTEXT_INFO)) 862 if (!(trace_flags & TRACE_ITER_CONTEXT_INFO))
941 return 0; 863 return;
942 864
943 /* Absolute time */ 865 /* Absolute time */
944 if (flags & TRACE_GRAPH_PRINT_ABS_TIME) { 866 if (flags & TRACE_GRAPH_PRINT_ABS_TIME)
945 ret = print_graph_abs_time(iter->ts, s); 867 print_graph_abs_time(iter->ts, s);
946 if (!ret)
947 return TRACE_TYPE_PARTIAL_LINE;
948 }
949 868
950 /* Cpu */ 869 /* Cpu */
951 if (flags & TRACE_GRAPH_PRINT_CPU) { 870 if (flags & TRACE_GRAPH_PRINT_CPU)
952 ret = print_graph_cpu(s, cpu); 871 print_graph_cpu(s, cpu);
953 if (ret == TRACE_TYPE_PARTIAL_LINE)
954 return TRACE_TYPE_PARTIAL_LINE;
955 }
956 872
957 /* Proc */ 873 /* Proc */
958 if (flags & TRACE_GRAPH_PRINT_PROC) { 874 if (flags & TRACE_GRAPH_PRINT_PROC) {
959 ret = print_graph_proc(s, ent->pid); 875 print_graph_proc(s, ent->pid);
960 if (ret == TRACE_TYPE_PARTIAL_LINE) 876 trace_seq_puts(s, " | ");
961 return TRACE_TYPE_PARTIAL_LINE;
962
963 ret = trace_seq_puts(s, " | ");
964 if (!ret)
965 return TRACE_TYPE_PARTIAL_LINE;
966 } 877 }
967 878
968 /* Latency format */ 879 /* Latency format */
969 if (trace_flags & TRACE_ITER_LATENCY_FMT) { 880 if (trace_flags & TRACE_ITER_LATENCY_FMT)
970 ret = print_graph_lat_fmt(s, ent); 881 print_graph_lat_fmt(s, ent);
971 if (ret == TRACE_TYPE_PARTIAL_LINE)
972 return TRACE_TYPE_PARTIAL_LINE;
973 }
974 882
975 return 0; 883 return;
976} 884}
977 885
978/* 886/*
@@ -1090,8 +998,7 @@ print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s,
1090 if (check_irq_entry(iter, flags, call->func, call->depth)) 998 if (check_irq_entry(iter, flags, call->func, call->depth))
1091 return TRACE_TYPE_HANDLED; 999 return TRACE_TYPE_HANDLED;
1092 1000
1093 if (print_graph_prologue(iter, s, TRACE_GRAPH_ENT, call->func, flags)) 1001 print_graph_prologue(iter, s, TRACE_GRAPH_ENT, call->func, flags);
1094 return TRACE_TYPE_PARTIAL_LINE;
1095 1002
1096 leaf_ret = get_return_for_leaf(iter, field); 1003 leaf_ret = get_return_for_leaf(iter, field);
1097 if (leaf_ret) 1004 if (leaf_ret)
@@ -1124,7 +1031,6 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
1124 pid_t pid = ent->pid; 1031 pid_t pid = ent->pid;
1125 int cpu = iter->cpu; 1032 int cpu = iter->cpu;
1126 int func_match = 1; 1033 int func_match = 1;
1127 int ret;
1128 int i; 1034 int i;
1129 1035
1130 if (check_irq_return(iter, flags, trace->depth)) 1036 if (check_irq_return(iter, flags, trace->depth))
@@ -1150,20 +1056,14 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
1150 } 1056 }
1151 } 1057 }
1152 1058
1153 if (print_graph_prologue(iter, s, 0, 0, flags)) 1059 print_graph_prologue(iter, s, 0, 0, flags);
1154 return TRACE_TYPE_PARTIAL_LINE;
1155 1060
1156 /* Overhead and duration */ 1061 /* Overhead and duration */
1157 ret = print_graph_duration(duration, s, flags); 1062 print_graph_duration(duration, s, flags);
1158 if (ret == TRACE_TYPE_PARTIAL_LINE)
1159 return TRACE_TYPE_PARTIAL_LINE;
1160 1063
1161 /* Closing brace */ 1064 /* Closing brace */
1162 for (i = 0; i < trace->depth * TRACE_GRAPH_INDENT; i++) { 1065 for (i = 0; i < trace->depth * TRACE_GRAPH_INDENT; i++)
1163 ret = trace_seq_putc(s, ' '); 1066 trace_seq_putc(s, ' ');
1164 if (!ret)
1165 return TRACE_TYPE_PARTIAL_LINE;
1166 }
1167 1067
1168 /* 1068 /*
1169 * If the return function does not have a matching entry, 1069 * If the return function does not have a matching entry,
@@ -1172,30 +1072,20 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
1172 * belongs to, write out the function name. Always do 1072 * belongs to, write out the function name. Always do
1173 * that if the funcgraph-tail option is enabled. 1073 * that if the funcgraph-tail option is enabled.
1174 */ 1074 */
1175 if (func_match && !(flags & TRACE_GRAPH_PRINT_TAIL)) { 1075 if (func_match && !(flags & TRACE_GRAPH_PRINT_TAIL))
1176 ret = trace_seq_puts(s, "}\n"); 1076 trace_seq_puts(s, "}\n");
1177 if (!ret) 1077 else
1178 return TRACE_TYPE_PARTIAL_LINE; 1078 trace_seq_printf(s, "} /* %ps */\n", (void *)trace->func);
1179 } else {
1180 ret = trace_seq_printf(s, "} /* %ps */\n", (void *)trace->func);
1181 if (!ret)
1182 return TRACE_TYPE_PARTIAL_LINE;
1183 }
1184 1079
1185 /* Overrun */ 1080 /* Overrun */
1186 if (flags & TRACE_GRAPH_PRINT_OVERRUN) { 1081 if (flags & TRACE_GRAPH_PRINT_OVERRUN)
1187 ret = trace_seq_printf(s, " (Overruns: %lu)\n", 1082 trace_seq_printf(s, " (Overruns: %lu)\n",
1188 trace->overrun); 1083 trace->overrun);
1189 if (!ret)
1190 return TRACE_TYPE_PARTIAL_LINE;
1191 }
1192 1084
1193 ret = print_graph_irq(iter, trace->func, TRACE_GRAPH_RET, 1085 print_graph_irq(iter, trace->func, TRACE_GRAPH_RET,
1194 cpu, pid, flags); 1086 cpu, pid, flags);
1195 if (ret == TRACE_TYPE_PARTIAL_LINE)
1196 return TRACE_TYPE_PARTIAL_LINE;
1197 1087
1198 return TRACE_TYPE_HANDLED; 1088 return trace_handle_return(s);
1199} 1089}
1200 1090
1201static enum print_line_t 1091static enum print_line_t
@@ -1212,26 +1102,18 @@ print_graph_comment(struct trace_seq *s, struct trace_entry *ent,
1212 if (data) 1102 if (data)
1213 depth = per_cpu_ptr(data->cpu_data, iter->cpu)->depth; 1103 depth = per_cpu_ptr(data->cpu_data, iter->cpu)->depth;
1214 1104
1215 if (print_graph_prologue(iter, s, 0, 0, flags)) 1105 print_graph_prologue(iter, s, 0, 0, flags);
1216 return TRACE_TYPE_PARTIAL_LINE;
1217 1106
1218 /* No time */ 1107 /* No time */
1219 ret = print_graph_duration(0, s, flags | FLAGS_FILL_FULL); 1108 print_graph_duration(0, s, flags | FLAGS_FILL_FULL);
1220 if (ret != TRACE_TYPE_HANDLED)
1221 return ret;
1222 1109
1223 /* Indentation */ 1110 /* Indentation */
1224 if (depth > 0) 1111 if (depth > 0)
1225 for (i = 0; i < (depth + 1) * TRACE_GRAPH_INDENT; i++) { 1112 for (i = 0; i < (depth + 1) * TRACE_GRAPH_INDENT; i++)
1226 ret = trace_seq_putc(s, ' '); 1113 trace_seq_putc(s, ' ');
1227 if (!ret)
1228 return TRACE_TYPE_PARTIAL_LINE;
1229 }
1230 1114
1231 /* The comment */ 1115 /* The comment */
1232 ret = trace_seq_puts(s, "/* "); 1116 trace_seq_puts(s, "/* ");
1233 if (!ret)
1234 return TRACE_TYPE_PARTIAL_LINE;
1235 1117
1236 switch (iter->ent->type) { 1118 switch (iter->ent->type) {
1237 case TRACE_BPRINT: 1119 case TRACE_BPRINT:
@@ -1254,17 +1136,18 @@ print_graph_comment(struct trace_seq *s, struct trace_entry *ent,
1254 return ret; 1136 return ret;
1255 } 1137 }
1256 1138
1139 if (trace_seq_has_overflowed(s))
1140 goto out;
1141
1257 /* Strip ending newline */ 1142 /* Strip ending newline */
1258 if (s->buffer[s->len - 1] == '\n') { 1143 if (s->buffer[s->seq.len - 1] == '\n') {
1259 s->buffer[s->len - 1] = '\0'; 1144 s->buffer[s->seq.len - 1] = '\0';
1260 s->len--; 1145 s->seq.len--;
1261 } 1146 }
1262 1147
1263 ret = trace_seq_puts(s, " */\n"); 1148 trace_seq_puts(s, " */\n");
1264 if (!ret) 1149 out:
1265 return TRACE_TYPE_PARTIAL_LINE; 1150 return trace_handle_return(s);
1266
1267 return TRACE_TYPE_HANDLED;
1268} 1151}
1269 1152
1270 1153
@@ -1371,35 +1254,35 @@ static void __print_graph_headers_flags(struct seq_file *s, u32 flags)
1371 print_lat_header(s, flags); 1254 print_lat_header(s, flags);
1372 1255
1373 /* 1st line */ 1256 /* 1st line */
1374 seq_printf(s, "#"); 1257 seq_putc(s, '#');
1375 if (flags & TRACE_GRAPH_PRINT_ABS_TIME) 1258 if (flags & TRACE_GRAPH_PRINT_ABS_TIME)
1376 seq_printf(s, " TIME "); 1259 seq_puts(s, " TIME ");
1377 if (flags & TRACE_GRAPH_PRINT_CPU) 1260 if (flags & TRACE_GRAPH_PRINT_CPU)
1378 seq_printf(s, " CPU"); 1261 seq_puts(s, " CPU");
1379 if (flags & TRACE_GRAPH_PRINT_PROC) 1262 if (flags & TRACE_GRAPH_PRINT_PROC)
1380 seq_printf(s, " TASK/PID "); 1263 seq_puts(s, " TASK/PID ");
1381 if (lat) 1264 if (lat)
1382 seq_printf(s, "||||"); 1265 seq_puts(s, "||||");
1383 if (flags & TRACE_GRAPH_PRINT_DURATION) 1266 if (flags & TRACE_GRAPH_PRINT_DURATION)
1384 seq_printf(s, " DURATION "); 1267 seq_puts(s, " DURATION ");
1385 seq_printf(s, " FUNCTION CALLS\n"); 1268 seq_puts(s, " FUNCTION CALLS\n");
1386 1269
1387 /* 2nd line */ 1270 /* 2nd line */
1388 seq_printf(s, "#"); 1271 seq_putc(s, '#');
1389 if (flags & TRACE_GRAPH_PRINT_ABS_TIME) 1272 if (flags & TRACE_GRAPH_PRINT_ABS_TIME)
1390 seq_printf(s, " | "); 1273 seq_puts(s, " | ");
1391 if (flags & TRACE_GRAPH_PRINT_CPU) 1274 if (flags & TRACE_GRAPH_PRINT_CPU)
1392 seq_printf(s, " | "); 1275 seq_puts(s, " | ");
1393 if (flags & TRACE_GRAPH_PRINT_PROC) 1276 if (flags & TRACE_GRAPH_PRINT_PROC)
1394 seq_printf(s, " | | "); 1277 seq_puts(s, " | | ");
1395 if (lat) 1278 if (lat)
1396 seq_printf(s, "||||"); 1279 seq_puts(s, "||||");
1397 if (flags & TRACE_GRAPH_PRINT_DURATION) 1280 if (flags & TRACE_GRAPH_PRINT_DURATION)
1398 seq_printf(s, " | | "); 1281 seq_puts(s, " | | ");
1399 seq_printf(s, " | | | |\n"); 1282 seq_puts(s, " | | | |\n");
1400} 1283}
1401 1284
1402void print_graph_headers(struct seq_file *s) 1285static void print_graph_headers(struct seq_file *s)
1403{ 1286{
1404 print_graph_headers_flags(s, tracer_flags.val); 1287 print_graph_headers_flags(s, tracer_flags.val);
1405} 1288}
@@ -1495,6 +1378,7 @@ static struct trace_event graph_trace_ret_event = {
1495 1378
1496static struct tracer graph_trace __tracer_data = { 1379static struct tracer graph_trace __tracer_data = {
1497 .name = "function_graph", 1380 .name = "function_graph",
1381 .update_thresh = graph_trace_update_thresh,
1498 .open = graph_trace_open, 1382 .open = graph_trace_open,
1499 .pipe_open = graph_trace_open, 1383 .pipe_open = graph_trace_open,
1500 .close = graph_trace_close, 1384 .close = graph_trace_close,