diff options
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r-- | kernel/trace/trace.c | 60 |
1 files changed, 36 insertions, 24 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 756d7283318b..8a76339a9e65 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -3309,12 +3309,12 @@ static ssize_t tracing_splice_read_pipe(struct file *filp, | |||
3309 | size_t len, | 3309 | size_t len, |
3310 | unsigned int flags) | 3310 | unsigned int flags) |
3311 | { | 3311 | { |
3312 | struct page *pages[PIPE_BUFFERS]; | 3312 | struct page *pages_def[PIPE_DEF_BUFFERS]; |
3313 | struct partial_page partial[PIPE_BUFFERS]; | 3313 | struct partial_page partial_def[PIPE_DEF_BUFFERS]; |
3314 | struct trace_iterator *iter = filp->private_data; | 3314 | struct trace_iterator *iter = filp->private_data; |
3315 | struct splice_pipe_desc spd = { | 3315 | struct splice_pipe_desc spd = { |
3316 | .pages = pages, | 3316 | .pages = pages_def, |
3317 | .partial = partial, | 3317 | .partial = partial_def, |
3318 | .nr_pages = 0, /* This gets updated below. */ | 3318 | .nr_pages = 0, /* This gets updated below. */ |
3319 | .flags = flags, | 3319 | .flags = flags, |
3320 | .ops = &tracing_pipe_buf_ops, | 3320 | .ops = &tracing_pipe_buf_ops, |
@@ -3325,6 +3325,9 @@ static ssize_t tracing_splice_read_pipe(struct file *filp, | |||
3325 | size_t rem; | 3325 | size_t rem; |
3326 | unsigned int i; | 3326 | unsigned int i; |
3327 | 3327 | ||
3328 | if (splice_grow_spd(pipe, &spd)) | ||
3329 | return -ENOMEM; | ||
3330 | |||
3328 | /* copy the tracer to avoid using a global lock all around */ | 3331 | /* copy the tracer to avoid using a global lock all around */ |
3329 | mutex_lock(&trace_types_lock); | 3332 | mutex_lock(&trace_types_lock); |
3330 | if (unlikely(old_tracer != current_trace && current_trace)) { | 3333 | if (unlikely(old_tracer != current_trace && current_trace)) { |
@@ -3355,23 +3358,23 @@ static ssize_t tracing_splice_read_pipe(struct file *filp, | |||
3355 | trace_access_lock(iter->cpu_file); | 3358 | trace_access_lock(iter->cpu_file); |
3356 | 3359 | ||
3357 | /* Fill as many pages as possible. */ | 3360 | /* Fill as many pages as possible. */ |
3358 | for (i = 0, rem = len; i < PIPE_BUFFERS && rem; i++) { | 3361 | for (i = 0, rem = len; i < pipe->buffers && rem; i++) { |
3359 | pages[i] = alloc_page(GFP_KERNEL); | 3362 | spd.pages[i] = alloc_page(GFP_KERNEL); |
3360 | if (!pages[i]) | 3363 | if (!spd.pages[i]) |
3361 | break; | 3364 | break; |
3362 | 3365 | ||
3363 | rem = tracing_fill_pipe_page(rem, iter); | 3366 | rem = tracing_fill_pipe_page(rem, iter); |
3364 | 3367 | ||
3365 | /* Copy the data into the page, so we can start over. */ | 3368 | /* Copy the data into the page, so we can start over. */ |
3366 | ret = trace_seq_to_buffer(&iter->seq, | 3369 | ret = trace_seq_to_buffer(&iter->seq, |
3367 | page_address(pages[i]), | 3370 | page_address(spd.pages[i]), |
3368 | iter->seq.len); | 3371 | iter->seq.len); |
3369 | if (ret < 0) { | 3372 | if (ret < 0) { |
3370 | __free_page(pages[i]); | 3373 | __free_page(spd.pages[i]); |
3371 | break; | 3374 | break; |
3372 | } | 3375 | } |
3373 | partial[i].offset = 0; | 3376 | spd.partial[i].offset = 0; |
3374 | partial[i].len = iter->seq.len; | 3377 | spd.partial[i].len = iter->seq.len; |
3375 | 3378 | ||
3376 | trace_seq_init(&iter->seq); | 3379 | trace_seq_init(&iter->seq); |
3377 | } | 3380 | } |
@@ -3382,12 +3385,14 @@ static ssize_t tracing_splice_read_pipe(struct file *filp, | |||
3382 | 3385 | ||
3383 | spd.nr_pages = i; | 3386 | spd.nr_pages = i; |
3384 | 3387 | ||
3385 | return splice_to_pipe(pipe, &spd); | 3388 | ret = splice_to_pipe(pipe, &spd); |
3389 | out: | ||
3390 | splice_shrink_spd(pipe, &spd); | ||
3391 | return ret; | ||
3386 | 3392 | ||
3387 | out_err: | 3393 | out_err: |
3388 | mutex_unlock(&iter->mutex); | 3394 | mutex_unlock(&iter->mutex); |
3389 | 3395 | goto out; | |
3390 | return ret; | ||
3391 | } | 3396 | } |
3392 | 3397 | ||
3393 | static ssize_t | 3398 | static ssize_t |
@@ -3786,11 +3791,11 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, | |||
3786 | unsigned int flags) | 3791 | unsigned int flags) |
3787 | { | 3792 | { |
3788 | struct ftrace_buffer_info *info = file->private_data; | 3793 | struct ftrace_buffer_info *info = file->private_data; |
3789 | struct partial_page partial[PIPE_BUFFERS]; | 3794 | struct partial_page partial_def[PIPE_DEF_BUFFERS]; |
3790 | struct page *pages[PIPE_BUFFERS]; | 3795 | struct page *pages_def[PIPE_DEF_BUFFERS]; |
3791 | struct splice_pipe_desc spd = { | 3796 | struct splice_pipe_desc spd = { |
3792 | .pages = pages, | 3797 | .pages = pages_def, |
3793 | .partial = partial, | 3798 | .partial = partial_def, |
3794 | .flags = flags, | 3799 | .flags = flags, |
3795 | .ops = &buffer_pipe_buf_ops, | 3800 | .ops = &buffer_pipe_buf_ops, |
3796 | .spd_release = buffer_spd_release, | 3801 | .spd_release = buffer_spd_release, |
@@ -3799,22 +3804,28 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, | |||
3799 | int entries, size, i; | 3804 | int entries, size, i; |
3800 | size_t ret; | 3805 | size_t ret; |
3801 | 3806 | ||
3807 | if (splice_grow_spd(pipe, &spd)) | ||
3808 | return -ENOMEM; | ||
3809 | |||
3802 | if (*ppos & (PAGE_SIZE - 1)) { | 3810 | if (*ppos & (PAGE_SIZE - 1)) { |
3803 | WARN_ONCE(1, "Ftrace: previous read must page-align\n"); | 3811 | WARN_ONCE(1, "Ftrace: previous read must page-align\n"); |
3804 | return -EINVAL; | 3812 | ret = -EINVAL; |
3813 | goto out; | ||
3805 | } | 3814 | } |
3806 | 3815 | ||
3807 | if (len & (PAGE_SIZE - 1)) { | 3816 | if (len & (PAGE_SIZE - 1)) { |
3808 | WARN_ONCE(1, "Ftrace: splice_read should page-align\n"); | 3817 | WARN_ONCE(1, "Ftrace: splice_read should page-align\n"); |
3809 | if (len < PAGE_SIZE) | 3818 | if (len < PAGE_SIZE) { |
3810 | return -EINVAL; | 3819 | ret = -EINVAL; |
3820 | goto out; | ||
3821 | } | ||
3811 | len &= PAGE_MASK; | 3822 | len &= PAGE_MASK; |
3812 | } | 3823 | } |
3813 | 3824 | ||
3814 | trace_access_lock(info->cpu); | 3825 | trace_access_lock(info->cpu); |
3815 | entries = ring_buffer_entries_cpu(info->tr->buffer, info->cpu); | 3826 | entries = ring_buffer_entries_cpu(info->tr->buffer, info->cpu); |
3816 | 3827 | ||
3817 | for (i = 0; i < PIPE_BUFFERS && len && entries; i++, len -= PAGE_SIZE) { | 3828 | for (i = 0; i < pipe->buffers && len && entries; i++, len -= PAGE_SIZE) { |
3818 | struct page *page; | 3829 | struct page *page; |
3819 | int r; | 3830 | int r; |
3820 | 3831 | ||
@@ -3869,11 +3880,12 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, | |||
3869 | else | 3880 | else |
3870 | ret = 0; | 3881 | ret = 0; |
3871 | /* TODO: block */ | 3882 | /* TODO: block */ |
3872 | return ret; | 3883 | goto out; |
3873 | } | 3884 | } |
3874 | 3885 | ||
3875 | ret = splice_to_pipe(pipe, &spd); | 3886 | ret = splice_to_pipe(pipe, &spd); |
3876 | 3887 | splice_shrink_spd(pipe, &spd); | |
3888 | out: | ||
3877 | return ret; | 3889 | return ret; |
3878 | } | 3890 | } |
3879 | 3891 | ||