diff options
author | Eric Dumazet <edumazet@google.com> | 2012-06-12 09:24:40 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2012-06-13 15:16:42 -0400 |
commit | 047fe3605235888f3ebcda0c728cb31937eadfe6 (patch) | |
tree | 9c33ef4b076bd54f686afe924cee01e21c55f427 /mm/shmem.c | |
parent | 27e1f9d1cc87be4e53c6eb7158cafc21c4b85a14 (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.c | 3 |
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; |