diff options
Diffstat (limited to 'mm/readahead.c')
| -rw-r--r-- | mm/readahead.c | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/mm/readahead.c b/mm/readahead.c index 8d6eeaaa6296..0f142a40984b 100644 --- a/mm/readahead.c +++ b/mm/readahead.c | |||
| @@ -52,13 +52,24 @@ static inline unsigned long get_min_readahead(struct file_ra_state *ra) | |||
| 52 | return (VM_MIN_READAHEAD * 1024) / PAGE_CACHE_SIZE; | 52 | return (VM_MIN_READAHEAD * 1024) / PAGE_CACHE_SIZE; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | static inline void reset_ahead_window(struct file_ra_state *ra) | ||
| 56 | { | ||
| 57 | /* | ||
| 58 | * ... but preserve ahead_start + ahead_size value, | ||
| 59 | * see 'recheck:' label in page_cache_readahead(). | ||
| 60 | * Note: We never use ->ahead_size as rvalue without | ||
| 61 | * checking ->ahead_start != 0 first. | ||
| 62 | */ | ||
| 63 | ra->ahead_size += ra->ahead_start; | ||
| 64 | ra->ahead_start = 0; | ||
| 65 | } | ||
| 66 | |||
| 55 | static inline void ra_off(struct file_ra_state *ra) | 67 | static inline void ra_off(struct file_ra_state *ra) |
| 56 | { | 68 | { |
| 57 | ra->start = 0; | 69 | ra->start = 0; |
| 58 | ra->flags = 0; | 70 | ra->flags = 0; |
| 59 | ra->size = 0; | 71 | ra->size = 0; |
| 60 | ra->ahead_start = 0; | 72 | reset_ahead_window(ra); |
| 61 | ra->ahead_size = 0; | ||
| 62 | return; | 73 | return; |
| 63 | } | 74 | } |
| 64 | 75 | ||
| @@ -72,10 +83,10 @@ static unsigned long get_init_ra_size(unsigned long size, unsigned long max) | |||
| 72 | { | 83 | { |
| 73 | unsigned long newsize = roundup_pow_of_two(size); | 84 | unsigned long newsize = roundup_pow_of_two(size); |
| 74 | 85 | ||
| 75 | if (newsize <= max / 64) | 86 | if (newsize <= max / 32) |
| 76 | newsize = newsize * newsize; | 87 | newsize = newsize * 4; |
| 77 | else if (newsize <= max / 4) | 88 | else if (newsize <= max / 4) |
| 78 | newsize = max / 4; | 89 | newsize = newsize * 2; |
| 79 | else | 90 | else |
| 80 | newsize = max; | 91 | newsize = max; |
| 81 | return newsize; | 92 | return newsize; |
| @@ -426,8 +437,7 @@ static int make_ahead_window(struct address_space *mapping, struct file *filp, | |||
| 426 | * congestion. The ahead window will any way be closed | 437 | * congestion. The ahead window will any way be closed |
| 427 | * in case we failed due to excessive page cache hits. | 438 | * in case we failed due to excessive page cache hits. |
| 428 | */ | 439 | */ |
| 429 | ra->ahead_start = 0; | 440 | reset_ahead_window(ra); |
| 430 | ra->ahead_size = 0; | ||
| 431 | } | 441 | } |
| 432 | 442 | ||
| 433 | return ret; | 443 | return ret; |
| @@ -520,11 +530,11 @@ page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra, | |||
| 520 | * If we get here we are doing sequential IO and this was not the first | 530 | * If we get here we are doing sequential IO and this was not the first |
| 521 | * occurence (ie we have an existing window) | 531 | * occurence (ie we have an existing window) |
| 522 | */ | 532 | */ |
| 523 | |||
| 524 | if (ra->ahead_start == 0) { /* no ahead window yet */ | 533 | if (ra->ahead_start == 0) { /* no ahead window yet */ |
| 525 | if (!make_ahead_window(mapping, filp, ra, 0)) | 534 | if (!make_ahead_window(mapping, filp, ra, 0)) |
| 526 | goto out; | 535 | goto recheck; |
| 527 | } | 536 | } |
| 537 | |||
| 528 | /* | 538 | /* |
| 529 | * Already have an ahead window, check if we crossed into it. | 539 | * Already have an ahead window, check if we crossed into it. |
| 530 | * If so, shift windows and issue a new ahead window. | 540 | * If so, shift windows and issue a new ahead window. |
| @@ -536,11 +546,16 @@ page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra, | |||
| 536 | ra->start = ra->ahead_start; | 546 | ra->start = ra->ahead_start; |
| 537 | ra->size = ra->ahead_size; | 547 | ra->size = ra->ahead_size; |
| 538 | make_ahead_window(mapping, filp, ra, 0); | 548 | make_ahead_window(mapping, filp, ra, 0); |
| 549 | recheck: | ||
| 550 | /* prev_page shouldn't overrun the ahead window */ | ||
| 551 | ra->prev_page = min(ra->prev_page, | ||
| 552 | ra->ahead_start + ra->ahead_size - 1); | ||
| 539 | } | 553 | } |
| 540 | 554 | ||
| 541 | out: | 555 | out: |
| 542 | return ra->prev_page + 1; | 556 | return ra->prev_page + 1; |
| 543 | } | 557 | } |
| 558 | EXPORT_SYMBOL_GPL(page_cache_readahead); | ||
| 544 | 559 | ||
| 545 | /* | 560 | /* |
| 546 | * handle_ra_miss() is called when it is known that a page which should have | 561 | * handle_ra_miss() is called when it is known that a page which should have |
