aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXishi Qiu <qiuxishi@huawei.com>2015-08-14 18:35:16 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-08-14 18:56:32 -0400
commitf9126ab9241f66562debf69c2c9d8fee32ddcc53 (patch)
tree99b24da6550082e628b756aab3275190f6fdcae3
parent2baf9e8948530f2c6af36f0e3d9a26e0315900e6 (diff)
memory-hotplug: fix wrong edge when hot add a new node
When we add a new node, the edge of memory may be wrong. e.g. system has 4 nodes, and node3 is movable, node3 mem:[24G-32G], 1. hotremove the node3, 2. then hotadd node3 with a part of memory, mem:[26G-30G], 3. call hotadd_new_pgdat() free_area_init_node() get_pfn_range_for_nid() 4. it will return wrong start_pfn and end_pfn, because we have not update the memblock. This patch also fixes a BUG_ON during hot-addition, please see http://marc.info/?l=linux-kernel&m=142961156129456&w=2 Signed-off-by: Xishi Qiu <qiuxishi@huawei.com> Cc: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Cc: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Taku Izumi <izumi.taku@jp.fujitsu.com> Cc: Tang Chen <tangchen@cn.fujitsu.com> Cc: Gu Zheng <guz.fnst@cn.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--mm/memory_hotplug.c3
-rw-r--r--mm/page_alloc.c8
2 files changed, 11 insertions, 0 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 003dbe4b060d..6da82bcb0a8b 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1277,6 +1277,7 @@ int __ref add_memory(int nid, u64 start, u64 size)
1277 1277
1278 /* create new memmap entry */ 1278 /* create new memmap entry */
1279 firmware_map_add_hotplug(start, start + size, "System RAM"); 1279 firmware_map_add_hotplug(start, start + size, "System RAM");
1280 memblock_add_node(start, size, nid);
1280 1281
1281 goto out; 1282 goto out;
1282 1283
@@ -2013,6 +2014,8 @@ void __ref remove_memory(int nid, u64 start, u64 size)
2013 2014
2014 /* remove memmap entry */ 2015 /* remove memmap entry */
2015 firmware_map_remove(start, start + size, "System RAM"); 2016 firmware_map_remove(start, start + size, "System RAM");
2017 memblock_free(start, size);
2018 memblock_remove(start, size);
2016 2019
2017 arch_remove_memory(start, size); 2020 arch_remove_memory(start, size);
2018 2021
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index beda41710802..df959b7d6085 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -5060,6 +5060,10 @@ static unsigned long __meminit zone_spanned_pages_in_node(int nid,
5060{ 5060{
5061 unsigned long zone_start_pfn, zone_end_pfn; 5061 unsigned long zone_start_pfn, zone_end_pfn;
5062 5062
5063 /* When hotadd a new node, the node should be empty */
5064 if (!node_start_pfn && !node_end_pfn)
5065 return 0;
5066
5063 /* Get the start and end of the zone */ 5067 /* Get the start and end of the zone */
5064 zone_start_pfn = arch_zone_lowest_possible_pfn[zone_type]; 5068 zone_start_pfn = arch_zone_lowest_possible_pfn[zone_type];
5065 zone_end_pfn = arch_zone_highest_possible_pfn[zone_type]; 5069 zone_end_pfn = arch_zone_highest_possible_pfn[zone_type];
@@ -5123,6 +5127,10 @@ static unsigned long __meminit zone_absent_pages_in_node(int nid,
5123 unsigned long zone_high = arch_zone_highest_possible_pfn[zone_type]; 5127 unsigned long zone_high = arch_zone_highest_possible_pfn[zone_type];
5124 unsigned long zone_start_pfn, zone_end_pfn; 5128 unsigned long zone_start_pfn, zone_end_pfn;
5125 5129
5130 /* When hotadd a new node, the node should be empty */
5131 if (!node_start_pfn && !node_end_pfn)
5132 return 0;
5133
5126 zone_start_pfn = clamp(node_start_pfn, zone_low, zone_high); 5134 zone_start_pfn = clamp(node_start_pfn, zone_low, zone_high);
5127 zone_end_pfn = clamp(node_end_pfn, zone_low, zone_high); 5135 zone_end_pfn = clamp(node_end_pfn, zone_low, zone_high);
5128 5136