diff options
Diffstat (limited to 'fs/buffer.c')
-rw-r--r-- | fs/buffer.c | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index 517860f2d75b..d1f1b54d3108 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/hash.h> | 35 | #include <linux/hash.h> |
36 | #include <linux/suspend.h> | 36 | #include <linux/suspend.h> |
37 | #include <linux/buffer_head.h> | 37 | #include <linux/buffer_head.h> |
38 | #include <linux/task_io_accounting_ops.h> | ||
38 | #include <linux/bio.h> | 39 | #include <linux/bio.h> |
39 | #include <linux/notifier.h> | 40 | #include <linux/notifier.h> |
40 | #include <linux/cpu.h> | 41 | #include <linux/cpu.h> |
@@ -724,20 +725,21 @@ int __set_page_dirty_buffers(struct page *page) | |||
724 | } | 725 | } |
725 | spin_unlock(&mapping->private_lock); | 726 | spin_unlock(&mapping->private_lock); |
726 | 727 | ||
727 | if (!TestSetPageDirty(page)) { | 728 | if (TestSetPageDirty(page)) |
728 | write_lock_irq(&mapping->tree_lock); | 729 | return 0; |
729 | if (page->mapping) { /* Race with truncate? */ | 730 | |
730 | if (mapping_cap_account_dirty(mapping)) | 731 | write_lock_irq(&mapping->tree_lock); |
731 | __inc_zone_page_state(page, NR_FILE_DIRTY); | 732 | if (page->mapping) { /* Race with truncate? */ |
732 | radix_tree_tag_set(&mapping->page_tree, | 733 | if (mapping_cap_account_dirty(mapping)) { |
733 | page_index(page), | 734 | __inc_zone_page_state(page, NR_FILE_DIRTY); |
734 | PAGECACHE_TAG_DIRTY); | 735 | task_io_account_write(PAGE_CACHE_SIZE); |
735 | } | 736 | } |
736 | write_unlock_irq(&mapping->tree_lock); | 737 | radix_tree_tag_set(&mapping->page_tree, |
737 | __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); | 738 | page_index(page), PAGECACHE_TAG_DIRTY); |
738 | return 1; | ||
739 | } | 739 | } |
740 | return 0; | 740 | write_unlock_irq(&mapping->tree_lock); |
741 | __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); | ||
742 | return 1; | ||
741 | } | 743 | } |
742 | EXPORT_SYMBOL(__set_page_dirty_buffers); | 744 | EXPORT_SYMBOL(__set_page_dirty_buffers); |
743 | 745 | ||
@@ -2851,8 +2853,13 @@ int try_to_free_buffers(struct page *page) | |||
2851 | * could encounter a non-uptodate page, which is unresolvable. | 2853 | * could encounter a non-uptodate page, which is unresolvable. |
2852 | * This only applies in the rare case where try_to_free_buffers | 2854 | * This only applies in the rare case where try_to_free_buffers |
2853 | * succeeds but the page is not freed. | 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. | ||
2854 | */ | 2860 | */ |
2855 | clear_page_dirty(page); | 2861 | if (test_clear_page_dirty(page)) |
2862 | task_io_account_cancelled_write(PAGE_CACHE_SIZE); | ||
2856 | } | 2863 | } |
2857 | out: | 2864 | out: |
2858 | if (buffers_to_free) { | 2865 | if (buffers_to_free) { |