Skip to content

Commit

Permalink
splice: fix repeated kmap()'s in default_file_splice_read()
Browse files Browse the repository at this point in the history
We cannot reliably map more than one page at the time, or we risk
deadlocking. Just allocate the pages from low mem instead.

Reported-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
  • Loading branch information
Jens Axboe committed May 13, 2009
1 parent 2b1ccc0 commit 4f23122
Showing 1 changed file with 4 additions and 6 deletions.
10 changes: 4 additions & 6 deletions fs/splice.c
Original file line number Diff line number Diff line change
Expand Up @@ -580,13 +580,13 @@ ssize_t default_file_splice_read(struct file *in, loff_t *ppos,
for (i = 0; i < nr_pages && i < PIPE_BUFFERS && len; i++) {
struct page *page;

page = alloc_page(GFP_HIGHUSER);
page = alloc_page(GFP_USER);
error = -ENOMEM;
if (!page)
goto err;

this_len = min_t(size_t, len, PAGE_CACHE_SIZE - offset);
vec[i].iov_base = (void __user *) kmap(page);
vec[i].iov_base = (void __user *) page_address(page);
vec[i].iov_len = this_len;
pages[i] = page;
spd.nr_pages++;
Expand All @@ -604,7 +604,6 @@ ssize_t default_file_splice_read(struct file *in, loff_t *ppos,

nr_freed = 0;
for (i = 0; i < spd.nr_pages; i++) {
kunmap(pages[i]);
this_len = min_t(size_t, vec[i].iov_len, res);
partial[i].offset = 0;
partial[i].len = this_len;
Expand All @@ -624,10 +623,9 @@ ssize_t default_file_splice_read(struct file *in, loff_t *ppos,
return res;

err:
for (i = 0; i < spd.nr_pages; i++) {
kunmap(pages[i]);
for (i = 0; i < spd.nr_pages; i++)
__free_page(pages[i]);
}

return error;
}
EXPORT_SYMBOL(default_file_splice_read);
Expand Down

0 comments on commit 4f23122

Please sign in to comment.