|
@@ -56,6 +56,7 @@
|
|
|
#include <linux/mmu_notifier.h>
|
|
|
#include <linux/migrate.h>
|
|
|
#include <linux/hugetlb.h>
|
|
|
+#include <linux/backing-dev.h>
|
|
|
|
|
|
#include <asm/tlbflush.h>
|
|
|
|
|
@@ -926,11 +927,8 @@ int page_mkclean(struct page *page)
|
|
|
|
|
|
if (page_mapped(page)) {
|
|
|
struct address_space *mapping = page_mapping(page);
|
|
|
- if (mapping) {
|
|
|
+ if (mapping)
|
|
|
ret = page_mkclean_file(mapping, page);
|
|
|
- if (page_test_and_clear_dirty(page_to_pfn(page), 1))
|
|
|
- ret = 1;
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
return ret;
|
|
@@ -1116,6 +1114,7 @@ void page_add_file_rmap(struct page *page)
|
|
|
*/
|
|
|
void page_remove_rmap(struct page *page)
|
|
|
{
|
|
|
+ struct address_space *mapping = page_mapping(page);
|
|
|
bool anon = PageAnon(page);
|
|
|
bool locked;
|
|
|
unsigned long flags;
|
|
@@ -1138,8 +1137,19 @@ void page_remove_rmap(struct page *page)
|
|
|
* this if the page is anon, so about to be freed; but perhaps
|
|
|
* not if it's in swapcache - there might be another pte slot
|
|
|
* containing the swap entry, but page not yet written to swap.
|
|
|
+ *
|
|
|
+ * And we can skip it on file pages, so long as the filesystem
|
|
|
+ * participates in dirty tracking; but need to catch shm and tmpfs
|
|
|
+ * and ramfs pages which have been modified since creation by read
|
|
|
+ * fault.
|
|
|
+ *
|
|
|
+ * Note that mapping must be decided above, before decrementing
|
|
|
+ * mapcount (which luckily provides a barrier): once page is unmapped,
|
|
|
+ * it could be truncated and page->mapping reset to NULL at any moment.
|
|
|
+ * Note also that we are relying on page_mapping(page) to set mapping
|
|
|
+ * to &swapper_space when PageSwapCache(page).
|
|
|
*/
|
|
|
- if ((!anon || PageSwapCache(page)) &&
|
|
|
+ if (mapping && !mapping_cap_account_dirty(mapping) &&
|
|
|
page_test_and_clear_dirty(page_to_pfn(page), 1))
|
|
|
set_page_dirty(page);
|
|
|
/*
|