aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mm/mm_init.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/mm/mm_init.c b/mm/mm_init.c
index 0f64909e8d20..498d62c4ece3 100644
--- a/mm/mm_init.c
+++ b/mm/mm_init.c
@@ -1540,7 +1540,7 @@ void __ref free_area_init_core_hotplug(struct pglist_data *pgdat)
{
int nid = pgdat->node_id;
enum zone_type z;
- int cpu;
+ int cpu, i;
pgdat_init_internals(pgdat);
@@ -1558,10 +1558,17 @@ void __ref free_area_init_core_hotplug(struct pglist_data *pgdat)
pgdat->node_start_pfn = 0;
pgdat->node_present_pages = 0;
- for_each_online_cpu(cpu) {
- struct per_cpu_nodestat *p;
+ /*
+ * Hot-unplug can leave per-cpu vmstat deltas unfolded (folders skip
+ * offline nodes) - reconcile this at online. Foreign access to counters
+ * is safe: the node is not online yet and we hold the hotplug lock.
+ */
+ for_each_possible_cpu(cpu) {
+ struct per_cpu_nodestat *p = per_cpu_ptr(pgdat->per_cpu_nodestats, cpu);
- p = per_cpu_ptr(pgdat->per_cpu_nodestats, cpu);
+ for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++)
+ if (p->vm_node_stat_diff[i])
+ node_page_state_add(p->vm_node_stat_diff[i], pgdat, i);
memset(p, 0, sizeof(*p));
}