aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMel Gorman <mel@skynet.ie>2006-09-27 01:49:58 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-27 08:26:11 -0700
commit9c7cd6877cf8db15269163deda69392263124c1e (patch)
treeff5197bdd2d5f02a5032c050eb39349534a4b14b
parent0e0b864e069c52a7b3e4a7da56e29b03a012fd75 (diff)
downloadlinux-9c7cd6877cf8db15269163deda69392263124c1e.tar.gz
[PATCH] Account for holes that are outside the range of physical memory
absent_pages_in_range() made the assumption that users of the API would not care about holes beyound the end of physical memory. This was not the case. This patch will account for ranges outside of physical memory as holes correctly. Cc: Dave Hansen <haveblue@us.ibm.com> Cc: Andy Whitcroft <apw@shadowen.org> Cc: Andi Kleen <ak@muc.de> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mackerras <paulus@samba.org> Cc: "Keith Mannthey" <kmannth@gmail.com> Cc: "Luck, Tony" <tony.luck@intel.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Yasunori Goto <y-goto@jp.fujitsu.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/x86_64/mm/srat.c4
-rw-r--r--mm/page_alloc.c22
2 files changed, 22 insertions, 4 deletions
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c
index 7b50bb1caabe0..db1b2e11cf8f0 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 8d9a1eb9fbba9..75133e1dc4b1c 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 */