diff options
| author | Stephen C. Tweedie <sct@redhat.com> | 2005-03-09 16:39:55 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-03-09 16:39:55 -0800 |
| commit | f9e697a27f5ca0432289b30cbda83882bdce7643 (patch) | |
| tree | a08c9eed8855e81bb1855b65efeecd8ad7ba5e05 | |
| parent | cbd24e681028a12fef694e6152aa1f0a8845b9f3 (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.c | 18 |
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); } } |
