| From 051db87772d9867fc2406338717675f5e12d25c8 Mon Sep 17 00:00:00 2001 |
| From: Linxu Fang <fanglinxu@huawei.com> |
| Date: Mon, 13 May 2019 17:19:17 -0700 |
| Subject: mem-hotplug: fix node spanned pages when we have a node with only |
| ZONE_MOVABLE |
| |
| [ Upstream commit 299c83dce9ea3a79bb4b5511d2cb996b6b8e5111 ] |
| |
| 342332e6a925 ("mm/page_alloc.c: introduce kernelcore=mirror option") and |
| later patches rewrote the calculation of node spanned pages. |
| |
| e506b99696a2 ("mem-hotplug: fix node spanned pages when we have a movable |
| node"), but the current code still has problems, |
| |
| When we have a node with only zone_movable and the node id is not zero, |
| the size of node spanned pages is double added. |
| |
| That's because we have an empty normal zone, and zone_start_pfn or |
| zone_end_pfn is not between arch_zone_lowest_possible_pfn and |
| arch_zone_highest_possible_pfn, so we need to use clamp to constrain the |
| range just like the commit <96e907d13602> (bootmem: Reimplement |
| __absent_pages_in_range() using for_each_mem_pfn_range()). |
| |
| e.g. |
| Zone ranges: |
| DMA [mem 0x0000000000001000-0x0000000000ffffff] |
| DMA32 [mem 0x0000000001000000-0x00000000ffffffff] |
| Normal [mem 0x0000000100000000-0x000000023fffffff] |
| Movable zone start for each node |
| Node 0: 0x0000000100000000 |
| Node 1: 0x0000000140000000 |
| Early memory node ranges |
| node 0: [mem 0x0000000000001000-0x000000000009efff] |
| node 0: [mem 0x0000000000100000-0x00000000bffdffff] |
| node 0: [mem 0x0000000100000000-0x000000013fffffff] |
| node 1: [mem 0x0000000140000000-0x000000023fffffff] |
| |
| node 0 DMA spanned:0xfff present:0xf9e absent:0x61 |
| node 0 DMA32 spanned:0xff000 present:0xbefe0 absent:0x40020 |
| node 0 Normal spanned:0 present:0 absent:0 |
| node 0 Movable spanned:0x40000 present:0x40000 absent:0 |
| On node 0 totalpages(node_present_pages): 1048446 |
| node_spanned_pages:1310719 |
| node 1 DMA spanned:0 present:0 absent:0 |
| node 1 DMA32 spanned:0 present:0 absent:0 |
| node 1 Normal spanned:0x100000 present:0x100000 absent:0 |
| node 1 Movable spanned:0x100000 present:0x100000 absent:0 |
| On node 1 totalpages(node_present_pages): 2097152 |
| node_spanned_pages:2097152 |
| Memory: 6967796K/12582392K available (16388K kernel code, 3686K rwdata, |
| 4468K rodata, 2160K init, 10444K bss, 5614596K reserved, 0K |
| cma-reserved) |
| |
| It shows that the current memory of node 1 is double added. |
| After this patch, the problem is fixed. |
| |
| node 0 DMA spanned:0xfff present:0xf9e absent:0x61 |
| node 0 DMA32 spanned:0xff000 present:0xbefe0 absent:0x40020 |
| node 0 Normal spanned:0 present:0 absent:0 |
| node 0 Movable spanned:0x40000 present:0x40000 absent:0 |
| On node 0 totalpages(node_present_pages): 1048446 |
| node_spanned_pages:1310719 |
| node 1 DMA spanned:0 present:0 absent:0 |
| node 1 DMA32 spanned:0 present:0 absent:0 |
| node 1 Normal spanned:0 present:0 absent:0 |
| node 1 Movable spanned:0x100000 present:0x100000 absent:0 |
| On node 1 totalpages(node_present_pages): 1048576 |
| node_spanned_pages:1048576 |
| memory: 6967796K/8388088K available (16388K kernel code, 3686K rwdata, |
| 4468K rodata, 2160K init, 10444K bss, 1420292K reserved, 0K |
| cma-reserved) |
| |
| Link: http://lkml.kernel.org/r/1554178276-10372-1-git-send-email-fanglinxu@huawei.com |
| Signed-off-by: Linxu Fang <fanglinxu@huawei.com> |
| Cc: Taku Izumi <izumi.taku@jp.fujitsu.com> |
| Cc: Xishi Qiu <qiuxishi@huawei.com> |
| Cc: Michal Hocko <mhocko@suse.com> |
| Cc: Vlastimil Babka <vbabka@suse.cz> |
| Cc: Pavel Tatashin <pavel.tatashin@microsoft.com> |
| Cc: Oscar Salvador <osalvador@suse.de> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| mm/page_alloc.c | 6 ++++-- |
| 1 file changed, 4 insertions(+), 2 deletions(-) |
| |
| diff --git a/mm/page_alloc.c b/mm/page_alloc.c |
| index 8e6932a140b8..2d04bd2e1ced 100644 |
| --- a/mm/page_alloc.c |
| +++ b/mm/page_alloc.c |
| @@ -5937,13 +5937,15 @@ static unsigned long __meminit zone_spanned_pages_in_node(int nid, |
| unsigned long *zone_end_pfn, |
| unsigned long *ignored) |
| { |
| + unsigned long zone_low = arch_zone_lowest_possible_pfn[zone_type]; |
| + unsigned long zone_high = arch_zone_highest_possible_pfn[zone_type]; |
| /* When hotadd a new node from cpu_up(), the node should be empty */ |
| if (!node_start_pfn && !node_end_pfn) |
| return 0; |
| |
| /* Get the start and end of the zone */ |
| - *zone_start_pfn = arch_zone_lowest_possible_pfn[zone_type]; |
| - *zone_end_pfn = arch_zone_highest_possible_pfn[zone_type]; |
| + *zone_start_pfn = clamp(node_start_pfn, zone_low, zone_high); |
| + *zone_end_pfn = clamp(node_end_pfn, zone_low, zone_high); |
| adjust_zone_range_for_zone_movable(nid, zone_type, |
| node_start_pfn, node_end_pfn, |
| zone_start_pfn, zone_end_pfn); |
| -- |
| 2.20.1 |
| |