aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBob Picco <bob.picco@hp.com>2006-05-20 18:00:31 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-05-21 15:59:22 -0400
commite984bb43f7450312ba66fe0e67a99efa6be3b246 (patch)
tree54c86240172136fc81c773f71cd70eda54fed6f2
parentae57a856429dd932c547530df1b234eb7e642297 (diff)
[PATCH] Align the node_mem_map endpoints to a MAX_ORDER boundary
Andy added code to buddy allocator which does not require the zone's endpoints to be aligned to MAX_ORDER. An issue is that the buddy allocator requires the node_mem_map's endpoints to be MAX_ORDER aligned. Otherwise __page_find_buddy could compute a buddy not in node_mem_map for partial MAX_ORDER regions at zone's endpoints. page_is_buddy will detect that these pages at endpoints are not PG_buddy (they were zeroed out by bootmem allocator and not part of zone). Of course the negative here is we could waste a little memory but the positive is eliminating all the old checks for zone boundary conditions. SPARSEMEM won't encounter this issue because of MAX_ORDER size constraint when SPARSEMEM is configured. ia64 VIRTUAL_MEM_MAP doesn't need the logic either because the holes and endpoints are handled differently. This leaves checking alloc_remap and other arches which privately allocate for node_mem_map. Signed-off-by: Bob Picco <bob.picco@hp.com> Acked-by: Mel Gorman <mel@csn.ul.ie> Cc: Dave Hansen <haveblue@us.ibm.com> Cc: Andy Whitcroft <apw@shadowen.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--include/linux/mmzone.h1
-rw-r--r--mm/page_alloc.c14
2 files changed, 12 insertions, 3 deletions
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index b5c21122c299..36740354d4db 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -22,6 +22,7 @@
22#else 22#else
23#define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER 23#define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER
24#endif 24#endif
25#define MAX_ORDER_NR_PAGES (1 << (MAX_ORDER - 1))
25 26
26struct free_area { 27struct free_area {
27 struct list_head free_list; 28 struct list_head free_list;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index bb3416932ab0..253a450c400d 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2125,14 +2125,22 @@ static void __init alloc_node_mem_map(struct pglist_data *pgdat)
2125#ifdef CONFIG_FLAT_NODE_MEM_MAP 2125#ifdef CONFIG_FLAT_NODE_MEM_MAP
2126 /* ia64 gets its own node_mem_map, before this, without bootmem */ 2126 /* ia64 gets its own node_mem_map, before this, without bootmem */
2127 if (!pgdat->node_mem_map) { 2127 if (!pgdat->node_mem_map) {
2128 unsigned long size; 2128 unsigned long size, start, end;
2129 struct page *map; 2129 struct page *map;
2130 2130
2131 size = (pgdat->node_spanned_pages + 1) * sizeof(struct page); 2131 /*
2132 * The zone's endpoints aren't required to be MAX_ORDER
2133 * aligned but the node_mem_map endpoints must be in order
2134 * for the buddy allocator to function correctly.
2135 */
2136 start = pgdat->node_start_pfn & ~(MAX_ORDER_NR_PAGES - 1);
2137 end = pgdat->node_start_pfn + pgdat->node_spanned_pages;
2138 end = ALIGN(end, MAX_ORDER_NR_PAGES);
2139 size = (end - start) * sizeof(struct page);
2132 map = alloc_remap(pgdat->node_id, size); 2140 map = alloc_remap(pgdat->node_id, size);
2133 if (!map) 2141 if (!map)
2134 map = alloc_bootmem_node(pgdat, size); 2142 map = alloc_bootmem_node(pgdat, size);
2135 pgdat->node_mem_map = map; 2143 pgdat->node_mem_map = map + (pgdat->node_start_pfn - start);
2136 } 2144 }
2137#ifdef CONFIG_FLATMEM 2145#ifdef CONFIG_FLATMEM
2138 /* 2146 /*