mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
splice: fix repeated kmap()'s in default_file_splice_read()
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>
This commit is contained in:
parent
2b1ccc0ee9
commit
4f23122858
10
fs/splice.c
10
fs/splice.c
@ -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++;
|
||||
@ -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;
|
||||
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user