diff options
Diffstat (limited to 'mm/mmzone.c')
| -rw-r--r-- | mm/mmzone.c | 21 | 
1 files changed, 21 insertions, 0 deletions
| diff --git a/mm/mmzone.c b/mm/mmzone.c index f5b7d176021..e35bfb82c85 100644 --- a/mm/mmzone.c +++ b/mm/mmzone.c @@ -87,3 +87,24 @@ int memmap_valid_within(unsigned long pfn,  	return 1;  }  #endif /* CONFIG_ARCH_HAS_HOLES_MEMORYMODEL */ + +#ifdef CONFIG_SMP +/* Called when a more accurate view of NR_FREE_PAGES is needed */ +unsigned long zone_nr_free_pages(struct zone *zone) +{ +	unsigned long nr_free_pages = zone_page_state(zone, NR_FREE_PAGES); + +	/* +	 * While kswapd is awake, it is considered the zone is under some +	 * memory pressure. Under pressure, there is a risk that +	 * per-cpu-counter-drift will allow the min watermark to be breached +	 * potentially causing a live-lock. While kswapd is awake and +	 * free pages are low, get a better estimate for free pages +	 */ +	if (nr_free_pages < zone->percpu_drift_mark && +			!waitqueue_active(&zone->zone_pgdat->kswapd_wait)) +		return zone_page_state_snapshot(zone, NR_FREE_PAGES); + +	return nr_free_pages; +} +#endif /* CONFIG_SMP */ | 
