aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2012-06-12 09:24:40 -0400
committerJens Axboe <axboe@kernel.dk>2012-06-13 15:16:42 -0400
commit047fe3605235888f3ebcda0c728cb31937eadfe6 (patch)
tree9c33ef4b076bd54f686afe924cee01e21c55f427 /kernel
parent27e1f9d1cc87be4e53c6eb7158cafc21c4b85a14 (diff)
splice: fix racy pipe->buffers uses
Dave Jones reported a kernel BUG at mm/slub.c:3474! triggered by splice_shrink_spd() called from vmsplice_to_pipe() commit 35f3d14dbbc5 (pipe: add support for shrinking and growing pipes) added capability to adjust pipe->buffers. Problem is some paths don't hold pipe mutex and assume pipe->buffers doesn't change for their duration. Fix this by adding nr_pages_max field in struct splice_pipe_desc, and use it in place of pipe->buffers where appropriate. splice_shrink_spd() loses its struct pipe_inode_info argument. Reported-by: Dave Jones <davej@redhat.com> Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Jens Axboe <axboe@kernel.dk> Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Tom Herbert <therbert@google.com> Cc: stable <stable@vger.kernel.org> # 2.6.35 Tested-by: Dave Jones <davej@redhat.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/relay.c5
-rw-r--r--kernel/trace/trace.c6
2 files changed, 7 insertions, 4 deletions
diff --git a/kernel/relay.c b/kernel/relay.c
index ab56a1764d4d..e8cd2027abbd 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -1235,6 +1235,7 @@ static ssize_t subbuf_splice_actor(struct file *in,
1235 struct splice_pipe_desc spd = { 1235 struct splice_pipe_desc spd = {
1236 .pages = pages, 1236 .pages = pages,
1237 .nr_pages = 0, 1237 .nr_pages = 0,
1238 .nr_pages_max = PIPE_DEF_BUFFERS,
1238 .partial = partial, 1239 .partial = partial,
1239 .flags = flags, 1240 .flags = flags,
1240 .ops = &relay_pipe_buf_ops, 1241 .ops = &relay_pipe_buf_ops,
@@ -1302,8 +1303,8 @@ static ssize_t subbuf_splice_actor(struct file *in,
1302 ret += padding; 1303 ret += padding;
1303 1304
1304out: 1305out:
1305 splice_shrink_spd(pipe, &spd); 1306 splice_shrink_spd(&spd);
1306 return ret; 1307 return ret;
1307} 1308}
1308 1309
1309static ssize_t relay_file_splice_read(struct file *in, 1310static ssize_t relay_file_splice_read(struct file *in,
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 68032c6177db..288488082224 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -3609,6 +3609,7 @@ static ssize_t tracing_splice_read_pipe(struct file *filp,
3609 .pages = pages_def, 3609 .pages = pages_def,
3610 .partial = partial_def, 3610 .partial = partial_def,
3611 .nr_pages = 0, /* This gets updated below. */ 3611 .nr_pages = 0, /* This gets updated below. */
3612 .nr_pages_max = PIPE_DEF_BUFFERS,
3612 .flags = flags, 3613 .flags = flags,
3613 .ops = &tracing_pipe_buf_ops, 3614 .ops = &tracing_pipe_buf_ops,
3614 .spd_release = tracing_spd_release_pipe, 3615 .spd_release = tracing_spd_release_pipe,
@@ -3680,7 +3681,7 @@ static ssize_t tracing_splice_read_pipe(struct file *filp,
3680 3681
3681 ret = splice_to_pipe(pipe, &spd); 3682 ret = splice_to_pipe(pipe, &spd);
3682out: 3683out:
3683 splice_shrink_spd(pipe, &spd); 3684 splice_shrink_spd(&spd);
3684 return ret; 3685 return ret;
3685 3686
3686out_err: 3687out_err:
@@ -4231,6 +4232,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
4231 struct splice_pipe_desc spd = { 4232 struct splice_pipe_desc spd = {
4232 .pages = pages_def, 4233 .pages = pages_def,
4233 .partial = partial_def, 4234 .partial = partial_def,
4235 .nr_pages_max = PIPE_DEF_BUFFERS,
4234 .flags = flags, 4236 .flags = flags,
4235 .ops = &buffer_pipe_buf_ops, 4237 .ops = &buffer_pipe_buf_ops,
4236 .spd_release = buffer_spd_release, 4238 .spd_release = buffer_spd_release,
@@ -4318,7 +4320,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
4318 } 4320 }
4319 4321
4320 ret = splice_to_pipe(pipe, &spd); 4322 ret = splice_to_pipe(pipe, &spd);
4321 splice_shrink_spd(pipe, &spd); 4323 splice_shrink_spd(&spd);
4322out: 4324out:
4323 return ret; 4325 return ret;
4324} 4326}