summaryrefslogtreecommitdiff
path: root/fs/buffer.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.osdl.org>2006-12-19 15:21:59 -0800
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-21 09:04:31 -0800
commit46d2277c796f9f4937bfa668c40b2e3f43e93dd0 (patch)
treecfde4d8c4b1d721455c978a53e70a55a6c73c3ef /fs/buffer.c
parent9bfb18392ef586467277fa25d8f3a7a93611f6df (diff)
downloadlinux-next-46d2277c796f9f4937bfa668c40b2e3f43e93dd0.tar.gz
Clean up and make try_to_free_buffers() not race with dirty pages
This is preparatory work in our continuing saga on some hard-to-trigger file corruption with shared writable mmap() after the dirty page tracking changes (commit d08b3851da41d0ee60851f2c75b118e1f7a5fc89 etc) were merged. Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/buffer.c')
-rw-r--r--fs/buffer.c18
1 files changed, 1 insertions, 17 deletions
diff --git a/fs/buffer.c b/fs/buffer.c
index d1f1b54d3108..263f88e4dffb 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2834,7 +2834,7 @@ int try_to_free_buffers(struct page *page)
int ret = 0;
BUG_ON(!PageLocked(page));
- if (PageWriteback(page))
+ if (PageDirty(page) || PageWriteback(page))
return 0;
if (mapping == NULL) { /* can this still happen? */
@@ -2845,22 +2845,6 @@ int try_to_free_buffers(struct page *page)
spin_lock(&mapping->private_lock);
ret = drop_buffers(page, &buffers_to_free);
spin_unlock(&mapping->private_lock);
- if (ret) {
- /*
- * If the filesystem writes its buffers by hand (eg ext3)
- * then we can have clean buffers against a dirty page. We
- * clean the page here; otherwise later reattachment of buffers
- * could encounter a non-uptodate page, which is unresolvable.
- * This only applies in the rare case where try_to_free_buffers
- * succeeds but the page is not freed.
- *
- * Also, during truncate, discard_buffer will have marked all
- * the page's buffers clean. We discover that here and clean
- * the page also.
- */
- if (test_clear_page_dirty(page))
- task_io_account_cancelled_write(PAGE_CACHE_SIZE);
- }
out:
if (buffers_to_free) {
struct buffer_head *bh = buffers_to_free;