diff options
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r-- | kernel/trace/trace.c | 127 |
1 files changed, 121 insertions, 6 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 5c75deeefe30..fd52a19dd172 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -339,6 +339,112 @@ static struct { | |||
339 | 339 | ||
340 | int trace_clock_id; | 340 | int trace_clock_id; |
341 | 341 | ||
342 | /* | ||
343 | * trace_parser_get_init - gets the buffer for trace parser | ||
344 | */ | ||
345 | int trace_parser_get_init(struct trace_parser *parser, int size) | ||
346 | { | ||
347 | memset(parser, 0, sizeof(*parser)); | ||
348 | |||
349 | parser->buffer = kmalloc(size, GFP_KERNEL); | ||
350 | if (!parser->buffer) | ||
351 | return 1; | ||
352 | |||
353 | parser->size = size; | ||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | /* | ||
358 | * trace_parser_put - frees the buffer for trace parser | ||
359 | */ | ||
360 | void trace_parser_put(struct trace_parser *parser) | ||
361 | { | ||
362 | kfree(parser->buffer); | ||
363 | } | ||
364 | |||
365 | /* | ||
366 | * trace_get_user - reads the user input string separated by space | ||
367 | * (matched by isspace(ch)) | ||
368 | * | ||
369 | * For each string found the 'struct trace_parser' is updated, | ||
370 | * and the function returns. | ||
371 | * | ||
372 | * Returns number of bytes read. | ||
373 | * | ||
374 | * See kernel/trace/trace.h for 'struct trace_parser' details. | ||
375 | */ | ||
376 | int trace_get_user(struct trace_parser *parser, const char __user *ubuf, | ||
377 | size_t cnt, loff_t *ppos) | ||
378 | { | ||
379 | char ch; | ||
380 | size_t read = 0; | ||
381 | ssize_t ret; | ||
382 | |||
383 | if (!*ppos) | ||
384 | trace_parser_clear(parser); | ||
385 | |||
386 | ret = get_user(ch, ubuf++); | ||
387 | if (ret) | ||
388 | goto out; | ||
389 | |||
390 | read++; | ||
391 | cnt--; | ||
392 | |||
393 | /* | ||
394 | * The parser is not finished with the last write, | ||
395 | * continue reading the user input without skipping spaces. | ||
396 | */ | ||
397 | if (!parser->cont) { | ||
398 | /* skip white space */ | ||
399 | while (cnt && isspace(ch)) { | ||
400 | ret = get_user(ch, ubuf++); | ||
401 | if (ret) | ||
402 | goto out; | ||
403 | read++; | ||
404 | cnt--; | ||
405 | } | ||
406 | |||
407 | /* only spaces were written */ | ||
408 | if (isspace(ch)) { | ||
409 | *ppos += read; | ||
410 | ret = read; | ||
411 | goto out; | ||
412 | } | ||
413 | |||
414 | parser->idx = 0; | ||
415 | } | ||
416 | |||
417 | /* read the non-space input */ | ||
418 | while (cnt && !isspace(ch)) { | ||
419 | if (parser->idx < parser->size) | ||
420 | parser->buffer[parser->idx++] = ch; | ||
421 | else { | ||
422 | ret = -EINVAL; | ||
423 | goto out; | ||
424 | } | ||
425 | ret = get_user(ch, ubuf++); | ||
426 | if (ret) | ||
427 | goto out; | ||
428 | read++; | ||
429 | cnt--; | ||
430 | } | ||
431 | |||
432 | /* We either got finished input or we have to wait for another call. */ | ||
433 | if (isspace(ch)) { | ||
434 | parser->buffer[parser->idx] = 0; | ||
435 | parser->cont = false; | ||
436 | } else { | ||
437 | parser->cont = true; | ||
438 | parser->buffer[parser->idx++] = ch; | ||
439 | } | ||
440 | |||
441 | *ppos += read; | ||
442 | ret = read; | ||
443 | |||
444 | out: | ||
445 | return ret; | ||
446 | } | ||
447 | |||
342 | ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, size_t cnt) | 448 | ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, size_t cnt) |
343 | { | 449 | { |
344 | int len; | 450 | int len; |
@@ -719,6 +825,11 @@ static void trace_init_cmdlines(void) | |||
719 | cmdline_idx = 0; | 825 | cmdline_idx = 0; |
720 | } | 826 | } |
721 | 827 | ||
828 | int is_tracing_stopped(void) | ||
829 | { | ||
830 | return trace_stop_count; | ||
831 | } | ||
832 | |||
722 | /** | 833 | /** |
723 | * ftrace_off_permanent - disable all ftrace code permanently | 834 | * ftrace_off_permanent - disable all ftrace code permanently |
724 | * | 835 | * |
@@ -886,7 +997,7 @@ tracing_generic_entry_update(struct trace_entry *entry, unsigned long flags, | |||
886 | 997 | ||
887 | entry->preempt_count = pc & 0xff; | 998 | entry->preempt_count = pc & 0xff; |
888 | entry->pid = (tsk) ? tsk->pid : 0; | 999 | entry->pid = (tsk) ? tsk->pid : 0; |
889 | entry->tgid = (tsk) ? tsk->tgid : 0; | 1000 | entry->lock_depth = (tsk) ? tsk->lock_depth : 0; |
890 | entry->flags = | 1001 | entry->flags = |
891 | #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT | 1002 | #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT |
892 | (irqs_disabled_flags(flags) ? TRACE_FLAG_IRQS_OFF : 0) | | 1003 | (irqs_disabled_flags(flags) ? TRACE_FLAG_IRQS_OFF : 0) | |
@@ -1068,6 +1179,7 @@ ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc) | |||
1068 | return; | 1179 | return; |
1069 | entry = ring_buffer_event_data(event); | 1180 | entry = ring_buffer_event_data(event); |
1070 | 1181 | ||
1182 | entry->tgid = current->tgid; | ||
1071 | memset(&entry->caller, 0, sizeof(entry->caller)); | 1183 | memset(&entry->caller, 0, sizeof(entry->caller)); |
1072 | 1184 | ||
1073 | trace.nr_entries = 0; | 1185 | trace.nr_entries = 0; |
@@ -1094,6 +1206,7 @@ ftrace_trace_special(void *__tr, | |||
1094 | unsigned long arg1, unsigned long arg2, unsigned long arg3, | 1206 | unsigned long arg1, unsigned long arg2, unsigned long arg3, |
1095 | int pc) | 1207 | int pc) |
1096 | { | 1208 | { |
1209 | struct ftrace_event_call *call = &event_special; | ||
1097 | struct ring_buffer_event *event; | 1210 | struct ring_buffer_event *event; |
1098 | struct trace_array *tr = __tr; | 1211 | struct trace_array *tr = __tr; |
1099 | struct ring_buffer *buffer = tr->buffer; | 1212 | struct ring_buffer *buffer = tr->buffer; |
@@ -1107,7 +1220,9 @@ ftrace_trace_special(void *__tr, | |||
1107 | entry->arg1 = arg1; | 1220 | entry->arg1 = arg1; |
1108 | entry->arg2 = arg2; | 1221 | entry->arg2 = arg2; |
1109 | entry->arg3 = arg3; | 1222 | entry->arg3 = arg3; |
1110 | trace_buffer_unlock_commit(buffer, event, 0, pc); | 1223 | |
1224 | if (!filter_check_discard(call, entry, buffer, event)) | ||
1225 | trace_buffer_unlock_commit(buffer, event, 0, pc); | ||
1111 | } | 1226 | } |
1112 | 1227 | ||
1113 | void | 1228 | void |
@@ -1530,10 +1645,10 @@ static void print_lat_help_header(struct seq_file *m) | |||
1530 | seq_puts(m, "# | / _----=> need-resched \n"); | 1645 | seq_puts(m, "# | / _----=> need-resched \n"); |
1531 | seq_puts(m, "# || / _---=> hardirq/softirq \n"); | 1646 | seq_puts(m, "# || / _---=> hardirq/softirq \n"); |
1532 | seq_puts(m, "# ||| / _--=> preempt-depth \n"); | 1647 | seq_puts(m, "# ||| / _--=> preempt-depth \n"); |
1533 | seq_puts(m, "# |||| / \n"); | 1648 | seq_puts(m, "# |||| /_--=> lock-depth \n"); |
1534 | seq_puts(m, "# ||||| delay \n"); | 1649 | seq_puts(m, "# |||||/ delay \n"); |
1535 | seq_puts(m, "# cmd pid ||||| time | caller \n"); | 1650 | seq_puts(m, "# cmd pid |||||| time | caller \n"); |
1536 | seq_puts(m, "# \\ / ||||| \\ | / \n"); | 1651 | seq_puts(m, "# \\ / |||||| \\ | / \n"); |
1537 | } | 1652 | } |
1538 | 1653 | ||
1539 | static void print_func_help_header(struct seq_file *m) | 1654 | static void print_func_help_header(struct seq_file *m) |