aboutsummaryrefslogtreecommitdiffstats
path: root/mm/shmem.c
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 /mm/shmem.c
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 'mm/shmem.c')
-rw-r--r--mm/shmem.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/mm/shmem.c b/mm/shmem.c
index 585bd220a21e..c244e93a70fa 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1577,6 +1577,7 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
1577 struct splice_pipe_desc spd = { 1577 struct splice_pipe_desc spd = {
1578 .pages = pages, 1578 .pages = pages,
1579 .partial = partial, 1579 .partial = partial,
1580 .nr_pages_max = PIPE_DEF_BUFFERS,
1580 .flags = flags, 1581 .flags = flags,
1581 .ops = &page_cache_pipe_buf_ops, 1582 .ops = &page_cache_pipe_buf_ops,
1582 .spd_release = spd_release_page, 1583 .spd_release = spd_release_page,
@@ -1665,7 +1666,7 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
1665 if (spd.nr_pages) 1666 if (spd.nr_pages)
1666 error = splice_to_pipe(pipe, &spd); 1667 error = splice_to_pipe(pipe, &spd);
1667 1668
1668 splice_shrink_spd(pipe, &spd); 1669 splice_shrink_spd(&spd);
1669 1670
1670 if (error > 0) { 1671 if (error > 0) {
1671 *ppos += error; 1672 *ppos += error;