summaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
authorMel Gorman <mgorman@techsingularity.net>2016-08-04 18:31:49 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-08-04 20:02:09 -0400
commitb4911ea2bcf52345bf3dc73292b8c4676f6192c6 (patch)
tree8afaeb68362a0c5b9fd429fe212d5c70a1089f21 /mm/page_alloc.c
parent412d0008d69ce964ac60ac9da714edb40bbae244 (diff)
mm: initialise per_cpu_nodestats for all online pgdats at boot
Paul Mackerras and Reza Arbab reported that machines with memoryless nodes fail when vmstats are refreshed. Paul reported an oops as follows Unable to handle kernel paging request for data at address 0xff7a10000 Faulting instruction address: 0xc000000000270cd0 Oops: Kernel access of bad area, sig: 11 [#1] SMP NR_CPUS=2048 NUMA PowerNV Modules linked in: CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.7.0-kvm+ #118 task: c000000ff0680010 task.stack: c000000ff0704000 NIP: c000000000270cd0 LR: c000000000270ce8 CTR: 0000000000000000 REGS: c000000ff0707900 TRAP: 0300 Not tainted (4.7.0-kvm+) MSR: 9000000102009033 <SF,HV,VEC,EE,ME,IR,DR,RI,LE,TM[E]> CR: 846b6824 XER: 20000000 CFAR: c000000000008768 DAR: 0000000ff7a10000 DSISR: 42000000 SOFTE: 1 NIP refresh_zone_stat_thresholds+0x80/0x240 LR refresh_zone_stat_thresholds+0x98/0x240 Call Trace: refresh_zone_stat_thresholds+0xb8/0x240 (unreliable) Both supplied potential fixes but one potentially misses checks and another had redundant initialisations. This version initialises per_cpu_nodestats on a per-pgdat basis instead of on a per-zone basis. Link: http://lkml.kernel.org/r/20160804092404.GI2799@techsingularity.net Signed-off-by: Mel Gorman <mgorman@techsingularity.net> Reported-by: Paul Mackerras <paulus@ozlabs.org> Reported-by: Reza Arbab <arbab@linux.vnet.ibm.com> Tested-by: Reza Arbab <arbab@linux.vnet.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r--mm/page_alloc.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 39a372a2a1d6..fb975cec3518 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -5257,11 +5257,6 @@ static void __meminit setup_zone_pageset(struct zone *zone)
5257 zone->pageset = alloc_percpu(struct per_cpu_pageset); 5257 zone->pageset = alloc_percpu(struct per_cpu_pageset);
5258 for_each_possible_cpu(cpu) 5258 for_each_possible_cpu(cpu)
5259 zone_pageset_init(zone, cpu); 5259 zone_pageset_init(zone, cpu);
5260
5261 if (!zone->zone_pgdat->per_cpu_nodestats) {
5262 zone->zone_pgdat->per_cpu_nodestats =
5263 alloc_percpu(struct per_cpu_nodestat);
5264 }
5265} 5260}
5266 5261
5267/* 5262/*
@@ -5270,10 +5265,15 @@ static void __meminit setup_zone_pageset(struct zone *zone)
5270 */ 5265 */
5271void __init setup_per_cpu_pageset(void) 5266void __init setup_per_cpu_pageset(void)
5272{ 5267{
5268 struct pglist_data *pgdat;
5273 struct zone *zone; 5269 struct zone *zone;
5274 5270
5275 for_each_populated_zone(zone) 5271 for_each_populated_zone(zone)
5276 setup_zone_pageset(zone); 5272 setup_zone_pageset(zone);
5273
5274 for_each_online_pgdat(pgdat)
5275 pgdat->per_cpu_nodestats =
5276 alloc_percpu(struct per_cpu_nodestat);
5277} 5277}
5278 5278
5279static noinline __ref 5279static noinline __ref