|
@@ -284,6 +284,10 @@ EXPORT_SYMBOL(dec_zone_page_state);
|
|
|
/*
|
|
|
* Update the zone counters for one cpu.
|
|
|
*
|
|
|
+ * The cpu specified must be either the current cpu or a processor that
|
|
|
+ * is not online. If it is the current cpu then the execution thread must
|
|
|
+ * be pinned to the current cpu.
|
|
|
+ *
|
|
|
* Note that refresh_cpu_vm_stats strives to only access
|
|
|
* node local memory. The per cpu pagesets on remote zones are placed
|
|
|
* in the memory local to the processor using that pageset. So the
|
|
@@ -299,7 +303,7 @@ void refresh_cpu_vm_stats(int cpu)
|
|
|
{
|
|
|
struct zone *zone;
|
|
|
int i;
|
|
|
- unsigned long flags;
|
|
|
+ int global_diff[NR_VM_ZONE_STAT_ITEMS] = { 0, };
|
|
|
|
|
|
for_each_zone(zone) {
|
|
|
struct per_cpu_pageset *p;
|
|
@@ -311,15 +315,19 @@ void refresh_cpu_vm_stats(int cpu)
|
|
|
|
|
|
for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
|
|
|
if (p->vm_stat_diff[i]) {
|
|
|
+ unsigned long flags;
|
|
|
+ int v;
|
|
|
+
|
|
|
local_irq_save(flags);
|
|
|
- zone_page_state_add(p->vm_stat_diff[i],
|
|
|
- zone, i);
|
|
|
+ v = p->vm_stat_diff[i];
|
|
|
p->vm_stat_diff[i] = 0;
|
|
|
+ local_irq_restore(flags);
|
|
|
+ atomic_long_add(v, &zone->vm_stat[i]);
|
|
|
+ global_diff[i] += v;
|
|
|
#ifdef CONFIG_NUMA
|
|
|
/* 3 seconds idle till flush */
|
|
|
p->expire = 3;
|
|
|
#endif
|
|
|
- local_irq_restore(flags);
|
|
|
}
|
|
|
#ifdef CONFIG_NUMA
|
|
|
/*
|
|
@@ -351,6 +359,10 @@ void refresh_cpu_vm_stats(int cpu)
|
|
|
drain_zone_pages(zone, p->pcp + 1);
|
|
|
#endif
|
|
|
}
|
|
|
+
|
|
|
+ for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
|
|
|
+ if (global_diff[i])
|
|
|
+ atomic_long_add(global_diff[i], &vm_stat[i]);
|
|
|
}
|
|
|
|
|
|
#endif
|