diff options
Diffstat (limited to 'kernel/trace/trace_output.c')
-rw-r--r-- | kernel/trace/trace_output.c | 98 |
1 files changed, 75 insertions, 23 deletions
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c index f572f44c6e1e..8e46b3323cdc 100644 --- a/kernel/trace/trace_output.c +++ b/kernel/trace/trace_output.c | |||
@@ -23,13 +23,21 @@ static struct hlist_head event_hash[EVENT_HASHSIZE] __read_mostly; | |||
23 | 23 | ||
24 | static int next_event_type = __TRACE_LAST_TYPE + 1; | 24 | static int next_event_type = __TRACE_LAST_TYPE + 1; |
25 | 25 | ||
26 | void trace_print_seq(struct seq_file *m, struct trace_seq *s) | 26 | int trace_print_seq(struct seq_file *m, struct trace_seq *s) |
27 | { | 27 | { |
28 | int len = s->len >= PAGE_SIZE ? PAGE_SIZE - 1 : s->len; | 28 | int len = s->len >= PAGE_SIZE ? PAGE_SIZE - 1 : s->len; |
29 | int ret; | ||
30 | |||
31 | ret = seq_write(m, s->buffer, len); | ||
29 | 32 | ||
30 | seq_write(m, s->buffer, len); | 33 | /* |
34 | * Only reset this buffer if we successfully wrote to the | ||
35 | * seq_file buffer. | ||
36 | */ | ||
37 | if (!ret) | ||
38 | trace_seq_init(s); | ||
31 | 39 | ||
32 | trace_seq_init(s); | 40 | return ret; |
33 | } | 41 | } |
34 | 42 | ||
35 | enum print_line_t trace_print_bprintk_msg_only(struct trace_iterator *iter) | 43 | enum print_line_t trace_print_bprintk_msg_only(struct trace_iterator *iter) |
@@ -69,6 +77,9 @@ enum print_line_t trace_print_printk_msg_only(struct trace_iterator *iter) | |||
69 | * @s: trace sequence descriptor | 77 | * @s: trace sequence descriptor |
70 | * @fmt: printf format string | 78 | * @fmt: printf format string |
71 | * | 79 | * |
80 | * It returns 0 if the trace oversizes the buffer's free | ||
81 | * space, 1 otherwise. | ||
82 | * | ||
72 | * The tracer may use either sequence operations or its own | 83 | * The tracer may use either sequence operations or its own |
73 | * copy to user routines. To simplify formating of a trace | 84 | * copy to user routines. To simplify formating of a trace |
74 | * trace_seq_printf is used to store strings into a special | 85 | * trace_seq_printf is used to store strings into a special |
@@ -82,7 +93,7 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...) | |||
82 | va_list ap; | 93 | va_list ap; |
83 | int ret; | 94 | int ret; |
84 | 95 | ||
85 | if (!len) | 96 | if (s->full || !len) |
86 | return 0; | 97 | return 0; |
87 | 98 | ||
88 | va_start(ap, fmt); | 99 | va_start(ap, fmt); |
@@ -90,12 +101,14 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...) | |||
90 | va_end(ap); | 101 | va_end(ap); |
91 | 102 | ||
92 | /* If we can't write it all, don't bother writing anything */ | 103 | /* If we can't write it all, don't bother writing anything */ |
93 | if (ret >= len) | 104 | if (ret >= len) { |
105 | s->full = 1; | ||
94 | return 0; | 106 | return 0; |
107 | } | ||
95 | 108 | ||
96 | s->len += ret; | 109 | s->len += ret; |
97 | 110 | ||
98 | return len; | 111 | return 1; |
99 | } | 112 | } |
100 | EXPORT_SYMBOL_GPL(trace_seq_printf); | 113 | EXPORT_SYMBOL_GPL(trace_seq_printf); |
101 | 114 | ||
@@ -116,14 +129,16 @@ trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args) | |||
116 | int len = (PAGE_SIZE - 1) - s->len; | 129 | int len = (PAGE_SIZE - 1) - s->len; |
117 | int ret; | 130 | int ret; |
118 | 131 | ||
119 | if (!len) | 132 | if (s->full || !len) |
120 | return 0; | 133 | return 0; |
121 | 134 | ||
122 | ret = vsnprintf(s->buffer + s->len, len, fmt, args); | 135 | ret = vsnprintf(s->buffer + s->len, len, fmt, args); |
123 | 136 | ||
124 | /* If we can't write it all, don't bother writing anything */ | 137 | /* If we can't write it all, don't bother writing anything */ |
125 | if (ret >= len) | 138 | if (ret >= len) { |
139 | s->full = 1; | ||
126 | return 0; | 140 | return 0; |
141 | } | ||
127 | 142 | ||
128 | s->len += ret; | 143 | s->len += ret; |
129 | 144 | ||
@@ -136,14 +151,16 @@ int trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary) | |||
136 | int len = (PAGE_SIZE - 1) - s->len; | 151 | int len = (PAGE_SIZE - 1) - s->len; |
137 | int ret; | 152 | int ret; |
138 | 153 | ||
139 | if (!len) | 154 | if (s->full || !len) |
140 | return 0; | 155 | return 0; |
141 | 156 | ||
142 | ret = bstr_printf(s->buffer + s->len, len, fmt, binary); | 157 | ret = bstr_printf(s->buffer + s->len, len, fmt, binary); |
143 | 158 | ||
144 | /* If we can't write it all, don't bother writing anything */ | 159 | /* If we can't write it all, don't bother writing anything */ |
145 | if (ret >= len) | 160 | if (ret >= len) { |
161 | s->full = 1; | ||
146 | return 0; | 162 | return 0; |
163 | } | ||
147 | 164 | ||
148 | s->len += ret; | 165 | s->len += ret; |
149 | 166 | ||
@@ -164,9 +181,14 @@ int trace_seq_puts(struct trace_seq *s, const char *str) | |||
164 | { | 181 | { |
165 | int len = strlen(str); | 182 | int len = strlen(str); |
166 | 183 | ||
167 | if (len > ((PAGE_SIZE - 1) - s->len)) | 184 | if (s->full) |
168 | return 0; | 185 | return 0; |
169 | 186 | ||
187 | if (len > ((PAGE_SIZE - 1) - s->len)) { | ||
188 | s->full = 1; | ||
189 | return 0; | ||
190 | } | ||
191 | |||
170 | memcpy(s->buffer + s->len, str, len); | 192 | memcpy(s->buffer + s->len, str, len); |
171 | s->len += len; | 193 | s->len += len; |
172 | 194 | ||
@@ -175,9 +197,14 @@ int trace_seq_puts(struct trace_seq *s, const char *str) | |||
175 | 197 | ||
176 | int trace_seq_putc(struct trace_seq *s, unsigned char c) | 198 | int trace_seq_putc(struct trace_seq *s, unsigned char c) |
177 | { | 199 | { |
178 | if (s->len >= (PAGE_SIZE - 1)) | 200 | if (s->full) |
179 | return 0; | 201 | return 0; |
180 | 202 | ||
203 | if (s->len >= (PAGE_SIZE - 1)) { | ||
204 | s->full = 1; | ||
205 | return 0; | ||
206 | } | ||
207 | |||
181 | s->buffer[s->len++] = c; | 208 | s->buffer[s->len++] = c; |
182 | 209 | ||
183 | return 1; | 210 | return 1; |
@@ -185,8 +212,13 @@ int trace_seq_putc(struct trace_seq *s, unsigned char c) | |||
185 | 212 | ||
186 | int trace_seq_putmem(struct trace_seq *s, const void *mem, size_t len) | 213 | int trace_seq_putmem(struct trace_seq *s, const void *mem, size_t len) |
187 | { | 214 | { |
188 | if (len > ((PAGE_SIZE - 1) - s->len)) | 215 | if (s->full) |
216 | return 0; | ||
217 | |||
218 | if (len > ((PAGE_SIZE - 1) - s->len)) { | ||
219 | s->full = 1; | ||
189 | return 0; | 220 | return 0; |
221 | } | ||
190 | 222 | ||
191 | memcpy(s->buffer + s->len, mem, len); | 223 | memcpy(s->buffer + s->len, mem, len); |
192 | s->len += len; | 224 | s->len += len; |
@@ -200,6 +232,9 @@ int trace_seq_putmem_hex(struct trace_seq *s, const void *mem, size_t len) | |||
200 | const unsigned char *data = mem; | 232 | const unsigned char *data = mem; |
201 | int i, j; | 233 | int i, j; |
202 | 234 | ||
235 | if (s->full) | ||
236 | return 0; | ||
237 | |||
203 | #ifdef __BIG_ENDIAN | 238 | #ifdef __BIG_ENDIAN |
204 | for (i = 0, j = 0; i < len; i++) { | 239 | for (i = 0, j = 0; i < len; i++) { |
205 | #else | 240 | #else |
@@ -217,8 +252,13 @@ void *trace_seq_reserve(struct trace_seq *s, size_t len) | |||
217 | { | 252 | { |
218 | void *ret; | 253 | void *ret; |
219 | 254 | ||
220 | if (len > ((PAGE_SIZE - 1) - s->len)) | 255 | if (s->full) |
256 | return 0; | ||
257 | |||
258 | if (len > ((PAGE_SIZE - 1) - s->len)) { | ||
259 | s->full = 1; | ||
221 | return NULL; | 260 | return NULL; |
261 | } | ||
222 | 262 | ||
223 | ret = s->buffer + s->len; | 263 | ret = s->buffer + s->len; |
224 | s->len += len; | 264 | s->len += len; |
@@ -230,8 +270,14 @@ int trace_seq_path(struct trace_seq *s, struct path *path) | |||
230 | { | 270 | { |
231 | unsigned char *p; | 271 | unsigned char *p; |
232 | 272 | ||
233 | if (s->len >= (PAGE_SIZE - 1)) | 273 | if (s->full) |
274 | return 0; | ||
275 | |||
276 | if (s->len >= (PAGE_SIZE - 1)) { | ||
277 | s->full = 1; | ||
234 | return 0; | 278 | return 0; |
279 | } | ||
280 | |||
235 | p = d_path(path, s->buffer + s->len, PAGE_SIZE - s->len); | 281 | p = d_path(path, s->buffer + s->len, PAGE_SIZE - s->len); |
236 | if (!IS_ERR(p)) { | 282 | if (!IS_ERR(p)) { |
237 | p = mangle_path(s->buffer + s->len, p, "\n"); | 283 | p = mangle_path(s->buffer + s->len, p, "\n"); |
@@ -244,6 +290,7 @@ int trace_seq_path(struct trace_seq *s, struct path *path) | |||
244 | return 1; | 290 | return 1; |
245 | } | 291 | } |
246 | 292 | ||
293 | s->full = 1; | ||
247 | return 0; | 294 | return 0; |
248 | } | 295 | } |
249 | 296 | ||
@@ -370,6 +417,9 @@ int seq_print_user_ip(struct trace_seq *s, struct mm_struct *mm, | |||
370 | unsigned long vmstart = 0; | 417 | unsigned long vmstart = 0; |
371 | int ret = 1; | 418 | int ret = 1; |
372 | 419 | ||
420 | if (s->full) | ||
421 | return 0; | ||
422 | |||
373 | if (mm) { | 423 | if (mm) { |
374 | const struct vm_area_struct *vma; | 424 | const struct vm_area_struct *vma; |
375 | 425 | ||
@@ -486,16 +536,18 @@ int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry) | |||
486 | hardirq ? 'h' : softirq ? 's' : '.')) | 536 | hardirq ? 'h' : softirq ? 's' : '.')) |
487 | return 0; | 537 | return 0; |
488 | 538 | ||
489 | if (entry->lock_depth < 0) | 539 | if (entry->preempt_count) |
490 | ret = trace_seq_putc(s, '.'); | 540 | ret = trace_seq_printf(s, "%x", entry->preempt_count); |
491 | else | 541 | else |
492 | ret = trace_seq_printf(s, "%d", entry->lock_depth); | 542 | ret = trace_seq_putc(s, '.'); |
543 | |||
493 | if (!ret) | 544 | if (!ret) |
494 | return 0; | 545 | return 0; |
495 | 546 | ||
496 | if (entry->preempt_count) | 547 | if (entry->lock_depth < 0) |
497 | return trace_seq_printf(s, "%x", entry->preempt_count); | 548 | return trace_seq_putc(s, '.'); |
498 | return trace_seq_putc(s, '.'); | 549 | |
550 | return trace_seq_printf(s, "%d", entry->lock_depth); | ||
499 | } | 551 | } |
500 | 552 | ||
501 | static int | 553 | static int |
@@ -883,7 +935,7 @@ static int trace_ctxwake_raw(struct trace_iterator *iter, char S) | |||
883 | trace_assign_type(field, iter->ent); | 935 | trace_assign_type(field, iter->ent); |
884 | 936 | ||
885 | if (!S) | 937 | if (!S) |
886 | task_state_char(field->prev_state); | 938 | S = task_state_char(field->prev_state); |
887 | T = task_state_char(field->next_state); | 939 | T = task_state_char(field->next_state); |
888 | if (!trace_seq_printf(&iter->seq, "%d %d %c %d %d %d %c\n", | 940 | if (!trace_seq_printf(&iter->seq, "%d %d %c %d %d %d %c\n", |
889 | field->prev_pid, | 941 | field->prev_pid, |
@@ -918,7 +970,7 @@ static int trace_ctxwake_hex(struct trace_iterator *iter, char S) | |||
918 | trace_assign_type(field, iter->ent); | 970 | trace_assign_type(field, iter->ent); |
919 | 971 | ||
920 | if (!S) | 972 | if (!S) |
921 | task_state_char(field->prev_state); | 973 | S = task_state_char(field->prev_state); |
922 | T = task_state_char(field->next_state); | 974 | T = task_state_char(field->next_state); |
923 | 975 | ||
924 | SEQ_PUT_HEX_FIELD_RET(s, field->prev_pid); | 976 | SEQ_PUT_HEX_FIELD_RET(s, field->prev_pid); |