diff options
author | Xishi Qiu <qiuxishi@huawei.com> | 2015-08-14 18:35:16 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-08-14 18:56:32 -0400 |
commit | f9126ab9241f66562debf69c2c9d8fee32ddcc53 (patch) | |
tree | 99b24da6550082e628b756aab3275190f6fdcae3 | |
parent | 2baf9e8948530f2c6af36f0e3d9a26e0315900e6 (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.c | 3 | ||||
-rw-r--r-- | mm/page_alloc.c | 8 |
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 | ||