aboutsummaryrefslogtreecommitdiffstats
path: root/mm/filemap.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/filemap.c')
-rw-r--r--mm/filemap.c28
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}
829EXPORT_SYMBOL(grab_cache_page_nowait); 829EXPORT_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 */
846static 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}