aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorJens Axboe <jens.axboe@oracle.com>2010-05-20 04:43:18 -0400
committerJens Axboe <jens.axboe@oracle.com>2010-05-21 15:12:40 -0400
commit35f3d14dbbc58447c61e38a162ea10add6b31dc7 (patch)
tree3e03cd540b7dcdac82195c4e76862c0ce6daaaf0 /kernel
parent3d42b3612891baecf709d93f28655a6882a65d41 (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.c15
-rw-r--r--kernel/trace/trace.c60
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
1305out:
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);
3349out:
3350 splice_shrink_spd(pipe, &spd);
3351 return ret;
3346 3352
3347out_err: 3353out_err:
3348 mutex_unlock(&iter->mutex); 3354 mutex_unlock(&iter->mutex);
3349 3355 goto out;
3350 return ret;
3351} 3356}
3352 3357
3353static ssize_t 3358static 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);
3848out:
3837 return ret; 3849 return ret;
3838} 3850}
3839 3851