aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2008-05-12 15:20:46 -0400
committerThomas Gleixner <tglx@linutronix.de>2008-05-23 14:41:46 -0400
commit214023c3d13a71525e463b5e54e360b926b4dc90 (patch)
tree6fe6f3e513d976b32eb07f60810ccf336daf1f6b
parent93a588f459da134be6ab17c4104e28441beb0d22 (diff)
ftrace: add a buffer for output
Later patches will need to print the same things as the seq output does. But those outputs will not use the seq utility. This patch adds a buffer to the iterator, that can be used by either the seq utility or other output. Signed-off-by: Steven Rostedt <srostedt@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--kernel/trace/trace.c202
-rw-r--r--kernel/trace/trace.h6
2 files changed, 140 insertions, 68 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 777b859e1c2e..d39f4faec7c3 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -169,6 +169,66 @@ void *head_page(struct trace_array_cpu *data)
169 return page_address(page); 169 return page_address(page);
170} 170}
171 171
172static notrace int
173trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
174{
175 int len = (PAGE_SIZE - 1) - s->len;
176 va_list ap;
177
178 if (!len)
179 return 0;
180
181 va_start(ap, fmt);
182 len = vsnprintf(s->buffer + s->len, len, fmt, ap);
183 va_end(ap);
184
185 s->len += len;
186
187 return len;
188}
189
190static notrace int
191trace_seq_puts(struct trace_seq *s, const char *str)
192{
193 int len = strlen(str);
194
195 if (len > ((PAGE_SIZE - 1) - s->len))
196 len = (PAGE_SIZE - 1) - s->len;
197
198 memcpy(s->buffer + s->len, str, len);
199 s->len += len;
200
201 return len;
202}
203
204static notrace int
205trace_seq_putc(struct trace_seq *s, unsigned char c)
206{
207 if (s->len >= (PAGE_SIZE - 1))
208 return 0;
209
210 s->buffer[s->len++] = c;
211
212 return 1;
213}
214
215static notrace void
216trace_seq_reset(struct trace_seq *s)
217{
218 s->len = 0;
219}
220
221static notrace void
222trace_print_seq(struct seq_file *m, struct trace_seq *s)
223{
224 int len = s->len >= PAGE_SIZE ? PAGE_SIZE - 1 : s->len;
225
226 s->buffer[len] = 0;
227 seq_puts(m, s->buffer);
228
229 trace_seq_reset(s);
230}
231
172notrace static void 232notrace static void
173flip_trace(struct trace_array_cpu *tr1, struct trace_array_cpu *tr2) 233flip_trace(struct trace_array_cpu *tr1, struct trace_array_cpu *tr2)
174{ 234{
@@ -756,25 +816,26 @@ static void s_stop(struct seq_file *m, void *p)
756} 816}
757 817
758static void 818static void
759seq_print_sym_short(struct seq_file *m, const char *fmt, unsigned long address) 819seq_print_sym_short(struct trace_seq *s, const char *fmt, unsigned long address)
760{ 820{
761#ifdef CONFIG_KALLSYMS 821#ifdef CONFIG_KALLSYMS
762 char str[KSYM_SYMBOL_LEN]; 822 char str[KSYM_SYMBOL_LEN];
763 823
764 kallsyms_lookup(address, NULL, NULL, NULL, str); 824 kallsyms_lookup(address, NULL, NULL, NULL, str);
765 825
766 seq_printf(m, fmt, str); 826 trace_seq_printf(s, fmt, str);
767#endif 827#endif
768} 828}
769 829
770static void 830static void
771seq_print_sym_offset(struct seq_file *m, const char *fmt, unsigned long address) 831seq_print_sym_offset(struct trace_seq *s, const char *fmt,
832 unsigned long address)
772{ 833{
773#ifdef CONFIG_KALLSYMS 834#ifdef CONFIG_KALLSYMS
774 char str[KSYM_SYMBOL_LEN]; 835 char str[KSYM_SYMBOL_LEN];
775 836
776 sprint_symbol(str, address); 837 sprint_symbol(str, address);
777 seq_printf(m, fmt, str); 838 trace_seq_printf(s, fmt, str);
778#endif 839#endif
779} 840}
780 841
@@ -785,20 +846,20 @@ seq_print_sym_offset(struct seq_file *m, const char *fmt, unsigned long address)
785#endif 846#endif
786 847
787static notrace void 848static notrace void
788seq_print_ip_sym(struct seq_file *m, unsigned long ip, unsigned long sym_flags) 849seq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags)
789{ 850{
790 if (!ip) { 851 if (!ip) {
791 seq_printf(m, "0"); 852 trace_seq_printf(s, "0");
792 return; 853 return;
793 } 854 }
794 855
795 if (sym_flags & TRACE_ITER_SYM_OFFSET) 856 if (sym_flags & TRACE_ITER_SYM_OFFSET)
796 seq_print_sym_offset(m, "%s", ip); 857 seq_print_sym_offset(s, "%s", ip);
797 else 858 else
798 seq_print_sym_short(m, "%s", ip); 859 seq_print_sym_short(s, "%s", ip);
799 860
800 if (sym_flags & TRACE_ITER_SYM_ADDR) 861 if (sym_flags & TRACE_ITER_SYM_ADDR)
801 seq_printf(m, " <" IP_FMT ">", ip); 862 trace_seq_printf(s, " <" IP_FMT ">", ip);
802} 863}
803 864
804static notrace void print_lat_help_header(struct seq_file *m) 865static notrace void print_lat_help_header(struct seq_file *m)
@@ -881,9 +942,11 @@ print_trace_header(struct seq_file *m, struct trace_iterator *iter)
881 942
882 if (data->critical_start) { 943 if (data->critical_start) {
883 seq_puts(m, " => started at: "); 944 seq_puts(m, " => started at: ");
884 seq_print_ip_sym(m, data->critical_start, sym_flags); 945 seq_print_ip_sym(&iter->seq, data->critical_start, sym_flags);
946 trace_print_seq(m, &iter->seq);
885 seq_puts(m, "\n => ended at: "); 947 seq_puts(m, "\n => ended at: ");
886 seq_print_ip_sym(m, data->critical_end, sym_flags); 948 seq_print_ip_sym(&iter->seq, data->critical_end, sym_flags);
949 trace_print_seq(m, &iter->seq);
887 seq_puts(m, "\n"); 950 seq_puts(m, "\n");
888 } 951 }
889 952
@@ -891,61 +954,61 @@ print_trace_header(struct seq_file *m, struct trace_iterator *iter)
891} 954}
892 955
893static notrace void 956static notrace void
894lat_print_generic(struct seq_file *m, struct trace_entry *entry, int cpu) 957lat_print_generic(struct trace_seq *s, struct trace_entry *entry, int cpu)
895{ 958{
896 int hardirq, softirq; 959 int hardirq, softirq;
897 char *comm; 960 char *comm;
898 961
899 comm = trace_find_cmdline(entry->pid); 962 comm = trace_find_cmdline(entry->pid);
900 963
901 seq_printf(m, "%8.8s-%-5d ", comm, entry->pid); 964 trace_seq_printf(s, "%8.8s-%-5d ", comm, entry->pid);
902 seq_printf(m, "%d", cpu); 965 trace_seq_printf(s, "%d", cpu);
903 seq_printf(m, "%c%c", 966 trace_seq_printf(s, "%c%c",
904 (entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' : '.', 967 (entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' : '.',
905 ((entry->flags & TRACE_FLAG_NEED_RESCHED) ? 'N' : '.')); 968 ((entry->flags & TRACE_FLAG_NEED_RESCHED) ? 'N' : '.'));
906 969
907 hardirq = entry->flags & TRACE_FLAG_HARDIRQ; 970 hardirq = entry->flags & TRACE_FLAG_HARDIRQ;
908 softirq = entry->flags & TRACE_FLAG_SOFTIRQ; 971 softirq = entry->flags & TRACE_FLAG_SOFTIRQ;
909 if (hardirq && softirq) 972 if (hardirq && softirq)
910 seq_putc(m, 'H'); 973 trace_seq_putc(s, 'H');
911 else { 974 else {
912 if (hardirq) 975 if (hardirq)
913 seq_putc(m, 'h'); 976 trace_seq_putc(s, 'h');
914 else { 977 else {
915 if (softirq) 978 if (softirq)
916 seq_putc(m, 's'); 979 trace_seq_putc(s, 's');
917 else 980 else
918 seq_putc(m, '.'); 981 trace_seq_putc(s, '.');
919 } 982 }
920 } 983 }
921 984
922 if (entry->preempt_count) 985 if (entry->preempt_count)
923 seq_printf(m, "%x", entry->preempt_count); 986 trace_seq_printf(s, "%x", entry->preempt_count);
924 else 987 else
925 seq_puts(m, "."); 988 trace_seq_puts(s, ".");
926} 989}
927 990
928unsigned long preempt_mark_thresh = 100; 991unsigned long preempt_mark_thresh = 100;
929 992
930static notrace void 993static notrace void
931lat_print_timestamp(struct seq_file *m, unsigned long long abs_usecs, 994lat_print_timestamp(struct trace_seq *s, unsigned long long abs_usecs,
932 unsigned long rel_usecs) 995 unsigned long rel_usecs)
933{ 996{
934 seq_printf(m, " %4lldus", abs_usecs); 997 trace_seq_printf(s, " %4lldus", abs_usecs);
935 if (rel_usecs > preempt_mark_thresh) 998 if (rel_usecs > preempt_mark_thresh)
936 seq_puts(m, "!: "); 999 trace_seq_puts(s, "!: ");
937 else if (rel_usecs > 1) 1000 else if (rel_usecs > 1)
938 seq_puts(m, "+: "); 1001 trace_seq_puts(s, "+: ");
939 else 1002 else
940 seq_puts(m, " : "); 1003 trace_seq_puts(s, " : ");
941} 1004}
942 1005
943static const char state_to_char[] = TASK_STATE_TO_CHAR_STR; 1006static const char state_to_char[] = TASK_STATE_TO_CHAR_STR;
944 1007
945static notrace void 1008static notrace void
946print_lat_fmt(struct seq_file *m, struct trace_iterator *iter, 1009print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)
947 unsigned int trace_idx, int cpu)
948{ 1010{
1011 struct trace_seq *s = &iter->seq;
949 unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK); 1012 unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK);
950 struct trace_entry *next_entry = find_next_entry(iter, NULL); 1013 struct trace_entry *next_entry = find_next_entry(iter, NULL);
951 unsigned long verbose = (trace_flags & TRACE_ITER_VERBOSE); 1014 unsigned long verbose = (trace_flags & TRACE_ITER_VERBOSE);
@@ -962,39 +1025,40 @@ print_lat_fmt(struct seq_file *m, struct trace_iterator *iter,
962 1025
963 if (verbose) { 1026 if (verbose) {
964 comm = trace_find_cmdline(entry->pid); 1027 comm = trace_find_cmdline(entry->pid);
965 seq_printf(m, "%16s %5d %d %d %08x %08x [%08lx]" 1028 trace_seq_printf(s, "%16s %5d %d %d %08x %08x [%08lx]"
966 " %ld.%03ldms (+%ld.%03ldms): ", 1029 " %ld.%03ldms (+%ld.%03ldms): ",
967 comm, 1030 comm,
968 entry->pid, cpu, entry->flags, 1031 entry->pid, cpu, entry->flags,
969 entry->preempt_count, trace_idx, 1032 entry->preempt_count, trace_idx,
970 ns2usecs(entry->t), 1033 ns2usecs(entry->t),
971 abs_usecs/1000, 1034 abs_usecs/1000,
972 abs_usecs % 1000, rel_usecs/1000, rel_usecs % 1000); 1035 abs_usecs % 1000, rel_usecs/1000,
1036 rel_usecs % 1000);
973 } else { 1037 } else {
974 lat_print_generic(m, entry, cpu); 1038 lat_print_generic(s, entry, cpu);
975 lat_print_timestamp(m, abs_usecs, rel_usecs); 1039 lat_print_timestamp(s, abs_usecs, rel_usecs);
976 } 1040 }
977 switch (entry->type) { 1041 switch (entry->type) {
978 case TRACE_FN: 1042 case TRACE_FN:
979 seq_print_ip_sym(m, entry->fn.ip, sym_flags); 1043 seq_print_ip_sym(s, entry->fn.ip, sym_flags);
980 seq_puts(m, " ("); 1044 trace_seq_puts(s, " (");
981 seq_print_ip_sym(m, entry->fn.parent_ip, sym_flags); 1045 seq_print_ip_sym(s, entry->fn.parent_ip, sym_flags);
982 seq_puts(m, ")\n"); 1046 trace_seq_puts(s, ")\n");
983 break; 1047 break;
984 case TRACE_CTX: 1048 case TRACE_CTX:
985 S = entry->ctx.prev_state < sizeof(state_to_char) ? 1049 S = entry->ctx.prev_state < sizeof(state_to_char) ?
986 state_to_char[entry->ctx.prev_state] : 'X'; 1050 state_to_char[entry->ctx.prev_state] : 'X';
987 comm = trace_find_cmdline(entry->ctx.next_pid); 1051 comm = trace_find_cmdline(entry->ctx.next_pid);
988 seq_printf(m, " %d:%d:%c --> %d:%d %s\n", 1052 trace_seq_printf(s, " %d:%d:%c --> %d:%d %s\n",
989 entry->ctx.prev_pid, 1053 entry->ctx.prev_pid,
990 entry->ctx.prev_prio, 1054 entry->ctx.prev_prio,
991 S, 1055 S,
992 entry->ctx.next_pid, 1056 entry->ctx.next_pid,
993 entry->ctx.next_prio, 1057 entry->ctx.next_prio,
994 comm); 1058 comm);
995 break; 1059 break;
996 default: 1060 default:
997 seq_printf(m, "Unknown type %d\n", entry->type); 1061 trace_seq_printf(s, "Unknown type %d\n", entry->type);
998 } 1062 }
999} 1063}
1000 1064
@@ -1026,8 +1090,9 @@ static notrace void sync_time_offset(struct trace_iterator *iter)
1026} 1090}
1027 1091
1028static notrace void 1092static notrace void
1029print_trace_fmt(struct seq_file *m, struct trace_iterator *iter) 1093print_trace_fmt(struct trace_iterator *iter)
1030{ 1094{
1095 struct trace_seq *s = &iter->seq;
1031 unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK); 1096 unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK);
1032 struct trace_entry *entry; 1097 struct trace_entry *entry;
1033 unsigned long usec_rem; 1098 unsigned long usec_rem;
@@ -1045,29 +1110,29 @@ print_trace_fmt(struct seq_file *m, struct trace_iterator *iter)
1045 usec_rem = do_div(t, 1000000ULL); 1110 usec_rem = do_div(t, 1000000ULL);
1046 secs = (unsigned long)t; 1111 secs = (unsigned long)t;
1047 1112
1048 seq_printf(m, "%16s-%-5d ", comm, entry->pid); 1113 trace_seq_printf(s, "%16s-%-5d ", comm, entry->pid);
1049 seq_printf(m, "[%02d] ", iter->cpu); 1114 trace_seq_printf(s, "[%02d] ", iter->cpu);
1050 seq_printf(m, "%5lu.%06lu: ", secs, usec_rem); 1115 trace_seq_printf(s, "%5lu.%06lu: ", secs, usec_rem);
1051 1116
1052 switch (entry->type) { 1117 switch (entry->type) {
1053 case TRACE_FN: 1118 case TRACE_FN:
1054 seq_print_ip_sym(m, entry->fn.ip, sym_flags); 1119 seq_print_ip_sym(s, entry->fn.ip, sym_flags);
1055 if ((sym_flags & TRACE_ITER_PRINT_PARENT) && 1120 if ((sym_flags & TRACE_ITER_PRINT_PARENT) &&
1056 entry->fn.parent_ip) { 1121 entry->fn.parent_ip) {
1057 seq_printf(m, " <-"); 1122 trace_seq_printf(s, " <-");
1058 seq_print_ip_sym(m, entry->fn.parent_ip, sym_flags); 1123 seq_print_ip_sym(s, entry->fn.parent_ip, sym_flags);
1059 } 1124 }
1060 seq_printf(m, "\n"); 1125 trace_seq_printf(s, "\n");
1061 break; 1126 break;
1062 case TRACE_CTX: 1127 case TRACE_CTX:
1063 S = entry->ctx.prev_state < sizeof(state_to_char) ? 1128 S = entry->ctx.prev_state < sizeof(state_to_char) ?
1064 state_to_char[entry->ctx.prev_state] : 'X'; 1129 state_to_char[entry->ctx.prev_state] : 'X';
1065 seq_printf(m, " %d:%d:%c ==> %d:%d\n", 1130 trace_seq_printf(s, " %d:%d:%c ==> %d:%d\n",
1066 entry->ctx.prev_pid, 1131 entry->ctx.prev_pid,
1067 entry->ctx.prev_prio, 1132 entry->ctx.prev_prio,
1068 S, 1133 S,
1069 entry->ctx.next_pid, 1134 entry->ctx.next_pid,
1070 entry->ctx.next_prio); 1135 entry->ctx.next_prio);
1071 break; 1136 break;
1072 } 1137 }
1073} 1138}
@@ -1108,9 +1173,10 @@ static int s_show(struct seq_file *m, void *v)
1108 } 1173 }
1109 } else { 1174 } else {
1110 if (iter->iter_flags & TRACE_FILE_LAT_FMT) 1175 if (iter->iter_flags & TRACE_FILE_LAT_FMT)
1111 print_lat_fmt(m, iter, iter->idx, iter->cpu); 1176 print_lat_fmt(iter, iter->idx, iter->cpu);
1112 else 1177 else
1113 print_trace_fmt(m, iter); 1178 print_trace_fmt(iter);
1179 trace_print_seq(m, &iter->seq);
1114 } 1180 }
1115 1181
1116 return 0; 1182 return 0;
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 0ce127455b4b..f5b32ca0b457 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -111,11 +111,17 @@ struct tracer {
111 int print_max; 111 int print_max;
112}; 112};
113 113
114struct trace_seq {
115 unsigned char buffer[PAGE_SIZE];
116 unsigned int len;
117};
118
114/* 119/*
115 * Trace iterator - used by printout routines who present trace 120 * Trace iterator - used by printout routines who present trace
116 * results to users and which routines might sleep, etc: 121 * results to users and which routines might sleep, etc:
117 */ 122 */
118struct trace_iterator { 123struct trace_iterator {
124 struct trace_seq seq;
119 struct trace_array *tr; 125 struct trace_array *tr;
120 struct tracer *trace; 126 struct tracer *trace;
121 127