diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h index 9044769f2296..dd0f59d2c945 100644 --- a/include/linux/vmstat.h +++ b/include/linux/vmstat.h @@ -142,6 +142,25 @@ static inline unsigned long zone_page_state_snapshot(struct zone *zone, return x; } +static inline unsigned long global_page_state_snapshot(enum zone_stat_item item) +{ + long x = atomic_long_read(&vm_stat[item]); + +#ifdef CONFIG_SMP + struct zone *zone; + int cpu; + for_each_online_cpu(cpu) { + for_each_populated_zone(zone) + x += per_cpu_ptr(zone->pageset, + cpu)->vm_stat_diff[item]; + } + + if (x < 0) + x = 0; +#endif + return x; +} + #ifdef CONFIG_NUMA /* * Determine the per node value of a stat item. This function diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 2ddcb5da6db1..c16f9197c54c 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -1670,6 +1670,12 @@ void throttle_vm_writeout(gfp_t gfp_mask) if (global_page_state(NR_UNSTABLE_NFS) + global_page_state(NR_WRITEBACK) <= dirty_thresh) break; + /* Try safe version */ + else if (unlikely(global_page_state_snapshot(NR_UNSTABLE_NFS) + + global_page_state_snapshot(NR_WRITEBACK) <= + dirty_thresh)) + break; + congestion_wait(BLK_RW_ASYNC, HZ/10); /*