diff options
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r-- | kernel/trace/trace.c | 170 |
1 files changed, 123 insertions, 47 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 9d20cd9743ef..815c878f409b 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -455,6 +455,9 @@ int __trace_puts(unsigned long ip, const char *str, int size) | |||
455 | unsigned long irq_flags; | 455 | unsigned long irq_flags; |
456 | int alloc; | 456 | int alloc; |
457 | 457 | ||
458 | if (unlikely(tracing_selftest_running || tracing_disabled)) | ||
459 | return 0; | ||
460 | |||
458 | alloc = sizeof(*entry) + size + 2; /* possible \n added */ | 461 | alloc = sizeof(*entry) + size + 2; /* possible \n added */ |
459 | 462 | ||
460 | local_save_flags(irq_flags); | 463 | local_save_flags(irq_flags); |
@@ -495,6 +498,9 @@ int __trace_bputs(unsigned long ip, const char *str) | |||
495 | unsigned long irq_flags; | 498 | unsigned long irq_flags; |
496 | int size = sizeof(struct bputs_entry); | 499 | int size = sizeof(struct bputs_entry); |
497 | 500 | ||
501 | if (unlikely(tracing_selftest_running || tracing_disabled)) | ||
502 | return 0; | ||
503 | |||
498 | local_save_flags(irq_flags); | 504 | local_save_flags(irq_flags); |
499 | buffer = global_trace.trace_buffer.buffer; | 505 | buffer = global_trace.trace_buffer.buffer; |
500 | event = trace_buffer_lock_reserve(buffer, TRACE_BPUTS, size, | 506 | event = trace_buffer_lock_reserve(buffer, TRACE_BPUTS, size, |
@@ -595,6 +601,28 @@ void free_snapshot(struct trace_array *tr) | |||
595 | } | 601 | } |
596 | 602 | ||
597 | /** | 603 | /** |
604 | * tracing_alloc_snapshot - allocate snapshot buffer. | ||
605 | * | ||
606 | * This only allocates the snapshot buffer if it isn't already | ||
607 | * allocated - it doesn't also take a snapshot. | ||
608 | * | ||
609 | * This is meant to be used in cases where the snapshot buffer needs | ||
610 | * to be set up for events that can't sleep but need to be able to | ||
611 | * trigger a snapshot. | ||
612 | */ | ||
613 | int tracing_alloc_snapshot(void) | ||
614 | { | ||
615 | struct trace_array *tr = &global_trace; | ||
616 | int ret; | ||
617 | |||
618 | ret = alloc_snapshot(tr); | ||
619 | WARN_ON(ret < 0); | ||
620 | |||
621 | return ret; | ||
622 | } | ||
623 | EXPORT_SYMBOL_GPL(tracing_alloc_snapshot); | ||
624 | |||
625 | /** | ||
598 | * trace_snapshot_alloc - allocate and take a snapshot of the current buffer. | 626 | * trace_snapshot_alloc - allocate and take a snapshot of the current buffer. |
599 | * | 627 | * |
600 | * This is similar to trace_snapshot(), but it will allocate the | 628 | * This is similar to trace_snapshot(), but it will allocate the |
@@ -607,11 +635,10 @@ void free_snapshot(struct trace_array *tr) | |||
607 | */ | 635 | */ |
608 | void tracing_snapshot_alloc(void) | 636 | void tracing_snapshot_alloc(void) |
609 | { | 637 | { |
610 | struct trace_array *tr = &global_trace; | ||
611 | int ret; | 638 | int ret; |
612 | 639 | ||
613 | ret = alloc_snapshot(tr); | 640 | ret = tracing_alloc_snapshot(); |
614 | if (WARN_ON(ret < 0)) | 641 | if (ret < 0) |
615 | return; | 642 | return; |
616 | 643 | ||
617 | tracing_snapshot(); | 644 | tracing_snapshot(); |
@@ -623,6 +650,12 @@ void tracing_snapshot(void) | |||
623 | WARN_ONCE(1, "Snapshot feature not enabled, but internal snapshot used"); | 650 | WARN_ONCE(1, "Snapshot feature not enabled, but internal snapshot used"); |
624 | } | 651 | } |
625 | EXPORT_SYMBOL_GPL(tracing_snapshot); | 652 | EXPORT_SYMBOL_GPL(tracing_snapshot); |
653 | int tracing_alloc_snapshot(void) | ||
654 | { | ||
655 | WARN_ONCE(1, "Snapshot feature not enabled, but snapshot allocation used"); | ||
656 | return -ENODEV; | ||
657 | } | ||
658 | EXPORT_SYMBOL_GPL(tracing_alloc_snapshot); | ||
626 | void tracing_snapshot_alloc(void) | 659 | void tracing_snapshot_alloc(void) |
627 | { | 660 | { |
628 | /* Give warning */ | 661 | /* Give warning */ |
@@ -3156,19 +3189,23 @@ tracing_write_stub(struct file *filp, const char __user *ubuf, | |||
3156 | return count; | 3189 | return count; |
3157 | } | 3190 | } |
3158 | 3191 | ||
3159 | static loff_t tracing_seek(struct file *file, loff_t offset, int origin) | 3192 | loff_t tracing_lseek(struct file *file, loff_t offset, int whence) |
3160 | { | 3193 | { |
3194 | int ret; | ||
3195 | |||
3161 | if (file->f_mode & FMODE_READ) | 3196 | if (file->f_mode & FMODE_READ) |
3162 | return seq_lseek(file, offset, origin); | 3197 | ret = seq_lseek(file, offset, whence); |
3163 | else | 3198 | else |
3164 | return 0; | 3199 | file->f_pos = ret = 0; |
3200 | |||
3201 | return ret; | ||
3165 | } | 3202 | } |
3166 | 3203 | ||
3167 | static const struct file_operations tracing_fops = { | 3204 | static const struct file_operations tracing_fops = { |
3168 | .open = tracing_open, | 3205 | .open = tracing_open, |
3169 | .read = seq_read, | 3206 | .read = seq_read, |
3170 | .write = tracing_write_stub, | 3207 | .write = tracing_write_stub, |
3171 | .llseek = tracing_seek, | 3208 | .llseek = tracing_lseek, |
3172 | .release = tracing_release, | 3209 | .release = tracing_release, |
3173 | }; | 3210 | }; |
3174 | 3211 | ||
@@ -3488,60 +3525,103 @@ static const char readme_msg[] = | |||
3488 | " instances\t\t- Make sub-buffers with: mkdir instances/foo\n" | 3525 | " instances\t\t- Make sub-buffers with: mkdir instances/foo\n" |
3489 | "\t\t\t Remove sub-buffer with rmdir\n" | 3526 | "\t\t\t Remove sub-buffer with rmdir\n" |
3490 | " trace_options\t\t- Set format or modify how tracing happens\n" | 3527 | " trace_options\t\t- Set format or modify how tracing happens\n" |
3491 | "\t\t\t Disable an option by adding a suffix 'no' to the option name\n" | 3528 | "\t\t\t Disable an option by adding a suffix 'no' to the\n" |
3529 | "\t\t\t option name\n" | ||
3492 | #ifdef CONFIG_DYNAMIC_FTRACE | 3530 | #ifdef CONFIG_DYNAMIC_FTRACE |
3493 | "\n available_filter_functions - list of functions that can be filtered on\n" | 3531 | "\n available_filter_functions - list of functions that can be filtered on\n" |
3494 | " set_ftrace_filter\t- echo function name in here to only trace these functions\n" | 3532 | " set_ftrace_filter\t- echo function name in here to only trace these\n" |
3495 | " accepts: func_full_name, *func_end, func_begin*, *func_middle*\n" | 3533 | "\t\t\t functions\n" |
3496 | " modules: Can select a group via module\n" | 3534 | "\t accepts: func_full_name, *func_end, func_begin*, *func_middle*\n" |
3497 | " Format: :mod:<module-name>\n" | 3535 | "\t modules: Can select a group via module\n" |
3498 | " example: echo :mod:ext3 > set_ftrace_filter\n" | 3536 | "\t Format: :mod:<module-name>\n" |
3499 | " triggers: a command to perform when function is hit\n" | 3537 | "\t example: echo :mod:ext3 > set_ftrace_filter\n" |
3500 | " Format: <function>:<trigger>[:count]\n" | 3538 | "\t triggers: a command to perform when function is hit\n" |
3501 | " trigger: traceon, traceoff\n" | 3539 | "\t Format: <function>:<trigger>[:count]\n" |
3502 | " enable_event:<system>:<event>\n" | 3540 | "\t trigger: traceon, traceoff\n" |
3503 | " disable_event:<system>:<event>\n" | 3541 | "\t\t enable_event:<system>:<event>\n" |
3542 | "\t\t disable_event:<system>:<event>\n" | ||
3504 | #ifdef CONFIG_STACKTRACE | 3543 | #ifdef CONFIG_STACKTRACE |
3505 | " stacktrace\n" | 3544 | "\t\t stacktrace\n" |
3506 | #endif | 3545 | #endif |
3507 | #ifdef CONFIG_TRACER_SNAPSHOT | 3546 | #ifdef CONFIG_TRACER_SNAPSHOT |
3508 | " snapshot\n" | 3547 | "\t\t snapshot\n" |
3509 | #endif | 3548 | #endif |
3510 | " example: echo do_fault:traceoff > set_ftrace_filter\n" | 3549 | "\t example: echo do_fault:traceoff > set_ftrace_filter\n" |
3511 | " echo do_trap:traceoff:3 > set_ftrace_filter\n" | 3550 | "\t echo do_trap:traceoff:3 > set_ftrace_filter\n" |
3512 | " The first one will disable tracing every time do_fault is hit\n" | 3551 | "\t The first one will disable tracing every time do_fault is hit\n" |
3513 | " The second will disable tracing at most 3 times when do_trap is hit\n" | 3552 | "\t The second will disable tracing at most 3 times when do_trap is hit\n" |
3514 | " The first time do trap is hit and it disables tracing, the counter\n" | 3553 | "\t The first time do trap is hit and it disables tracing, the\n" |
3515 | " will decrement to 2. If tracing is already disabled, the counter\n" | 3554 | "\t counter will decrement to 2. If tracing is already disabled,\n" |
3516 | " will not decrement. It only decrements when the trigger did work\n" | 3555 | "\t the counter will not decrement. It only decrements when the\n" |
3517 | " To remove trigger without count:\n" | 3556 | "\t trigger did work\n" |
3518 | " echo '!<function>:<trigger> > set_ftrace_filter\n" | 3557 | "\t To remove trigger without count:\n" |
3519 | " To remove trigger with a count:\n" | 3558 | "\t echo '!<function>:<trigger> > set_ftrace_filter\n" |
3520 | " echo '!<function>:<trigger>:0 > set_ftrace_filter\n" | 3559 | "\t To remove trigger with a count:\n" |
3560 | "\t echo '!<function>:<trigger>:0 > set_ftrace_filter\n" | ||
3521 | " set_ftrace_notrace\t- echo function name in here to never trace.\n" | 3561 | " set_ftrace_notrace\t- echo function name in here to never trace.\n" |
3522 | " accepts: func_full_name, *func_end, func_begin*, *func_middle*\n" | 3562 | "\t accepts: func_full_name, *func_end, func_begin*, *func_middle*\n" |
3523 | " modules: Can select a group via module command :mod:\n" | 3563 | "\t modules: Can select a group via module command :mod:\n" |
3524 | " Does not accept triggers\n" | 3564 | "\t Does not accept triggers\n" |
3525 | #endif /* CONFIG_DYNAMIC_FTRACE */ | 3565 | #endif /* CONFIG_DYNAMIC_FTRACE */ |
3526 | #ifdef CONFIG_FUNCTION_TRACER | 3566 | #ifdef CONFIG_FUNCTION_TRACER |
3527 | " set_ftrace_pid\t- Write pid(s) to only function trace those pids (function)\n" | 3567 | " set_ftrace_pid\t- Write pid(s) to only function trace those pids\n" |
3568 | "\t\t (function)\n" | ||
3528 | #endif | 3569 | #endif |
3529 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 3570 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
3530 | " set_graph_function\t- Trace the nested calls of a function (function_graph)\n" | 3571 | " set_graph_function\t- Trace the nested calls of a function (function_graph)\n" |
3531 | " max_graph_depth\t- Trace a limited depth of nested calls (0 is unlimited)\n" | 3572 | " max_graph_depth\t- Trace a limited depth of nested calls (0 is unlimited)\n" |
3532 | #endif | 3573 | #endif |
3533 | #ifdef CONFIG_TRACER_SNAPSHOT | 3574 | #ifdef CONFIG_TRACER_SNAPSHOT |
3534 | "\n snapshot\t\t- Like 'trace' but shows the content of the static snapshot buffer\n" | 3575 | "\n snapshot\t\t- Like 'trace' but shows the content of the static\n" |
3535 | "\t\t\t Read the contents for more information\n" | 3576 | "\t\t\t snapshot buffer. Read the contents for more\n" |
3577 | "\t\t\t information\n" | ||
3536 | #endif | 3578 | #endif |
3537 | #ifdef CONFIG_STACK_TRACER | 3579 | #ifdef CONFIG_STACK_TRACER |
3538 | " stack_trace\t\t- Shows the max stack trace when active\n" | 3580 | " stack_trace\t\t- Shows the max stack trace when active\n" |
3539 | " stack_max_size\t- Shows current max stack size that was traced\n" | 3581 | " stack_max_size\t- Shows current max stack size that was traced\n" |
3540 | "\t\t\t Write into this file to reset the max size (trigger a new trace)\n" | 3582 | "\t\t\t Write into this file to reset the max size (trigger a\n" |
3583 | "\t\t\t new trace)\n" | ||
3541 | #ifdef CONFIG_DYNAMIC_FTRACE | 3584 | #ifdef CONFIG_DYNAMIC_FTRACE |
3542 | " stack_trace_filter\t- Like set_ftrace_filter but limits what stack_trace traces\n" | 3585 | " stack_trace_filter\t- Like set_ftrace_filter but limits what stack_trace\n" |
3586 | "\t\t\t traces\n" | ||
3543 | #endif | 3587 | #endif |
3544 | #endif /* CONFIG_STACK_TRACER */ | 3588 | #endif /* CONFIG_STACK_TRACER */ |
3589 | " events/\t\t- Directory containing all trace event subsystems:\n" | ||
3590 | " enable\t\t- Write 0/1 to enable/disable tracing of all events\n" | ||
3591 | " events/<system>/\t- Directory containing all trace events for <system>:\n" | ||
3592 | " enable\t\t- Write 0/1 to enable/disable tracing of all <system>\n" | ||
3593 | "\t\t\t events\n" | ||
3594 | " filter\t\t- If set, only events passing filter are traced\n" | ||
3595 | " events/<system>/<event>/\t- Directory containing control files for\n" | ||
3596 | "\t\t\t <event>:\n" | ||
3597 | " enable\t\t- Write 0/1 to enable/disable tracing of <event>\n" | ||
3598 | " filter\t\t- If set, only events passing filter are traced\n" | ||
3599 | " trigger\t\t- If set, a command to perform when event is hit\n" | ||
3600 | "\t Format: <trigger>[:count][if <filter>]\n" | ||
3601 | "\t trigger: traceon, traceoff\n" | ||
3602 | "\t enable_event:<system>:<event>\n" | ||
3603 | "\t disable_event:<system>:<event>\n" | ||
3604 | #ifdef CONFIG_STACKTRACE | ||
3605 | "\t\t stacktrace\n" | ||
3606 | #endif | ||
3607 | #ifdef CONFIG_TRACER_SNAPSHOT | ||
3608 | "\t\t snapshot\n" | ||
3609 | #endif | ||
3610 | "\t example: echo traceoff > events/block/block_unplug/trigger\n" | ||
3611 | "\t echo traceoff:3 > events/block/block_unplug/trigger\n" | ||
3612 | "\t echo 'enable_event:kmem:kmalloc:3 if nr_rq > 1' > \\\n" | ||
3613 | "\t events/block/block_unplug/trigger\n" | ||
3614 | "\t The first disables tracing every time block_unplug is hit.\n" | ||
3615 | "\t The second disables tracing the first 3 times block_unplug is hit.\n" | ||
3616 | "\t The third enables the kmalloc event the first 3 times block_unplug\n" | ||
3617 | "\t is hit and has value of greater than 1 for the 'nr_rq' event field.\n" | ||
3618 | "\t Like function triggers, the counter is only decremented if it\n" | ||
3619 | "\t enabled or disabled tracing.\n" | ||
3620 | "\t To remove a trigger without a count:\n" | ||
3621 | "\t echo '!<trigger> > <system>/<event>/trigger\n" | ||
3622 | "\t To remove a trigger with a count:\n" | ||
3623 | "\t echo '!<trigger>:0 > <system>/<event>/trigger\n" | ||
3624 | "\t Filters can be ignored when removing a trigger.\n" | ||
3545 | ; | 3625 | ; |
3546 | 3626 | ||
3547 | static ssize_t | 3627 | static ssize_t |
@@ -4212,12 +4292,6 @@ out: | |||
4212 | return sret; | 4292 | return sret; |
4213 | } | 4293 | } |
4214 | 4294 | ||
4215 | static void tracing_pipe_buf_release(struct pipe_inode_info *pipe, | ||
4216 | struct pipe_buffer *buf) | ||
4217 | { | ||
4218 | __free_page(buf->page); | ||
4219 | } | ||
4220 | |||
4221 | static void tracing_spd_release_pipe(struct splice_pipe_desc *spd, | 4295 | static void tracing_spd_release_pipe(struct splice_pipe_desc *spd, |
4222 | unsigned int idx) | 4296 | unsigned int idx) |
4223 | { | 4297 | { |
@@ -4229,7 +4303,7 @@ static const struct pipe_buf_operations tracing_pipe_buf_ops = { | |||
4229 | .map = generic_pipe_buf_map, | 4303 | .map = generic_pipe_buf_map, |
4230 | .unmap = generic_pipe_buf_unmap, | 4304 | .unmap = generic_pipe_buf_unmap, |
4231 | .confirm = generic_pipe_buf_confirm, | 4305 | .confirm = generic_pipe_buf_confirm, |
4232 | .release = tracing_pipe_buf_release, | 4306 | .release = generic_pipe_buf_release, |
4233 | .steal = generic_pipe_buf_steal, | 4307 | .steal = generic_pipe_buf_steal, |
4234 | .get = generic_pipe_buf_get, | 4308 | .get = generic_pipe_buf_get, |
4235 | }; | 4309 | }; |
@@ -4913,7 +4987,7 @@ static const struct file_operations snapshot_fops = { | |||
4913 | .open = tracing_snapshot_open, | 4987 | .open = tracing_snapshot_open, |
4914 | .read = seq_read, | 4988 | .read = seq_read, |
4915 | .write = tracing_snapshot_write, | 4989 | .write = tracing_snapshot_write, |
4916 | .llseek = tracing_seek, | 4990 | .llseek = tracing_lseek, |
4917 | .release = tracing_snapshot_release, | 4991 | .release = tracing_snapshot_release, |
4918 | }; | 4992 | }; |
4919 | 4993 | ||
@@ -5883,6 +5957,8 @@ allocate_trace_buffer(struct trace_array *tr, struct trace_buffer *buf, int size | |||
5883 | 5957 | ||
5884 | rb_flags = trace_flags & TRACE_ITER_OVERWRITE ? RB_FL_OVERWRITE : 0; | 5958 | rb_flags = trace_flags & TRACE_ITER_OVERWRITE ? RB_FL_OVERWRITE : 0; |
5885 | 5959 | ||
5960 | buf->tr = tr; | ||
5961 | |||
5886 | buf->buffer = ring_buffer_alloc(size, rb_flags); | 5962 | buf->buffer = ring_buffer_alloc(size, rb_flags); |
5887 | if (!buf->buffer) | 5963 | if (!buf->buffer) |
5888 | return -ENOMEM; | 5964 | return -ENOMEM; |