summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen C. Tweedie <sct@redhat.com>2005-03-09 16:39:55 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-03-09 16:39:55 -0800
commitf9e697a27f5ca0432289b30cbda83882bdce7643 (patch)
treea08c9eed8855e81bb1855b65efeecd8ad7ba5e05
parentcbd24e681028a12fef694e6152aa1f0a8845b9f3 (diff)
[PATCH] invalidate_inode_pages2_range livelock fix
With Andrew Morton invalidate_inode_pages2_range() can livelock if all the pages in the pagevec are outside the end of teh range which we're trying to invalidate. Fix that up in a similar manner to the truncate_inode_pages_range() handling. Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--mm/truncate.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/mm/truncate.c b/mm/truncate.c
index dafd64ccb73d..c9a63f0b69a2 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -268,25 +268,31 @@ int invalidate_inode_pages2_range(struct address_space *mapping,
min(end - next, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) {
for (i = 0; !ret && i < pagevec_count(&pvec); i++) {
struct page *page = pvec.pages[i];
+ pgoff_t page_index;
int was_dirty;
lock_page(page);
- if (page->mapping != mapping || page->index > end) {
+ if (page->mapping != mapping) {
unlock_page(page);
continue;
}
- wait_on_page_writeback(page);
- next = page->index + 1;
+ page_index = page->index;
+ next = page_index + 1;
if (next == 0)
wrapped = 1;
+ if (page_index > end) {
+ unlock_page(page);
+ break;
+ }
+ wait_on_page_writeback(page);
while (page_mapped(page)) {
if (!did_range_unmap) {
/*
* Zap the rest of the file in one hit.
*/
unmap_mapping_range(mapping,
- page->index << PAGE_CACHE_SHIFT,
- (end - page->index + 1)
+ page_index << PAGE_CACHE_SHIFT,
+ (end - page_index + 1)
<< PAGE_CACHE_SHIFT,
0);
did_range_unmap = 1;
@@ -295,7 +301,7 @@ int invalidate_inode_pages2_range(struct address_space *mapping,
* Just zap this page
*/
unmap_mapping_range(mapping,
- page->index << PAGE_CACHE_SHIFT,
+ page_index << PAGE_CACHE_SHIFT,
PAGE_CACHE_SIZE, 0);
}
}