aboutsummaryrefslogtreecommitdiffstats
path: root/fs/splice.c
diff options
context:
space:
mode:
authorJens Axboe <axboe@suse.de>2006-04-11 07:52:47 -0400
committerJens Axboe <axboe@suse.de>2006-04-11 07:52:47 -0400
commit7480a90435673b4c717b6caf1350ec577d5f1adf (patch)
tree16470986faf89380450da76a928c7856e5a850a1 /fs/splice.c
parentb92ce55893745e011edae70830b8bc863be881f9 (diff)
[PATCH] splice: speedup __generic_file_splice_read
Using find_get_page() is a lot faster than find_or_create_page(). This gets splice a lot closer to sendfile() for fd -> socket transfers. Signed-off-by: Jens Axboe <axboe@suse.de>
Diffstat (limited to 'fs/splice.c')
-rw-r--r--fs/splice.c74
1 files changed, 63 insertions, 11 deletions
diff --git a/fs/splice.c b/fs/splice.c
index c47b561edac0..e30743c2c06a 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -240,7 +240,7 @@ __generic_file_splice_read(struct file *in, struct pipe_inode_info *pipe,
240 struct page *pages[PIPE_BUFFERS]; 240 struct page *pages[PIPE_BUFFERS];
241 struct page *page; 241 struct page *page;
242 pgoff_t index; 242 pgoff_t index;
243 int i; 243 int i, error;
244 244
245 index = in->f_pos >> PAGE_CACHE_SHIFT; 245 index = in->f_pos >> PAGE_CACHE_SHIFT;
246 offset = in->f_pos & ~PAGE_CACHE_MASK; 246 offset = in->f_pos & ~PAGE_CACHE_MASK;
@@ -260,32 +260,84 @@ __generic_file_splice_read(struct file *in, struct pipe_inode_info *pipe,
260 /* 260 /*
261 * now fill in the holes 261 * now fill in the holes
262 */ 262 */
263 error = 0;
263 for (i = 0; i < nr_pages; i++, index++) { 264 for (i = 0; i < nr_pages; i++, index++) {
265find_page:
264 /* 266 /*
265 * no page there, look one up / create it 267 * lookup the page for this index
266 */ 268 */
267 page = find_or_create_page(mapping, index, 269 page = find_get_page(mapping, index);
268 mapping_gfp_mask(mapping)); 270 if (!page) {
269 if (!page) 271 /*
270 break; 272 * If in nonblock mode then dont block on
273 * readpage (we've kicked readahead so there
274 * will be asynchronous progress):
275 */
276 if (flags & SPLICE_F_NONBLOCK)
277 break;
278
279 /*
280 * page didn't exist, allocate one
281 */
282 page = page_cache_alloc_cold(mapping);
283 if (!page)
284 break;
285
286 error = add_to_page_cache_lru(page, mapping, index,
287 mapping_gfp_mask(mapping));
288 if (unlikely(error)) {
289 page_cache_release(page);
290 break;
291 }
271 292
272 if (PageUptodate(page)) 293 goto readpage;
273 unlock_page(page); 294 }
274 else { 295
275 int error = mapping->a_ops->readpage(in, page); 296 /*
297 * If the page isn't uptodate, we may need to start io on it
298 */
299 if (!PageUptodate(page)) {
300 lock_page(page);
301
302 /*
303 * page was truncated, stop here. if this isn't the
304 * first page, we'll just complete what we already
305 * added
306 */
307 if (!page->mapping) {
308 unlock_page(page);
309 page_cache_release(page);
310 break;
311 }
312 /*
313 * page was already under io and is now done, great
314 */
315 if (PageUptodate(page)) {
316 unlock_page(page);
317 goto fill_it;
318 }
319
320readpage:
321 /*
322 * need to read in the page
323 */
324 error = mapping->a_ops->readpage(in, page);
276 325
277 if (unlikely(error)) { 326 if (unlikely(error)) {
278 page_cache_release(page); 327 page_cache_release(page);
328 if (error == AOP_TRUNCATED_PAGE)
329 goto find_page;
279 break; 330 break;
280 } 331 }
281 } 332 }
333fill_it:
282 pages[i] = page; 334 pages[i] = page;
283 } 335 }
284 336
285 if (i) 337 if (i)
286 return move_to_pipe(pipe, pages, i, offset, len, flags); 338 return move_to_pipe(pipe, pages, i, offset, len, flags);
287 339
288 return 0; 340 return error;
289} 341}
290 342
291/** 343/**