[PATCH] splice: cleanup __generic_file_splice_read()
The whole shadow/pages logic got overly complex, and this simpler approach is actually faster in testing. Signed-off-by: Jens Axboe <axboe@suse.de>
This commit is contained in:
parent
c0bd1f650b
commit
16c523ddab
59
fs/splice.c
59
fs/splice.c
@ -220,10 +220,10 @@ static int __generic_file_splice_read(struct file *in, struct inode *pipe,
|
|||||||
{
|
{
|
||||||
struct address_space *mapping = in->f_mapping;
|
struct address_space *mapping = in->f_mapping;
|
||||||
unsigned int offset, nr_pages;
|
unsigned int offset, nr_pages;
|
||||||
struct page *pages[PIPE_BUFFERS], *shadow[PIPE_BUFFERS];
|
struct page *pages[PIPE_BUFFERS];
|
||||||
struct page *page;
|
struct page *page;
|
||||||
pgoff_t index, pidx;
|
pgoff_t index;
|
||||||
int i, j;
|
int i;
|
||||||
|
|
||||||
index = in->f_pos >> PAGE_CACHE_SHIFT;
|
index = in->f_pos >> PAGE_CACHE_SHIFT;
|
||||||
offset = in->f_pos & ~PAGE_CACHE_MASK;
|
offset = in->f_pos & ~PAGE_CACHE_MASK;
|
||||||
@ -237,42 +237,14 @@ static int __generic_file_splice_read(struct file *in, struct inode *pipe,
|
|||||||
*/
|
*/
|
||||||
do_page_cache_readahead(mapping, in, index, nr_pages);
|
do_page_cache_readahead(mapping, in, index, nr_pages);
|
||||||
|
|
||||||
/*
|
|
||||||
* Get as many pages from the page cache as possible..
|
|
||||||
* Start IO on the page cache entries we create (we
|
|
||||||
* can assume that any pre-existing ones we find have
|
|
||||||
* already had IO started on them).
|
|
||||||
*/
|
|
||||||
i = find_get_pages(mapping, index, nr_pages, pages);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* common case - we found all pages and they are contiguous,
|
|
||||||
* kick them off
|
|
||||||
*/
|
|
||||||
if (i && (pages[i - 1]->index == index + i - 1))
|
|
||||||
goto splice_them;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* fill shadow[] with pages at the right locations, so we only
|
|
||||||
* have to fill holes
|
|
||||||
*/
|
|
||||||
memset(shadow, 0, nr_pages * sizeof(struct page *));
|
|
||||||
for (j = 0; j < i; j++)
|
|
||||||
shadow[pages[j]->index - index] = pages[j];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* now fill in the holes
|
* now fill in the holes
|
||||||
*/
|
*/
|
||||||
for (i = 0, pidx = index; i < nr_pages; pidx++, i++) {
|
for (i = 0; i < nr_pages; i++, index++) {
|
||||||
int error;
|
|
||||||
|
|
||||||
if (shadow[i])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* no page there, look one up / create it
|
* no page there, look one up / create it
|
||||||
*/
|
*/
|
||||||
page = find_or_create_page(mapping, pidx,
|
page = find_or_create_page(mapping, index,
|
||||||
mapping_gfp_mask(mapping));
|
mapping_gfp_mask(mapping));
|
||||||
if (!page)
|
if (!page)
|
||||||
break;
|
break;
|
||||||
@ -280,31 +252,20 @@ static int __generic_file_splice_read(struct file *in, struct inode *pipe,
|
|||||||
if (PageUptodate(page))
|
if (PageUptodate(page))
|
||||||
unlock_page(page);
|
unlock_page(page);
|
||||||
else {
|
else {
|
||||||
error = mapping->a_ops->readpage(in, page);
|
int error = mapping->a_ops->readpage(in, page);
|
||||||
|
|
||||||
if (unlikely(error)) {
|
if (unlikely(error)) {
|
||||||
page_cache_release(page);
|
page_cache_release(page);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
shadow[i] = page;
|
pages[i] = page;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!i) {
|
if (i)
|
||||||
for (i = 0; i < nr_pages; i++) {
|
return move_to_pipe(pipe, pages, i, offset, len, flags);
|
||||||
if (shadow[i])
|
|
||||||
page_cache_release(shadow[i]);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(pages, shadow, i * sizeof(struct page *));
|
return 0;
|
||||||
|
|
||||||
/*
|
|
||||||
* Now we splice them into the pipe..
|
|
||||||
*/
|
|
||||||
splice_them:
|
|
||||||
return move_to_pipe(pipe, pages, i, offset, len, flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user