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 | ||
