Commit 5c689659 authored by Ram Pai's avatar Ram Pai Committed by Linus Torvalds

[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: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 22141f05
......@@ -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 @@ void do_generic_mapping_read(struct address_space *mapping,
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 @@ void do_generic_mapping_read(struct address_space *mapping,
* 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:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment