diff options
Diffstat (limited to 'fs/splice.c')
-rw-r--r-- | fs/splice.c | 59 |
1 files changed, 10 insertions, 49 deletions
diff --git a/fs/splice.c b/fs/splice.c index 9f796b1034d..8b5efcc906d 100644 --- a/fs/splice.c +++ b/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; unsigned int offset, nr_pages; - struct page *pages[PIPE_BUFFERS], *shadow[PIPE_BUFFERS]; + struct page *pages[PIPE_BUFFERS]; struct page *page; - pgoff_t index, pidx; - int i, j; + pgoff_t index; + int i; index = in->f_pos >> PAGE_CACHE_SHIFT; offset = in->f_pos & ~PAGE_CACHE_MASK; @@ -238,41 +238,13 @@ static int __generic_file_splice_read(struct file *in, struct inode *pipe, 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 */ - for (i = 0, pidx = index; i < nr_pages; pidx++, i++) { - int error; - - if (shadow[i]) - continue; - + for (i = 0; i < nr_pages; i++, index++) { /* * 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)); if (!page) break; @@ -280,31 +252,20 @@ static int __generic_file_splice_read(struct file *in, struct inode *pipe, if (PageUptodate(page)) unlock_page(page); else { - error = mapping->a_ops->readpage(in, page); + int error = mapping->a_ops->readpage(in, page); if (unlikely(error)) { page_cache_release(page); break; } } - shadow[i] = page; - } - - if (!i) { - for (i = 0; i < nr_pages; i++) { - if (shadow[i]) - page_cache_release(shadow[i]); - } - return 0; + pages[i] = page; } - memcpy(pages, shadow, i * sizeof(struct page *)); + if (i) + return move_to_pipe(pipe, pages, i, offset, len, flags); - /* - * Now we splice them into the pipe.. - */ -splice_them: - return move_to_pipe(pipe, pages, i, offset, len, flags); + return 0; } /** |