diff options
Diffstat (limited to 'mm/filemap.c')
-rw-r--r-- | mm/filemap.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/mm/filemap.c b/mm/filemap.c index 1ed4be2a7654..9c7334bafda8 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -828,6 +828,32 @@ grab_cache_page_nowait(struct address_space *mapping, unsigned long index) | |||
828 | } | 828 | } |
829 | EXPORT_SYMBOL(grab_cache_page_nowait); | 829 | EXPORT_SYMBOL(grab_cache_page_nowait); |
830 | 830 | ||
831 | /* | ||
832 | * CD/DVDs are error prone. When a medium error occurs, the driver may fail | ||
833 | * a _large_ part of the i/o request. Imagine the worst scenario: | ||
834 | * | ||
835 | * ---R__________________________________________B__________ | ||
836 | * ^ reading here ^ bad block(assume 4k) | ||
837 | * | ||
838 | * read(R) => miss => readahead(R...B) => media error => frustrating retries | ||
839 | * => failing the whole request => read(R) => read(R+1) => | ||
840 | * readahead(R+1...B+1) => bang => read(R+2) => read(R+3) => | ||
841 | * readahead(R+3...B+2) => bang => read(R+3) => read(R+4) => | ||
842 | * readahead(R+4...B+3) => bang => read(R+4) => read(R+5) => ...... | ||
843 | * | ||
844 | * It is going insane. Fix it by quickly scaling down the readahead size. | ||
845 | */ | ||
846 | static void shrink_readahead_size_eio(struct file *filp, | ||
847 | struct file_ra_state *ra) | ||
848 | { | ||
849 | if (!ra->ra_pages) | ||
850 | return; | ||
851 | |||
852 | ra->ra_pages /= 4; | ||
853 | printk(KERN_WARNING "Reducing readahead size to %luK\n", | ||
854 | ra->ra_pages << (PAGE_CACHE_SHIFT - 10)); | ||
855 | } | ||
856 | |||
831 | /** | 857 | /** |
832 | * do_generic_mapping_read - generic file read routine | 858 | * do_generic_mapping_read - generic file read routine |
833 | * @mapping: address_space to be read | 859 | * @mapping: address_space to be read |
@@ -985,6 +1011,7 @@ readpage: | |||
985 | } | 1011 | } |
986 | unlock_page(page); | 1012 | unlock_page(page); |
987 | error = -EIO; | 1013 | error = -EIO; |
1014 | shrink_readahead_size_eio(filp, &ra); | ||
988 | goto readpage_error; | 1015 | goto readpage_error; |
989 | } | 1016 | } |
990 | unlock_page(page); | 1017 | unlock_page(page); |
@@ -1522,6 +1549,7 @@ page_not_uptodate: | |||
1522 | * Things didn't work out. Return zero to tell the | 1549 | * Things didn't work out. Return zero to tell the |
1523 | * mm layer so, possibly freeing the page cache page first. | 1550 | * mm layer so, possibly freeing the page cache page first. |
1524 | */ | 1551 | */ |
1552 | shrink_readahead_size_eio(file, ra); | ||
1525 | page_cache_release(page); | 1553 | page_cache_release(page); |
1526 | return NULL; | 1554 | return NULL; |
1527 | } | 1555 | } |