diff options
| author | Mel Gorman <mel@skynet.ie> | 2006-09-27 04:49:59 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-27 11:26:12 -0400 |
| commit | fb01439c5b778d5974a488c5d4fe85e6d0e18a68 (patch) | |
| tree | dd5483b2555adbdc51f215fcb010484d423f63a0 /mm/page_alloc.c | |
| parent | 9c7cd6877cf8db15269163deda69392263124c1e (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>
Diffstat (limited to 'mm/page_alloc.c')
| -rw-r--r-- | mm/page_alloc.c | 67 |
1 files changed, 67 insertions, 0 deletions
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 | ||
| 2114 | void __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 */ | ||
| 2132 | static 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 | ||
| 2149 | void __init push_node_boundaries(unsigned int nid, | ||
| 2150 | unsigned long start_pfn, unsigned long end_pfn) {} | ||
| 2151 | |||
| 2152 | static 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 */ |
