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>
This commit is contained in:
parent
2baf9e8948
commit
f9126ab924
|
@ -1277,6 +1277,7 @@ int __ref add_memory(int nid, u64 start, u64 size)
|
||||||
|
|
||||||
/* create new memmap entry */
|
/* create new memmap entry */
|
||||||
firmware_map_add_hotplug(start, start + size, "System RAM");
|
firmware_map_add_hotplug(start, start + size, "System RAM");
|
||||||
|
memblock_add_node(start, size, nid);
|
||||||
|
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -2013,6 +2014,8 @@ void __ref remove_memory(int nid, u64 start, u64 size)
|
||||||
|
|
||||||
/* remove memmap entry */
|
/* remove memmap entry */
|
||||||
firmware_map_remove(start, start + size, "System RAM");
|
firmware_map_remove(start, start + size, "System RAM");
|
||||||
|
memblock_free(start, size);
|
||||||
|
memblock_remove(start, size);
|
||||||
|
|
||||||
arch_remove_memory(start, size);
|
arch_remove_memory(start, size);
|
||||||
|
|
||||||
|
|
|
@ -5060,6 +5060,10 @@ static unsigned long __meminit zone_spanned_pages_in_node(int nid,
|
||||||
{
|
{
|
||||||
unsigned long zone_start_pfn, zone_end_pfn;
|
unsigned long zone_start_pfn, zone_end_pfn;
|
||||||
|
|
||||||
|
/* When hotadd a new node, the node should be empty */
|
||||||
|
if (!node_start_pfn && !node_end_pfn)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Get the start and end of the zone */
|
/* Get the start and end of the zone */
|
||||||
zone_start_pfn = arch_zone_lowest_possible_pfn[zone_type];
|
zone_start_pfn = arch_zone_lowest_possible_pfn[zone_type];
|
||||||
zone_end_pfn = arch_zone_highest_possible_pfn[zone_type];
|
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,
|
||||||
unsigned long zone_high = arch_zone_highest_possible_pfn[zone_type];
|
unsigned long zone_high = arch_zone_highest_possible_pfn[zone_type];
|
||||||
unsigned long zone_start_pfn, zone_end_pfn;
|
unsigned long zone_start_pfn, zone_end_pfn;
|
||||||
|
|
||||||
|
/* When hotadd a new node, the node should be empty */
|
||||||
|
if (!node_start_pfn && !node_end_pfn)
|
||||||
|
return 0;
|
||||||
|
|
||||||
zone_start_pfn = clamp(node_start_pfn, zone_low, zone_high);
|
zone_start_pfn = clamp(node_start_pfn, zone_low, zone_high);
|
||||||
zone_end_pfn = clamp(node_end_pfn, zone_low, zone_high);
|
zone_end_pfn = clamp(node_end_pfn, zone_low, zone_high);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue