aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.osdl.org>2006-12-19 18:21:59 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-21 12:04:31 -0500
commit46d2277c796f9f4937bfa668c40b2e3f43e93dd0 (patch)
treecfde4d8c4b1d721455c978a53e70a55a6c73c3ef /fs
parent9bfb18392ef586467277fa25d8f3a7a93611f6df (diff)
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')
-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)
2834 int ret = 0; 2834 int ret = 0;
2835 2835
2836 BUG_ON(!PageLocked(page)); 2836 BUG_ON(!PageLocked(page));
2837 if (PageWriteback(page)) 2837 if (PageDirty(page) || PageWriteback(page))
2838 return 0; 2838 return 0;
2839 2839
2840 if (mapping == NULL) { /* can this still happen? */ 2840 if (mapping == NULL) { /* can this still happen? */
@@ -2845,22 +2845,6 @@ int try_to_free_buffers(struct page *page)
2845 spin_lock(&mapping->private_lock); 2845 spin_lock(&mapping->private_lock);
2846 ret = drop_buffers(page, &buffers_to_free); 2846 ret = drop_buffers(page, &buffers_to_free);
2847 spin_unlock(&mapping->private_lock); 2847 spin_unlock(&mapping->private_lock);
2848 if (ret) {
2849 /*
2850 * If the filesystem writes its buffers by hand (eg ext3)
2851 * then we can have clean buffers against a dirty page. We
2852 * clean the page here; otherwise later reattachment of buffers
2853 * could encounter a non-uptodate page, which is unresolvable.
2854 * This only applies in the rare case where try_to_free_buffers
2855 * succeeds but the page is not freed.
2856 *
2857 * Also, during truncate, discard_buffer will have marked all
2858 * the page's buffers clean. We discover that here and clean
2859 * the page also.
2860 */
2861 if (test_clear_page_dirty(page))
2862 task_io_account_cancelled_write(PAGE_CACHE_SIZE);
2863 }
2864out: 2848out:
2865 if (buffers_to_free) { 2849 if (buffers_to_free) {
2866 struct buffer_head *bh = buffers_to_free; 2850 struct buffer_head *bh = buffers_to_free;