diff options
Diffstat (limited to 'mm/rmap.c')
-rw-r--r-- | mm/rmap.c | 20 |
1 files changed, 15 insertions, 5 deletions
@@ -56,6 +56,7 @@ | |||
56 | #include <linux/mmu_notifier.h> | 56 | #include <linux/mmu_notifier.h> |
57 | #include <linux/migrate.h> | 57 | #include <linux/migrate.h> |
58 | #include <linux/hugetlb.h> | 58 | #include <linux/hugetlb.h> |
59 | #include <linux/backing-dev.h> | ||
59 | 60 | ||
60 | #include <asm/tlbflush.h> | 61 | #include <asm/tlbflush.h> |
61 | 62 | ||
@@ -926,11 +927,8 @@ int page_mkclean(struct page *page) | |||
926 | 927 | ||
927 | if (page_mapped(page)) { | 928 | if (page_mapped(page)) { |
928 | struct address_space *mapping = page_mapping(page); | 929 | struct address_space *mapping = page_mapping(page); |
929 | if (mapping) { | 930 | if (mapping) |
930 | ret = page_mkclean_file(mapping, page); | 931 | ret = page_mkclean_file(mapping, page); |
931 | if (page_test_and_clear_dirty(page_to_pfn(page), 1)) | ||
932 | ret = 1; | ||
933 | } | ||
934 | } | 932 | } |
935 | 933 | ||
936 | return ret; | 934 | return ret; |
@@ -1116,6 +1114,7 @@ void page_add_file_rmap(struct page *page) | |||
1116 | */ | 1114 | */ |
1117 | void page_remove_rmap(struct page *page) | 1115 | void page_remove_rmap(struct page *page) |
1118 | { | 1116 | { |
1117 | struct address_space *mapping = page_mapping(page); | ||
1119 | bool anon = PageAnon(page); | 1118 | bool anon = PageAnon(page); |
1120 | bool locked; | 1119 | bool locked; |
1121 | unsigned long flags; | 1120 | unsigned long flags; |
@@ -1138,8 +1137,19 @@ void page_remove_rmap(struct page *page) | |||
1138 | * this if the page is anon, so about to be freed; but perhaps | 1137 | * this if the page is anon, so about to be freed; but perhaps |
1139 | * not if it's in swapcache - there might be another pte slot | 1138 | * not if it's in swapcache - there might be another pte slot |
1140 | * containing the swap entry, but page not yet written to swap. | 1139 | * containing the swap entry, but page not yet written to swap. |
1140 | * | ||
1141 | * And we can skip it on file pages, so long as the filesystem | ||
1142 | * participates in dirty tracking; but need to catch shm and tmpfs | ||
1143 | * and ramfs pages which have been modified since creation by read | ||
1144 | * fault. | ||
1145 | * | ||
1146 | * Note that mapping must be decided above, before decrementing | ||
1147 | * mapcount (which luckily provides a barrier): once page is unmapped, | ||
1148 | * it could be truncated and page->mapping reset to NULL at any moment. | ||
1149 | * Note also that we are relying on page_mapping(page) to set mapping | ||
1150 | * to &swapper_space when PageSwapCache(page). | ||
1141 | */ | 1151 | */ |
1142 | if ((!anon || PageSwapCache(page)) && | 1152 | if (mapping && !mapping_cap_account_dirty(mapping) && |
1143 | page_test_and_clear_dirty(page_to_pfn(page), 1)) | 1153 | page_test_and_clear_dirty(page_to_pfn(page), 1)) |
1144 | set_page_dirty(page); | 1154 | set_page_dirty(page); |
1145 | /* | 1155 | /* |