When memory shortage, we are using drain_pages() for flushing per cpu page cache. In this case, per cpu stat should be flushed too. because now we are under memory shortage and we need to know exact free pages. Otherwise get_page_from_freelist() may fail even though pcp was flushed. Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@xxxxxxxxxxxxxx> --- include/linux/vmstat.h | 5 +++++ mm/page_alloc.c | 1 + mm/vmstat.c | 12 ++++++++++++ 3 files changed, 18 insertions(+), 0 deletions(-) diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h index 1997988..df777f4 100644 --- a/include/linux/vmstat.h +++ b/include/linux/vmstat.h @@ -253,6 +253,8 @@ extern void __inc_zone_state(struct zone *, enum zone_stat_item); extern void dec_zone_state(struct zone *, enum zone_stat_item); extern void __dec_zone_state(struct zone *, enum zone_stat_item); +void __flush_zone_state(struct zone *zone, enum zone_stat_item item); + void refresh_cpu_vm_stats(int); void refresh_zone_stat_thresholds(void); #else /* CONFIG_SMP */ @@ -299,6 +301,9 @@ static inline void __dec_zone_page_state(struct page *page, #define dec_zone_page_state __dec_zone_page_state #define mod_zone_page_state __mod_zone_page_state +static inline void +__flush_zone_state(struct zone *zone, enum zone_stat_item item) { } + static inline void refresh_cpu_vm_stats(int cpu) { } static inline void refresh_zone_stat_thresholds(void) { } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 194bdaa..8b50e52 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1093,6 +1093,7 @@ static void drain_pages(unsigned int cpu) pcp = &pset->pcp; free_pcppages_bulk(zone, pcp->count, pcp); pcp->count = 0; + __flush_zone_state(zone, NR_FREE_PAGES); local_irq_restore(flags); } } diff --git a/mm/vmstat.c b/mm/vmstat.c index 48b0463..1ca04ec 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -233,6 +233,18 @@ void __inc_zone_state(struct zone *zone, enum zone_stat_item item) } } +void __flush_zone_state(struct zone *zone, enum zone_stat_item item) +{ + struct per_cpu_pageset *pcp = this_cpu_ptr(zone->pageset); + s8 *diff = pcp->vm_stat_diff + item; + + if (!*diff) + return; + + zone_page_state_add(*diff, zone, item); + *diff = 0; +} + void __inc_zone_page_state(struct page *page, enum zone_stat_item item) { __inc_zone_state(page_zone(page), item); -- 1.6.5.2 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@xxxxxxxxxx For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"dont@xxxxxxxxx"> email@xxxxxxxxx </a>