diff options
Diffstat (limited to 'mm/page-writeback.c')
-rw-r--r-- | mm/page-writeback.c | 89 |
1 files changed, 45 insertions, 44 deletions
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 8d9b19f239c3..237107c1b084 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/writeback.h> | 21 | #include <linux/writeback.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/backing-dev.h> | 23 | #include <linux/backing-dev.h> |
24 | #include <linux/task_io_accounting_ops.h> | ||
24 | #include <linux/blkdev.h> | 25 | #include <linux/blkdev.h> |
25 | #include <linux/mpage.h> | 26 | #include <linux/mpage.h> |
26 | #include <linux/rmap.h> | 27 | #include <linux/rmap.h> |
@@ -761,23 +762,24 @@ int __set_page_dirty_nobuffers(struct page *page) | |||
761 | struct address_space *mapping = page_mapping(page); | 762 | struct address_space *mapping = page_mapping(page); |
762 | struct address_space *mapping2; | 763 | struct address_space *mapping2; |
763 | 764 | ||
764 | if (mapping) { | 765 | if (!mapping) |
765 | write_lock_irq(&mapping->tree_lock); | 766 | return 1; |
766 | mapping2 = page_mapping(page); | 767 | |
767 | if (mapping2) { /* Race with truncate? */ | 768 | write_lock_irq(&mapping->tree_lock); |
768 | BUG_ON(mapping2 != mapping); | 769 | mapping2 = page_mapping(page); |
769 | if (mapping_cap_account_dirty(mapping)) | 770 | if (mapping2) { /* Race with truncate? */ |
770 | __inc_zone_page_state(page, | 771 | BUG_ON(mapping2 != mapping); |
771 | NR_FILE_DIRTY); | 772 | if (mapping_cap_account_dirty(mapping)) { |
772 | radix_tree_tag_set(&mapping->page_tree, | 773 | __inc_zone_page_state(page, NR_FILE_DIRTY); |
773 | page_index(page), PAGECACHE_TAG_DIRTY); | 774 | task_io_account_write(PAGE_CACHE_SIZE); |
774 | } | ||
775 | write_unlock_irq(&mapping->tree_lock); | ||
776 | if (mapping->host) { | ||
777 | /* !PageAnon && !swapper_space */ | ||
778 | __mark_inode_dirty(mapping->host, | ||
779 | I_DIRTY_PAGES); | ||
780 | } | 775 | } |
776 | radix_tree_tag_set(&mapping->page_tree, | ||
777 | page_index(page), PAGECACHE_TAG_DIRTY); | ||
778 | } | ||
779 | write_unlock_irq(&mapping->tree_lock); | ||
780 | if (mapping->host) { | ||
781 | /* !PageAnon && !swapper_space */ | ||
782 | __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); | ||
781 | } | 783 | } |
782 | return 1; | 784 | return 1; |
783 | } | 785 | } |
@@ -851,27 +853,26 @@ int test_clear_page_dirty(struct page *page) | |||
851 | struct address_space *mapping = page_mapping(page); | 853 | struct address_space *mapping = page_mapping(page); |
852 | unsigned long flags; | 854 | unsigned long flags; |
853 | 855 | ||
854 | if (mapping) { | 856 | if (!mapping) |
855 | write_lock_irqsave(&mapping->tree_lock, flags); | 857 | return TestClearPageDirty(page); |
856 | if (TestClearPageDirty(page)) { | 858 | |
857 | radix_tree_tag_clear(&mapping->page_tree, | 859 | write_lock_irqsave(&mapping->tree_lock, flags); |
858 | page_index(page), | 860 | if (TestClearPageDirty(page)) { |
859 | PAGECACHE_TAG_DIRTY); | 861 | radix_tree_tag_clear(&mapping->page_tree, |
860 | write_unlock_irqrestore(&mapping->tree_lock, flags); | 862 | page_index(page), PAGECACHE_TAG_DIRTY); |
861 | /* | ||
862 | * We can continue to use `mapping' here because the | ||
863 | * page is locked, which pins the address_space | ||
864 | */ | ||
865 | if (mapping_cap_account_dirty(mapping)) { | ||
866 | page_mkclean(page); | ||
867 | dec_zone_page_state(page, NR_FILE_DIRTY); | ||
868 | } | ||
869 | return 1; | ||
870 | } | ||
871 | write_unlock_irqrestore(&mapping->tree_lock, flags); | 863 | write_unlock_irqrestore(&mapping->tree_lock, flags); |
872 | return 0; | 864 | /* |
865 | * We can continue to use `mapping' here because the | ||
866 | * page is locked, which pins the address_space | ||
867 | */ | ||
868 | if (mapping_cap_account_dirty(mapping)) { | ||
869 | page_mkclean(page); | ||
870 | dec_zone_page_state(page, NR_FILE_DIRTY); | ||
871 | } | ||
872 | return 1; | ||
873 | } | 873 | } |
874 | return TestClearPageDirty(page); | 874 | write_unlock_irqrestore(&mapping->tree_lock, flags); |
875 | return 0; | ||
875 | } | 876 | } |
876 | EXPORT_SYMBOL(test_clear_page_dirty); | 877 | EXPORT_SYMBOL(test_clear_page_dirty); |
877 | 878 | ||
@@ -893,17 +894,17 @@ int clear_page_dirty_for_io(struct page *page) | |||
893 | { | 894 | { |
894 | struct address_space *mapping = page_mapping(page); | 895 | struct address_space *mapping = page_mapping(page); |
895 | 896 | ||
896 | if (mapping) { | 897 | if (!mapping) |
897 | if (TestClearPageDirty(page)) { | 898 | return TestClearPageDirty(page); |
898 | if (mapping_cap_account_dirty(mapping)) { | 899 | |
899 | page_mkclean(page); | 900 | if (TestClearPageDirty(page)) { |
900 | dec_zone_page_state(page, NR_FILE_DIRTY); | 901 | if (mapping_cap_account_dirty(mapping)) { |
901 | } | 902 | page_mkclean(page); |
902 | return 1; | 903 | dec_zone_page_state(page, NR_FILE_DIRTY); |
903 | } | 904 | } |
904 | return 0; | 905 | return 1; |
905 | } | 906 | } |
906 | return TestClearPageDirty(page); | 907 | return 0; |
907 | } | 908 | } |
908 | EXPORT_SYMBOL(clear_page_dirty_for_io); | 909 | EXPORT_SYMBOL(clear_page_dirty_for_io); |
909 | 910 | ||