Commit 46fc3e7b4e7233a0ac981ac9084b55217318d04d

Authored by Fengguang Wu
Committed by Linus Torvalds
1 parent d77c2d7cc5

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

... ... @@ -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]()