diff options
author | Ram Pai <linuxram@us.ibm.com> | 2004-09-07 17:50:22 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-09-07 17:50:22 -0700 |
commit | 5c689659b4056c0b4f70d10654d2c713fe2cf3d6 (patch) | |
tree | fb33374ce4ac71e07bd7991041c24f5ab2c759c2 /mm | |
parent | 22141f0513da328f8f4e405953e5e52fb7c4e65a (diff) | |
download | history-5c689659b4056c0b4f70d10654d2c713fe2cf3d6.tar.gz |
[PATCH] filemap read() fix
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 <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/filemap.c | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/mm/filemap.c b/mm/filemap.c index dfbc5e093b6692..78e18b7639b6aa 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -722,7 +722,10 @@ void do_generic_mapping_read(struct address_space *mapping, 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; @@ -730,6 +733,16 @@ void do_generic_mapping_read(struct address_space *mapping, 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); @@ -742,16 +755,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 @@ -827,11 +830,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: |