diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c index 7b50bb1caabe0500e73fd2113c9cda6fe164dddc..db1b2e11cf8f0742b40066b31b99b852459454a6 100644 --- a/arch/x86_64/mm/srat.c +++ b/arch/x86_64/mm/srat.c @@ -227,7 +227,9 @@ static int reserve_hotadd(int node, unsigned long start, unsigned long end) /* This check might be a bit too strict, but I'm keeping it for now. */ if (absent_pages_in_range(s_pfn, e_pfn) != e_pfn - s_pfn) { - printk(KERN_ERR "SRAT: Hotplug area has existing memory\n"); + printk(KERN_ERR + "SRAT: Hotplug area %lu -> %lu has existing memory\n", + s_pfn, e_pfn); return -1; } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 8d9a1eb9fbba9dddbfa3bbb71628a1557bf3158e..75133e1dc4b1c624f2a813f9cfeb9e0305ecf407 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2168,6 +2168,10 @@ unsigned long __init __absent_pages_in_range(int nid, if (i == -1) return 0; + /* Account for ranges before physical memory on this node */ + if (early_node_map[i].start_pfn > range_start_pfn) + hole_pages = early_node_map[i].start_pfn - range_start_pfn; + prev_end_pfn = early_node_map[i].start_pfn; /* Find all holes for the zone within the node */ @@ -2189,6 +2193,11 @@ unsigned long __init __absent_pages_in_range(int nid, prev_end_pfn = early_node_map[i].end_pfn; } + /* Account for ranges past physical memory on this node */ + if (range_end_pfn > prev_end_pfn) + hole_pages = range_end_pfn - + max(range_start_pfn, prev_end_pfn); + return hole_pages; } @@ -2210,9 +2219,16 @@ unsigned long __init zone_absent_pages_in_node(int nid, unsigned long zone_type, unsigned long *ignored) { - return __absent_pages_in_range(nid, - arch_zone_lowest_possible_pfn[zone_type], - arch_zone_highest_possible_pfn[zone_type]); + unsigned long node_start_pfn, node_end_pfn; + unsigned long zone_start_pfn, zone_end_pfn; + + get_pfn_range_for_nid(nid, &node_start_pfn, &node_end_pfn); + zone_start_pfn = max(arch_zone_lowest_possible_pfn[zone_type], + node_start_pfn); + zone_end_pfn = min(arch_zone_highest_possible_pfn[zone_type], + node_end_pfn); + + return __absent_pages_in_range(nid, zone_start_pfn, zone_end_pfn); } /* Return the zone index a PFN is in */