aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMel Gorman <mel@skynet.ie>2006-09-27 04:49:59 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-27 11:26:12 -0400
commitfb01439c5b778d5974a488c5d4fe85e6d0e18a68 (patch)
treedd5483b2555adbdc51f215fcb010484d423f63a0
parent9c7cd6877cf8db15269163deda69392263124c1e (diff)
[PATCH] Allow an arch to expand node boundaries
Arch-independent zone-sizing determines the size of a node (pgdat->node_spanned_pages) based on the physical memory that was registered by the architecture. However, when CONFIG_MEMORY_HOTPLUG_RESERVE is set, the architecture expects that the spanned_pages will be much larger and that mem_map will be allocated that is used lated on memory hot-add. This patch allows an architecture that sets CONFIG_MEMORY_HOTPLUG_RESERVE to call push_node_boundaries() which will set the node beginning and end to at *least* the requested boundary. 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.c2
-rw-r--r--include/linux/mm.h2
-rw-r--r--mm/page_alloc.c67
3 files changed, 71 insertions, 0 deletions
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c
index db1b2e11cf8f..f8c04d6935c9 100644
--- a/arch/x86_64/mm/srat.c
+++ b/arch/x86_64/mm/srat.c
@@ -324,6 +324,8 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
324 nd->start, nd->end); 324 nd->start, nd->end);
325 e820_register_active_regions(node, nd->start >> PAGE_SHIFT, 325 e820_register_active_regions(node, nd->start >> PAGE_SHIFT,
326 nd->end >> PAGE_SHIFT); 326 nd->end >> PAGE_SHIFT);
327 push_node_boundaries(node, nd->start >> PAGE_SHIFT,
328 nd->end >> PAGE_SHIFT);
327 329
328#ifdef RESERVE_HOTADD 330#ifdef RESERVE_HOTADD
329 if (ma->flags.hot_pluggable && reserve_hotadd(node, start, end) < 0) { 331 if (ma->flags.hot_pluggable && reserve_hotadd(node, start, end) < 0) {
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 22936e1fcdf2..9d046db31e76 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -970,6 +970,8 @@ extern void add_active_range(unsigned int nid, unsigned long start_pfn,
970 unsigned long end_pfn); 970 unsigned long end_pfn);
971extern void shrink_active_range(unsigned int nid, unsigned long old_end_pfn, 971extern void shrink_active_range(unsigned int nid, unsigned long old_end_pfn,
972 unsigned long new_end_pfn); 972 unsigned long new_end_pfn);
973extern void push_node_boundaries(unsigned int nid, unsigned long start_pfn,
974 unsigned long end_pfn);
973extern void remove_all_active_ranges(void); 975extern void remove_all_active_ranges(void);
974extern unsigned long absent_pages_in_range(unsigned long start_pfn, 976extern unsigned long absent_pages_in_range(unsigned long start_pfn,
975 unsigned long end_pfn); 977 unsigned long end_pfn);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 75133e1dc4b1..acbf58f8a1b7 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -131,6 +131,10 @@ static unsigned long __initdata dma_reserve;
131 int __initdata nr_nodemap_entries; 131 int __initdata nr_nodemap_entries;
132 unsigned long __initdata arch_zone_lowest_possible_pfn[MAX_NR_ZONES]; 132 unsigned long __initdata arch_zone_lowest_possible_pfn[MAX_NR_ZONES];
133 unsigned long __initdata arch_zone_highest_possible_pfn[MAX_NR_ZONES]; 133 unsigned long __initdata arch_zone_highest_possible_pfn[MAX_NR_ZONES];
134#ifdef CONFIG_MEMORY_HOTPLUG_RESERVE
135 unsigned long __initdata node_boundary_start_pfn[MAX_NUMNODES];
136 unsigned long __initdata node_boundary_end_pfn[MAX_NUMNODES];
137#endif /* CONFIG_MEMORY_HOTPLUG_RESERVE */
134#endif /* CONFIG_ARCH_POPULATES_NODE_MAP */ 138#endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
135 139
136#ifdef CONFIG_DEBUG_VM 140#ifdef CONFIG_DEBUG_VM
@@ -2095,6 +2099,62 @@ void __init sparse_memory_present_with_active_regions(int nid)
2095} 2099}
2096 2100
2097/** 2101/**
2102 * push_node_boundaries - Push node boundaries to at least the requested boundary
2103 * @nid: The nid of the node to push the boundary for
2104 * @start_pfn: The start pfn of the node
2105 * @end_pfn: The end pfn of the node
2106 *
2107 * In reserve-based hot-add, mem_map is allocated that is unused until hotadd
2108 * time. Specifically, on x86_64, SRAT will report ranges that can potentially
2109 * be hotplugged even though no physical memory exists. This function allows
2110 * an arch to push out the node boundaries so mem_map is allocated that can
2111 * be used later.
2112 */
2113#ifdef CONFIG_MEMORY_HOTPLUG_RESERVE
2114void __init push_node_boundaries(unsigned int nid,
2115 unsigned long start_pfn, unsigned long end_pfn)
2116{
2117 printk(KERN_DEBUG "Entering push_node_boundaries(%u, %lu, %lu)\n",
2118 nid, start_pfn, end_pfn);
2119
2120 /* Initialise the boundary for this node if necessary */
2121 if (node_boundary_end_pfn[nid] == 0)
2122 node_boundary_start_pfn[nid] = -1UL;
2123
2124 /* Update the boundaries */
2125 if (node_boundary_start_pfn[nid] > start_pfn)
2126 node_boundary_start_pfn[nid] = start_pfn;
2127 if (node_boundary_end_pfn[nid] < end_pfn)
2128 node_boundary_end_pfn[nid] = end_pfn;
2129}
2130
2131/* If necessary, push the node boundary out for reserve hotadd */
2132static void __init account_node_boundary(unsigned int nid,
2133 unsigned long *start_pfn, unsigned long *end_pfn)
2134{
2135 printk(KERN_DEBUG "Entering account_node_boundary(%u, %lu, %lu)\n",
2136 nid, *start_pfn, *end_pfn);
2137
2138 /* Return if boundary information has not been provided */
2139 if (node_boundary_end_pfn[nid] == 0)
2140 return;
2141
2142 /* Check the boundaries and update if necessary */
2143 if (node_boundary_start_pfn[nid] < *start_pfn)
2144 *start_pfn = node_boundary_start_pfn[nid];
2145 if (node_boundary_end_pfn[nid] > *end_pfn)
2146 *end_pfn = node_boundary_end_pfn[nid];
2147}
2148#else
2149void __init push_node_boundaries(unsigned int nid,
2150 unsigned long start_pfn, unsigned long end_pfn) {}
2151
2152static void __init account_node_boundary(unsigned int nid,
2153 unsigned long *start_pfn, unsigned long *end_pfn) {}
2154#endif
2155
2156
2157/**
2098 * get_pfn_range_for_nid - Return the start and end page frames for a node 2158 * get_pfn_range_for_nid - Return the start and end page frames for a node
2099 * @nid: The nid to return the range for. If MAX_NUMNODES, the min and max PFN are returned 2159 * @nid: The nid to return the range for. If MAX_NUMNODES, the min and max PFN are returned
2100 * @start_pfn: Passed by reference. On return, it will have the node start_pfn 2160 * @start_pfn: Passed by reference. On return, it will have the node start_pfn
@@ -2121,6 +2181,9 @@ void __init get_pfn_range_for_nid(unsigned int nid,
2121 printk(KERN_WARNING "Node %u active with no memory\n", nid); 2181 printk(KERN_WARNING "Node %u active with no memory\n", nid);
2122 *start_pfn = 0; 2182 *start_pfn = 0;
2123 } 2183 }
2184
2185 /* Push the node boundaries out if requested */
2186 account_node_boundary(nid, start_pfn, end_pfn);
2124} 2187}
2125 2188
2126/* 2189/*
@@ -2527,6 +2590,10 @@ void __init remove_all_active_ranges()
2527{ 2590{
2528 memset(early_node_map, 0, sizeof(early_node_map)); 2591 memset(early_node_map, 0, sizeof(early_node_map));
2529 nr_nodemap_entries = 0; 2592 nr_nodemap_entries = 0;
2593#ifdef CONFIG_MEMORY_HOTPLUG_RESERVE
2594 memset(node_boundary_start_pfn, 0, sizeof(node_boundary_start_pfn));
2595 memset(node_boundary_end_pfn, 0, sizeof(node_boundary_end_pfn));
2596#endif /* CONFIG_MEMORY_HOTPLUG_RESERVE */
2530} 2597}
2531 2598
2532/* Compare two active node_active_regions */ 2599/* Compare two active node_active_regions */