aboutsummaryrefslogtreecommitdiffstats
path: root/fs/splice.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/splice.c')
-rw-r--r--fs/splice.c59
1 files changed, 10 insertions, 49 deletions
diff --git a/fs/splice.c b/fs/splice.c
index 9f796b1034d1..8b5efcc906dc 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,
220{ 220{
221 struct address_space *mapping = in->f_mapping; 221 struct address_space *mapping = in->f_mapping;
222 unsigned int offset, nr_pages; 222 unsigned int offset, nr_pages;
223 struct page *pages[PIPE_BUFFERS], *shadow[PIPE_BUFFERS]; 223 struct page *pages[PIPE_BUFFERS];
224 struct page *page; 224 struct page *page;
225 pgoff_t index, pidx; 225 pgoff_t index;
226 int i, j; 226 int i;
227 227
228 index = in->f_pos >> PAGE_CACHE_SHIFT; 228 index = in->f_pos >> PAGE_CACHE_SHIFT;
229 offset = in->f_pos & ~PAGE_CACHE_MASK; 229 offset = in->f_pos & ~PAGE_CACHE_MASK;
@@ -238,41 +238,13 @@ static int __generic_file_splice_read(struct file *in, struct inode *pipe,
238 do_page_cache_readahead(mapping, in, index, nr_pages); 238 do_page_cache_readahead(mapping, in, index, nr_pages);
239 239
240 /* 240 /*
241 * Get as many pages from the page cache as possible..
242 * Start IO on the page cache entries we create (we
243 * can assume that any pre-existing ones we find have
244 * already had IO started on them).
245 */
246 i = find_get_pages(mapping, index, nr_pages, pages);
247
248 /*
249 * common case - we found all pages and they are contiguous,
250 * kick them off
251 */
252 if (i && (pages[i - 1]->index == index + i - 1))
253 goto splice_them;
254
255 /*
256 * fill shadow[] with pages at the right locations, so we only
257 * have to fill holes
258 */
259 memset(shadow, 0, nr_pages * sizeof(struct page *));
260 for (j = 0; j < i; j++)
261 shadow[pages[j]->index - index] = pages[j];
262
263 /*
264 * now fill in the holes 241 * now fill in the holes
265 */ 242 */
266 for (i = 0, pidx = index; i < nr_pages; pidx++, i++) { 243 for (i = 0; i < nr_pages; i++, index++) {
267 int error;
268
269 if (shadow[i])
270 continue;
271
272 /* 244 /*
273 * no page there, look one up / create it 245 * no page there, look one up / create it
274 */ 246 */
275 page = find_or_create_page(mapping, pidx, 247 page = find_or_create_page(mapping, index,
276 mapping_gfp_mask(mapping)); 248 mapping_gfp_mask(mapping));
277 if (!page) 249 if (!page)
278 break; 250 break;
@@ -280,31 +252,20 @@ static int __generic_file_splice_read(struct file *in, struct inode *pipe,
280 if (PageUptodate(page)) 252 if (PageUptodate(page))
281 unlock_page(page); 253 unlock_page(page);
282 else { 254 else {
283 error = mapping->a_ops->readpage(in, page); 255 int error = mapping->a_ops->readpage(in, page);
284 256
285 if (unlikely(error)) { 257 if (unlikely(error)) {
286 page_cache_release(page); 258 page_cache_release(page);
287 break; 259 break;
288 } 260 }
289 } 261 }
290 shadow[i] = page; 262 pages[i] = page;
291 }
292
293 if (!i) {
294 for (i = 0; i < nr_pages; i++) {
295 if (shadow[i])
296 page_cache_release(shadow[i]);
297 }
298 return 0;
299 } 263 }
300 264
301 memcpy(pages, shadow, i * sizeof(struct page *)); 265 if (i)
266 return move_to_pipe(pipe, pages, i, offset, len, flags);
302 267
303 /* 268 return 0;
304 * Now we splice them into the pipe..
305 */
306splice_them:
307 return move_to_pipe(pipe, pages, i, offset, len, flags);
308} 269}
309 270
310/** 271/**