diff options
author | Jens Axboe <jens.axboe@oracle.com> | 2010-05-20 04:43:18 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2010-05-21 15:12:40 -0400 |
commit | 35f3d14dbbc58447c61e38a162ea10add6b31dc7 (patch) | |
tree | 3e03cd540b7dcdac82195c4e76862c0ce6daaaf0 /kernel | |
parent | 3d42b3612891baecf709d93f28655a6882a65d41 (diff) |
pipe: add support for shrinking and growing pipes
This patch adds F_GETPIPE_SZ and F_SETPIPE_SZ fcntl() actions for
growing and shrinking the size of a pipe and adjusts pipe.c and splice.c
(and relay and network splice) usage to work with these larger (or smaller)
pipes.
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/relay.c | 15 | ||||
-rw-r--r-- | kernel/trace/trace.c | 60 |
2 files changed, 46 insertions, 29 deletions
diff --git a/kernel/relay.c b/kernel/relay.c index 3d97f2821611..4268287148c1 100644 --- a/kernel/relay.c +++ b/kernel/relay.c | |||
@@ -1231,8 +1231,8 @@ static ssize_t subbuf_splice_actor(struct file *in, | |||
1231 | size_t read_subbuf = read_start / subbuf_size; | 1231 | size_t read_subbuf = read_start / subbuf_size; |
1232 | size_t padding = rbuf->padding[read_subbuf]; | 1232 | size_t padding = rbuf->padding[read_subbuf]; |
1233 | size_t nonpad_end = read_subbuf * subbuf_size + subbuf_size - padding; | 1233 | size_t nonpad_end = read_subbuf * subbuf_size + subbuf_size - padding; |
1234 | struct page *pages[PIPE_BUFFERS]; | 1234 | struct page *pages[PIPE_DEF_BUFFERS]; |
1235 | struct partial_page partial[PIPE_BUFFERS]; | 1235 | struct partial_page partial[PIPE_DEF_BUFFERS]; |
1236 | struct splice_pipe_desc spd = { | 1236 | struct splice_pipe_desc spd = { |
1237 | .pages = pages, | 1237 | .pages = pages, |
1238 | .nr_pages = 0, | 1238 | .nr_pages = 0, |
@@ -1245,6 +1245,8 @@ static ssize_t subbuf_splice_actor(struct file *in, | |||
1245 | 1245 | ||
1246 | if (rbuf->subbufs_produced == rbuf->subbufs_consumed) | 1246 | if (rbuf->subbufs_produced == rbuf->subbufs_consumed) |
1247 | return 0; | 1247 | return 0; |
1248 | if (splice_grow_spd(pipe, &spd)) | ||
1249 | return -ENOMEM; | ||
1248 | 1250 | ||
1249 | /* | 1251 | /* |
1250 | * Adjust read len, if longer than what is available | 1252 | * Adjust read len, if longer than what is available |
@@ -1255,7 +1257,7 @@ static ssize_t subbuf_splice_actor(struct file *in, | |||
1255 | subbuf_pages = rbuf->chan->alloc_size >> PAGE_SHIFT; | 1257 | subbuf_pages = rbuf->chan->alloc_size >> PAGE_SHIFT; |
1256 | pidx = (read_start / PAGE_SIZE) % subbuf_pages; | 1258 | pidx = (read_start / PAGE_SIZE) % subbuf_pages; |
1257 | poff = read_start & ~PAGE_MASK; | 1259 | poff = read_start & ~PAGE_MASK; |
1258 | nr_pages = min_t(unsigned int, subbuf_pages, PIPE_BUFFERS); | 1260 | nr_pages = min_t(unsigned int, subbuf_pages, pipe->buffers); |
1259 | 1261 | ||
1260 | for (total_len = 0; spd.nr_pages < nr_pages; spd.nr_pages++) { | 1262 | for (total_len = 0; spd.nr_pages < nr_pages; spd.nr_pages++) { |
1261 | unsigned int this_len, this_end, private; | 1263 | unsigned int this_len, this_end, private; |
@@ -1289,16 +1291,19 @@ static ssize_t subbuf_splice_actor(struct file *in, | |||
1289 | } | 1291 | } |
1290 | } | 1292 | } |
1291 | 1293 | ||
1294 | ret = 0; | ||
1292 | if (!spd.nr_pages) | 1295 | if (!spd.nr_pages) |
1293 | return 0; | 1296 | goto out; |
1294 | 1297 | ||
1295 | ret = *nonpad_ret = splice_to_pipe(pipe, &spd); | 1298 | ret = *nonpad_ret = splice_to_pipe(pipe, &spd); |
1296 | if (ret < 0 || ret < total_len) | 1299 | if (ret < 0 || ret < total_len) |
1297 | return ret; | 1300 | goto out; |
1298 | 1301 | ||
1299 | if (read_start + ret == nonpad_end) | 1302 | if (read_start + ret == nonpad_end) |
1300 | ret += padding; | 1303 | ret += padding; |
1301 | 1304 | ||
1305 | out: | ||
1306 | splice_shrink_spd(pipe, &spd); | ||
1302 | return ret; | 1307 | return ret; |
1303 | } | 1308 | } |
1304 | 1309 | ||
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 44f916a04065..7b155a0e6f31 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -3269,12 +3269,12 @@ static ssize_t tracing_splice_read_pipe(struct file *filp, | |||
3269 | size_t len, | 3269 | size_t len, |
3270 | unsigned int flags) | 3270 | unsigned int flags) |
3271 | { | 3271 | { |
3272 | struct page *pages[PIPE_BUFFERS]; | 3272 | struct page *pages_def[PIPE_DEF_BUFFERS]; |
3273 | struct partial_page partial[PIPE_BUFFERS]; | 3273 | struct partial_page partial_def[PIPE_DEF_BUFFERS]; |
3274 | struct trace_iterator *iter = filp->private_data; | 3274 | struct trace_iterator *iter = filp->private_data; |
3275 | struct splice_pipe_desc spd = { | 3275 | struct splice_pipe_desc spd = { |
3276 | .pages = pages, | 3276 | .pages = pages_def, |
3277 | .partial = partial, | 3277 | .partial = partial_def, |
3278 | .nr_pages = 0, /* This gets updated below. */ | 3278 | .nr_pages = 0, /* This gets updated below. */ |
3279 | .flags = flags, | 3279 | .flags = flags, |
3280 | .ops = &tracing_pipe_buf_ops, | 3280 | .ops = &tracing_pipe_buf_ops, |
@@ -3285,6 +3285,9 @@ static ssize_t tracing_splice_read_pipe(struct file *filp, | |||
3285 | size_t rem; | 3285 | size_t rem; |
3286 | unsigned int i; | 3286 | unsigned int i; |
3287 | 3287 | ||
3288 | if (splice_grow_spd(pipe, &spd)) | ||
3289 | return -ENOMEM; | ||
3290 | |||
3288 | /* copy the tracer to avoid using a global lock all around */ | 3291 | /* copy the tracer to avoid using a global lock all around */ |
3289 | mutex_lock(&trace_types_lock); | 3292 | mutex_lock(&trace_types_lock); |
3290 | if (unlikely(old_tracer != current_trace && current_trace)) { | 3293 | if (unlikely(old_tracer != current_trace && current_trace)) { |
@@ -3315,23 +3318,23 @@ static ssize_t tracing_splice_read_pipe(struct file *filp, | |||
3315 | trace_access_lock(iter->cpu_file); | 3318 | trace_access_lock(iter->cpu_file); |
3316 | 3319 | ||
3317 | /* Fill as many pages as possible. */ | 3320 | /* Fill as many pages as possible. */ |
3318 | for (i = 0, rem = len; i < PIPE_BUFFERS && rem; i++) { | 3321 | for (i = 0, rem = len; i < pipe->buffers && rem; i++) { |
3319 | pages[i] = alloc_page(GFP_KERNEL); | 3322 | spd.pages[i] = alloc_page(GFP_KERNEL); |
3320 | if (!pages[i]) | 3323 | if (!spd.pages[i]) |
3321 | break; | 3324 | break; |
3322 | 3325 | ||
3323 | rem = tracing_fill_pipe_page(rem, iter); | 3326 | rem = tracing_fill_pipe_page(rem, iter); |
3324 | 3327 | ||
3325 | /* Copy the data into the page, so we can start over. */ | 3328 | /* Copy the data into the page, so we can start over. */ |
3326 | ret = trace_seq_to_buffer(&iter->seq, | 3329 | ret = trace_seq_to_buffer(&iter->seq, |
3327 | page_address(pages[i]), | 3330 | page_address(spd.pages[i]), |
3328 | iter->seq.len); | 3331 | iter->seq.len); |
3329 | if (ret < 0) { | 3332 | if (ret < 0) { |
3330 | __free_page(pages[i]); | 3333 | __free_page(spd.pages[i]); |
3331 | break; | 3334 | break; |
3332 | } | 3335 | } |
3333 | partial[i].offset = 0; | 3336 | spd.partial[i].offset = 0; |
3334 | partial[i].len = iter->seq.len; | 3337 | spd.partial[i].len = iter->seq.len; |
3335 | 3338 | ||
3336 | trace_seq_init(&iter->seq); | 3339 | trace_seq_init(&iter->seq); |
3337 | } | 3340 | } |
@@ -3342,12 +3345,14 @@ static ssize_t tracing_splice_read_pipe(struct file *filp, | |||
3342 | 3345 | ||
3343 | spd.nr_pages = i; | 3346 | spd.nr_pages = i; |
3344 | 3347 | ||
3345 | return splice_to_pipe(pipe, &spd); | 3348 | ret = splice_to_pipe(pipe, &spd); |
3349 | out: | ||
3350 | splice_shrink_spd(pipe, &spd); | ||
3351 | return ret; | ||
3346 | 3352 | ||
3347 | out_err: | 3353 | out_err: |
3348 | mutex_unlock(&iter->mutex); | 3354 | mutex_unlock(&iter->mutex); |
3349 | 3355 | goto out; | |
3350 | return ret; | ||
3351 | } | 3356 | } |
3352 | 3357 | ||
3353 | static ssize_t | 3358 | static ssize_t |
@@ -3746,11 +3751,11 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, | |||
3746 | unsigned int flags) | 3751 | unsigned int flags) |
3747 | { | 3752 | { |
3748 | struct ftrace_buffer_info *info = file->private_data; | 3753 | struct ftrace_buffer_info *info = file->private_data; |
3749 | struct partial_page partial[PIPE_BUFFERS]; | 3754 | struct partial_page partial_def[PIPE_DEF_BUFFERS]; |
3750 | struct page *pages[PIPE_BUFFERS]; | 3755 | struct page *pages_def[PIPE_DEF_BUFFERS]; |
3751 | struct splice_pipe_desc spd = { | 3756 | struct splice_pipe_desc spd = { |
3752 | .pages = pages, | 3757 | .pages = pages_def, |
3753 | .partial = partial, | 3758 | .partial = partial_def, |
3754 | .flags = flags, | 3759 | .flags = flags, |
3755 | .ops = &buffer_pipe_buf_ops, | 3760 | .ops = &buffer_pipe_buf_ops, |
3756 | .spd_release = buffer_spd_release, | 3761 | .spd_release = buffer_spd_release, |
@@ -3759,22 +3764,28 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, | |||
3759 | int entries, size, i; | 3764 | int entries, size, i; |
3760 | size_t ret; | 3765 | size_t ret; |
3761 | 3766 | ||
3767 | if (splice_grow_spd(pipe, &spd)) | ||
3768 | return -ENOMEM; | ||
3769 | |||
3762 | if (*ppos & (PAGE_SIZE - 1)) { | 3770 | if (*ppos & (PAGE_SIZE - 1)) { |
3763 | WARN_ONCE(1, "Ftrace: previous read must page-align\n"); | 3771 | WARN_ONCE(1, "Ftrace: previous read must page-align\n"); |
3764 | return -EINVAL; | 3772 | ret = -EINVAL; |
3773 | goto out; | ||
3765 | } | 3774 | } |
3766 | 3775 | ||
3767 | if (len & (PAGE_SIZE - 1)) { | 3776 | if (len & (PAGE_SIZE - 1)) { |
3768 | WARN_ONCE(1, "Ftrace: splice_read should page-align\n"); | 3777 | WARN_ONCE(1, "Ftrace: splice_read should page-align\n"); |
3769 | if (len < PAGE_SIZE) | 3778 | if (len < PAGE_SIZE) { |
3770 | return -EINVAL; | 3779 | ret = -EINVAL; |
3780 | goto out; | ||
3781 | } | ||
3771 | len &= PAGE_MASK; | 3782 | len &= PAGE_MASK; |
3772 | } | 3783 | } |
3773 | 3784 | ||
3774 | trace_access_lock(info->cpu); | 3785 | trace_access_lock(info->cpu); |
3775 | entries = ring_buffer_entries_cpu(info->tr->buffer, info->cpu); | 3786 | entries = ring_buffer_entries_cpu(info->tr->buffer, info->cpu); |
3776 | 3787 | ||
3777 | for (i = 0; i < PIPE_BUFFERS && len && entries; i++, len -= PAGE_SIZE) { | 3788 | for (i = 0; i < pipe->buffers && len && entries; i++, len -= PAGE_SIZE) { |
3778 | struct page *page; | 3789 | struct page *page; |
3779 | int r; | 3790 | int r; |
3780 | 3791 | ||
@@ -3829,11 +3840,12 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, | |||
3829 | else | 3840 | else |
3830 | ret = 0; | 3841 | ret = 0; |
3831 | /* TODO: block */ | 3842 | /* TODO: block */ |
3832 | return ret; | 3843 | goto out; |
3833 | } | 3844 | } |
3834 | 3845 | ||
3835 | ret = splice_to_pipe(pipe, &spd); | 3846 | ret = splice_to_pipe(pipe, &spd); |
3836 | 3847 | splice_shrink_spd(pipe, &spd); | |
3848 | out: | ||
3837 | return ret; | 3849 | return ret; |
3838 | } | 3850 | } |
3839 | 3851 | ||