diff options
| author | Ingo Molnar <mingo@kernel.org> | 2012-12-07 12:15:33 +0100 | 
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2012-12-07 12:15:33 +0100 | 
| commit | 222e82bef4bd520a31d48c31ab24e49dd46daa46 (patch) | |
| tree | b6e73cad8e0b3a1c3e1acc537789e97aadaefa92 /mm/rmap.c | |
| parent | 38ca9c927c7d3db61f57e3d3a9334958c3af6e9a (diff) | |
| parent | 18a2f371f5edf41810f6469cb9be39931ef9deb9 (diff) | |
Merge branch 'linus' into sched/core
Pick up the autogroups fix and other fixes.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'mm/rmap.c')
| -rw-r--r-- | mm/rmap.c | 20 | 
1 files changed, 15 insertions, 5 deletions
diff --git a/mm/rmap.c b/mm/rmap.c index 7df7984d476c..2ee1ef0f317b 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -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);  	/*  | 
