Commit 46fc3e7b4e7233a0ac981ac9084b55217318d04d
Committed by
Linus Torvalds
1 parent
d77c2d7cc5
Exists in
master
and in
4 other branches
readahead: add look-ahead support to __do_page_cache_readahead()
Add look-ahead support to __do_page_cache_readahead(). It works by - mark the Nth backwards page with PG_readahead, (which instructs the page's first reader to invoke readahead) - and only do the marking for newly allocated pages. (to prevent blindly doing readahead on already cached pages) Look-ahead is a technique to achieve I/O pipelining: While the application is working through a chunk of cached pages, the kernel reads-ahead the next chunk of pages _before_ time of need. It effectively hides low level I/O latencies to high level applications. Signed-off-by: Fengguang Wu <wfg@mail.ustc.edu.cn> Cc: Steven Pratt <slpratt@austin.ibm.com> Cc: Ram Pai <linuxram@us.ibm.com> Cc: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 1 changed file with 9 additions and 6 deletions Side-by-side Diff
mm/readahead.c
... | ... | @@ -265,7 +265,8 @@ |
265 | 265 | */ |
266 | 266 | static int |
267 | 267 | __do_page_cache_readahead(struct address_space *mapping, struct file *filp, |
268 | - pgoff_t offset, unsigned long nr_to_read) | |
268 | + pgoff_t offset, unsigned long nr_to_read, | |
269 | + unsigned long lookahead_size) | |
269 | 270 | { |
270 | 271 | struct inode *inode = mapping->host; |
271 | 272 | struct page *page; |
... | ... | @@ -278,7 +279,7 @@ |
278 | 279 | if (isize == 0) |
279 | 280 | goto out; |
280 | 281 | |
281 | - end_index = ((isize - 1) >> PAGE_CACHE_SHIFT); | |
282 | + end_index = ((isize - 1) >> PAGE_CACHE_SHIFT); | |
282 | 283 | |
283 | 284 | /* |
284 | 285 | * Preallocate as many pages as we will need. |
... | ... | @@ -301,6 +302,8 @@ |
301 | 302 | break; |
302 | 303 | page->index = page_offset; |
303 | 304 | list_add(&page->lru, &page_pool); |
305 | + if (page_idx == nr_to_read - lookahead_size) | |
306 | + SetPageReadahead(page); | |
304 | 307 | ret++; |
305 | 308 | } |
306 | 309 | read_unlock_irq(&mapping->tree_lock); |
... | ... | @@ -337,7 +340,7 @@ |
337 | 340 | if (this_chunk > nr_to_read) |
338 | 341 | this_chunk = nr_to_read; |
339 | 342 | err = __do_page_cache_readahead(mapping, filp, |
340 | - offset, this_chunk); | |
343 | + offset, this_chunk, 0); | |
341 | 344 | if (err < 0) { |
342 | 345 | ret = err; |
343 | 346 | break; |
... | ... | @@ -384,7 +387,7 @@ |
384 | 387 | if (bdi_read_congested(mapping->backing_dev_info)) |
385 | 388 | return -1; |
386 | 389 | |
387 | - return __do_page_cache_readahead(mapping, filp, offset, nr_to_read); | |
390 | + return __do_page_cache_readahead(mapping, filp, offset, nr_to_read, 0); | |
388 | 391 | } |
389 | 392 | |
390 | 393 | /* |
... | ... | @@ -404,7 +407,7 @@ |
404 | 407 | if (!block && bdi_read_congested(mapping->backing_dev_info)) |
405 | 408 | return 0; |
406 | 409 | |
407 | - actual = __do_page_cache_readahead(mapping, filp, offset, nr_to_read); | |
410 | + actual = __do_page_cache_readahead(mapping, filp, offset, nr_to_read, 0); | |
408 | 411 | |
409 | 412 | return check_ra_success(ra, nr_to_read, actual); |
410 | 413 | } |
... | ... | @@ -449,7 +452,7 @@ |
449 | 452 | * @req_size: hint: total size of the read which the caller is performing in |
450 | 453 | * PAGE_CACHE_SIZE units |
451 | 454 | * |
452 | - * page_cache_readahead() is the main function. If performs the adaptive | |
455 | + * page_cache_readahead() is the main function. It performs the adaptive | |
453 | 456 | * readahead window size management and submits the readahead I/O. |
454 | 457 | * |
455 | 458 | * Note that @filp is purely used for passing on to the ->readpage[s]() |