From 268b8443b5e1f77277df7c9c15e252a8f655bfc7 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Sun, 25 Jun 2006 05:48:43 -0700 Subject: [PATCH] --- yaml --- r: 29764 b: refs/heads/master c: 76d42bd96984832c4ea8bc8cbd74e496ac31409e h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/mm/filemap.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index 01f2cce6ab1d..de641f8b45c3 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 78dbe706e22f54bce61571ad837238382e1ba5f9 +refs/heads/master: 76d42bd96984832c4ea8bc8cbd74e496ac31409e diff --git a/trunk/mm/filemap.c b/trunk/mm/filemap.c index 1ed4be2a7654..9c7334bafda8 100644 --- a/trunk/mm/filemap.c +++ b/trunk/mm/filemap.c @@ -828,6 +828,32 @@ grab_cache_page_nowait(struct address_space *mapping, unsigned long index) } EXPORT_SYMBOL(grab_cache_page_nowait); +/* + * CD/DVDs are error prone. When a medium error occurs, the driver may fail + * a _large_ part of the i/o request. Imagine the worst scenario: + * + * ---R__________________________________________B__________ + * ^ reading here ^ bad block(assume 4k) + * + * read(R) => miss => readahead(R...B) => media error => frustrating retries + * => failing the whole request => read(R) => read(R+1) => + * readahead(R+1...B+1) => bang => read(R+2) => read(R+3) => + * readahead(R+3...B+2) => bang => read(R+3) => read(R+4) => + * readahead(R+4...B+3) => bang => read(R+4) => read(R+5) => ...... + * + * It is going insane. Fix it by quickly scaling down the readahead size. + */ +static void shrink_readahead_size_eio(struct file *filp, + struct file_ra_state *ra) +{ + if (!ra->ra_pages) + return; + + ra->ra_pages /= 4; + printk(KERN_WARNING "Reducing readahead size to %luK\n", + ra->ra_pages << (PAGE_CACHE_SHIFT - 10)); +} + /** * do_generic_mapping_read - generic file read routine * @mapping: address_space to be read @@ -985,6 +1011,7 @@ void do_generic_mapping_read(struct address_space *mapping, } unlock_page(page); error = -EIO; + shrink_readahead_size_eio(filp, &ra); goto readpage_error; } unlock_page(page); @@ -1522,6 +1549,7 @@ struct page *filemap_nopage(struct vm_area_struct *area, * Things didn't work out. Return zero to tell the * mm layer so, possibly freeing the page cache page first. */ + shrink_readahead_size_eio(file, ra); page_cache_release(page); return NULL; }