diff options
Diffstat (limited to 'mm/vmscan.c')
| -rw-r--r-- | mm/vmscan.c | 13 | 
1 files changed, 9 insertions, 4 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c index 0ea71e887bb6..64f9570cff56 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -511,10 +511,11 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc)  		 * PageDirty _after_ making sure that the page is freeable and  		 * not in use by anybody. 	(pagecache + us == 2)  		 */ -		if (page_count(page) != 2 || PageDirty(page)) { -			write_unlock_irq(&mapping->tree_lock); -			goto keep_locked; -		} +		if (unlikely(page_count(page) != 2)) +			goto cannot_free; +		smp_rmb(); +		if (unlikely(PageDirty(page))) +			goto cannot_free;  #ifdef CONFIG_SWAP  		if (PageSwapCache(page)) { @@ -538,6 +539,10 @@ free_it:  			__pagevec_release_nonlru(&freed_pvec);  		continue; +cannot_free: +		write_unlock_irq(&mapping->tree_lock); +		goto keep_locked; +  activate_locked:  		SetPageActive(page);  		pgactivate++;  | 
