From: Ram Pai Fix the do_generic_file_read()-reads-one-page-too-many-bug for the fifth time. This patch combines the best features from Nick's patch and also makes index and end_index consistent. (i.e index 'n' covers n*PAGE_SIZE to ((n+1)PAGE_SIZE)-1. I did not feel comfortable with the way index and end_index represented different ranges. It was like comparing apples with oranges. Signed-off-by: Andrew Morton --- 25-akpm/mm/filemap.c | 40 +++++++++++++++++++++++++++------------- 1 files changed, 27 insertions(+), 13 deletions(-) diff -puN mm/filemap.c~filemap-read-fix mm/filemap.c --- 25/mm/filemap.c~filemap-read-fix 2004-08-31 02:15:57.841167392 -0700 +++ 25-akpm/mm/filemap.c 2004-08-31 02:15:57.846166632 -0700 @@ -676,7 +676,10 @@ void do_generic_mapping_read(struct addr offset = *ppos & ~PAGE_CACHE_MASK; isize = i_size_read(inode); - end_index = isize >> PAGE_CACHE_SHIFT; + if (!isize) + goto out; + + end_index = (isize - 1) >> PAGE_CACHE_SHIFT; if (index > end_index) goto out; @@ -684,6 +687,16 @@ void do_generic_mapping_read(struct addr struct page *page; unsigned long nr, ret; + /* nr is the maximum number of bytes to copy from this page */ + nr = PAGE_CACHE_SIZE; + if (index == end_index) { + nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1; + if (nr <= offset) { + goto out; + } + } + nr = nr - offset; + cond_resched(); page_cache_readahead(mapping, &ra, filp, index); @@ -696,16 +709,6 @@ find_page: if (!PageUptodate(page)) goto page_not_up_to_date; page_ok: - /* nr is the maximum number of bytes to copy from this page */ - nr = PAGE_CACHE_SIZE; - if (index == end_index) { - nr = isize & ~PAGE_CACHE_MASK; - if (nr <= offset) { - page_cache_release(page); - goto out; - } - } - nr = nr - offset; /* If users can be writing to this page using arbitrary * virtual addresses, take care about potential aliasing @@ -781,11 +784,22 @@ readpage: * another truncate extends the file - this is desired though). */ isize = i_size_read(inode); - end_index = isize >> PAGE_CACHE_SHIFT; - if (index > end_index) { + end_index = (isize - 1) >> PAGE_CACHE_SHIFT; + if (unlikely(!isize || index > end_index)) { page_cache_release(page); goto out; } + + /* nr is the maximum number of bytes to copy from this page */ + nr = PAGE_CACHE_SIZE; + if (index == end_index) { + nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1; + if (nr <= offset) { + page_cache_release(page); + goto out; + } + } + nr = nr - offset; goto page_ok; readpage_error: _