diff options
author | Jens Axboe <axboe@suse.de> | 2004-10-18 08:56:50 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-10-18 08:56:50 -0700 |
commit | 9ee4f026a1a053c522f93982793d0e29d7db6a1f (patch) | |
tree | 8eb16ea0c6eb4a2875b45927a054052a619bb46c /mm | |
parent | 524396e721dc1a74d0f9f8e6e6667ad6f7dc6ff5 (diff) | |
download | history-9ee4f026a1a053c522f93982793d0e29d7db6a1f.tar.gz |
[PATCH] invalidate page race fix
invalidate_inode_pages() and invalidate_inode_pages2() can mark pages not
uptodate while read() is trying to read from them. This is interpreted as
an I/O error.
Fix that by teaching the invalidate code to leave the page alone if someone
else has a ref on it.
Signed-off-by: Jens Axboe <axboe@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/truncate.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/mm/truncate.c b/mm/truncate.c index 0ab3a157e985f4..7cd2ed501bb2f2 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -79,6 +79,12 @@ invalidate_complete_page(struct address_space *mapping, struct page *page) spin_unlock_irq(&mapping->tree_lock); return 0; } + + BUG_ON(PagePrivate(page)); + if (page_count(page) != 2) { + spin_unlock_irq(&mapping->tree_lock); + return 0; + } __remove_from_page_cache(page); spin_unlock_irq(&mapping->tree_lock); ClearPageUptodate(page); @@ -269,7 +275,11 @@ void invalidate_inode_pages2(struct address_space *mapping) clear_page_dirty(page); ClearPageUptodate(page); } else { - invalidate_complete_page(mapping, page); + if (!invalidate_complete_page(mapping, + page)) { + clear_page_dirty(page); + ClearPageUptodate(page); + } } } unlock_page(page); |