aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Tatashin <pasha.tatashin@oracle.com>2017-02-16 15:13:54 -0500
committerDavid S. Miller <davem@davemloft.net>2017-02-23 11:33:23 -0500
commitcd429ce2d095041d249ec85feaed608bbf72154f (patch)
tree32f0637f630d31722523530ae4c52a470b95c765
parent1537b26dab1c1dfd92a116a933143f52b1112a22 (diff)
sparc64: memblock resizes are not handled properly
In add_node_ranges() when memblock resize happens, the iterator keeps using the previous freed array. This bug cause hangs on machine where there are over 128 memory blocks during boot. For example, on machines where memory interleaving is small. The problem is seen on T4-4 because it cant have 2T of memory, and memory is interleaved at 8G. So we have 2T/8G = 256 regions to set node IDs. The starting size of regions array is 128. Thus, we have to double at least one time (actually we have to double twice because some memory is already reserved and thus we need more than 256 regions). We start using an incorrect pointer to the array after the first doubling. Signed-off-by: Pavel Tatashin <pasha.tatashin@oracle.com> Signed-off-by: Babu Moger <babu.moger@oracle.com> Reviewed-by: Babu Moger <babu.moger@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/sparc/mm/init_64.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 77446eaf1395..ccd455328989 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -1126,6 +1126,10 @@ int of_node_to_nid(struct device_node *dp)
1126static void __init add_node_ranges(void) 1126static void __init add_node_ranges(void)
1127{ 1127{
1128 struct memblock_region *reg; 1128 struct memblock_region *reg;
1129 unsigned long prev_max;
1130
1131memblock_resized:
1132 prev_max = memblock.memory.max;
1129 1133
1130 for_each_memblock(memory, reg) { 1134 for_each_memblock(memory, reg) {
1131 unsigned long size = reg->size; 1135 unsigned long size = reg->size;
@@ -1145,6 +1149,8 @@ static void __init add_node_ranges(void)
1145 1149
1146 memblock_set_node(start, this_end - start, 1150 memblock_set_node(start, this_end - start,
1147 &memblock.memory, nid); 1151 &memblock.memory, nid);
1152 if (memblock.memory.max != prev_max)
1153 goto memblock_resized;
1148 start = this_end; 1154 start = this_end;
1149 } 1155 }
1150 } 1156 }