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, ...@@ -722,7 +722,10 @@ void do_generic_mapping_read(struct address_space *mapping,
offset = *ppos & ~PAGE_CACHE_MASK; offset = *ppos & ~PAGE_CACHE_MASK;
isize = i_size_read(inode); 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) if (index > end_index)
goto out; goto out;
...@@ -730,6 +733,16 @@ void do_generic_mapping_read(struct address_space *mapping, ...@@ -730,6 +733,16 @@ void do_generic_mapping_read(struct address_space *mapping,
struct page *page; struct page *page;
unsigned long nr, ret; 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(); cond_resched();
page_cache_readahead(mapping, &ra, filp, index); page_cache_readahead(mapping, &ra, filp, index);
...@@ -742,16 +755,6 @@ void do_generic_mapping_read(struct address_space *mapping, ...@@ -742,16 +755,6 @@ void do_generic_mapping_read(struct address_space *mapping,
if (!PageUptodate(page)) if (!PageUptodate(page))
goto page_not_up_to_date; goto page_not_up_to_date;
page_ok: 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 /* If users can be writing to this page using arbitrary
* virtual addresses, take care about potential aliasing * virtual addresses, take care about potential aliasing
...@@ -827,11 +830,22 @@ void do_generic_mapping_read(struct address_space *mapping, ...@@ -827,11 +830,22 @@ void do_generic_mapping_read(struct address_space *mapping,
* another truncate extends the file - this is desired though). * another truncate extends the file - this is desired though).
*/ */
isize = i_size_read(inode); isize = i_size_read(inode);
end_index = isize >> PAGE_CACHE_SHIFT; end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
if (index > end_index) { if (unlikely(!isize || index > end_index)) {
page_cache_release(page); page_cache_release(page);
goto out; 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; goto page_ok;
readpage_error: 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