diff options
Diffstat (limited to 'mm/filemap.c')
| -rw-r--r-- | mm/filemap.c | 37 | 
1 files changed, 25 insertions, 12 deletions
diff --git a/mm/filemap.c b/mm/filemap.c index 903bf316912..ab8553658af 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -33,6 +33,7 @@  #include <linux/cpuset.h>  #include <linux/hardirq.h> /* for BUG_ON(!in_atomic()) only */  #include <linux/memcontrol.h> +#include <linux/mm_inline.h> /* for page_is_file_cache() */  #include "internal.h"  /* @@ -115,12 +116,12 @@ void __remove_from_page_cache(struct page *page)  {  	struct address_space *mapping = page->mapping; -	mem_cgroup_uncharge_cache_page(page);  	radix_tree_delete(&mapping->page_tree, page->index);  	page->mapping = NULL;  	mapping->nrpages--;  	__dec_zone_page_state(page, NR_FILE_PAGES);  	BUG_ON(page_mapped(page)); +	mem_cgroup_uncharge_cache_page(page);  	/*  	 * Some filesystems seem to re-dirty the page even after @@ -492,9 +493,24 @@ EXPORT_SYMBOL(add_to_page_cache_locked);  int add_to_page_cache_lru(struct page *page, struct address_space *mapping,  				pgoff_t offset, gfp_t gfp_mask)  { -	int ret = add_to_page_cache(page, mapping, offset, gfp_mask); -	if (ret == 0) -		lru_cache_add(page); +	int ret; + +	/* +	 * Splice_read and readahead add shmem/tmpfs pages into the page cache +	 * before shmem_readpage has a chance to mark them as SwapBacked: they +	 * need to go on the active_anon lru below, and mem_cgroup_cache_charge +	 * (called in add_to_page_cache) needs to know where they're going too. +	 */ +	if (mapping_cap_swap_backed(mapping)) +		SetPageSwapBacked(page); + +	ret = add_to_page_cache(page, mapping, offset, gfp_mask); +	if (ret == 0) { +		if (page_is_file_cache(page)) +			lru_cache_add_file(page); +		else +			lru_cache_add_active_anon(page); +	}  	return ret;  } @@ -557,17 +573,14 @@ EXPORT_SYMBOL(wait_on_page_bit);   * mechananism between PageLocked pages and PageWriteback pages is shared.   * But that's OK - sleepers in wait_on_page_writeback() just go back to sleep.   * - * The first mb is necessary to safely close the critical section opened by the - * test_and_set_bit() to lock the page; the second mb is necessary to enforce - * ordering between the clear_bit and the read of the waitqueue (to avoid SMP - * races with a parallel wait_on_page_locked()). + * The mb is necessary to enforce ordering between the clear_bit and the read + * of the waitqueue (to avoid SMP races with a parallel wait_on_page_locked()).   */  void unlock_page(struct page *page)  { -	smp_mb__before_clear_bit(); -	if (!test_and_clear_bit(PG_locked, &page->flags)) -		BUG(); -	smp_mb__after_clear_bit();  +	VM_BUG_ON(!PageLocked(page)); +	clear_bit_unlock(PG_locked, &page->flags); +	smp_mb__after_clear_bit();  	wake_up_page(page, PG_locked);  }  EXPORT_SYMBOL(unlock_page);  |