From: Dave Hansen When using CONFIG_NONLINEAR, a zone's mem_map isn't contiguous, and isn't allocated in the same place. This means that nonlinear doesn't really have a mem_map[] to pass into free_area_init_node() or memmap_init_zone() which makes any sense. So, this patch removes the 'struct page *mem_map' argument to both of those functions. All non-NUMA architectures just pass a NULL in there, which is ignored. The solution on the NUMA arches is to pass the mem_map in via the pgdat, which works just fine. To replace the removed arguments, a call to pfn_to_page(node_start_pfn) is made. This is valid because all of the pfn_to_page() implementations rely only on the pgdats, which are already set up at this time. Plus, the pfn_to_page() method should work for any future nonlinear-type code. Finally, the patch creates a function: node_alloc_mem_map(), which I plan to effectively #ifdef out for nonlinear at some future date. Compile tested and booted on SMP x86, NUMAQ, and ppc64. Signed-off-by: Andrew Morton --- 25-akpm/arch/alpha/mm/numa.c | 2 +- 25-akpm/arch/ia64/mm/contig.c | 3 ++- 25-akpm/arch/ia64/mm/init.c | 2 +- 25-akpm/arch/ppc64/mm/init.c | 2 +- 25-akpm/arch/sh/mm/init.c | 2 +- 25-akpm/include/linux/mm.h | 5 ++--- 25-akpm/mm/page_alloc.c | 39 +++++++++++++++++++++------------------ 7 files changed, 29 insertions(+), 26 deletions(-) diff -puN arch/alpha/mm/numa.c~dont-pass-mem_map-into-init-functions arch/alpha/mm/numa.c --- 25/arch/alpha/mm/numa.c~dont-pass-mem_map-into-init-functions 2004-08-09 22:02:09.989110472 -0700 +++ 25-akpm/arch/alpha/mm/numa.c 2004-08-09 22:02:10.002108496 -0700 @@ -313,7 +313,7 @@ void __init paging_init(void) zones_size[ZONE_DMA] = dma_local_pfn; zones_size[ZONE_NORMAL] = (end_pfn - start_pfn) - dma_local_pfn; } - free_area_init_node(nid, NODE_DATA(nid), NULL, zones_size, start_pfn, NULL); + free_area_init_node(nid, NODE_DATA(nid), zones_size, start_pfn, NULL); } /* Initialize the kernel's ZERO_PGE. */ diff -puN arch/ia64/mm/contig.c~dont-pass-mem_map-into-init-functions arch/ia64/mm/contig.c --- 25/arch/ia64/mm/contig.c~dont-pass-mem_map-into-init-functions 2004-08-09 22:02:09.990110320 -0700 +++ 25-akpm/arch/ia64/mm/contig.c 2004-08-09 22:02:10.003108344 -0700 @@ -280,7 +280,8 @@ paging_init (void) vmem_map = (struct page *) vmalloc_end; efi_memmap_walk(create_mem_map_page_table, 0); - free_area_init_node(0, &contig_page_data, vmem_map, zones_size, + contig_page_data.node_mem_map = vmem_map; + free_area_init_node(0, &contig_page_data, zones_size, 0, zholes_size); mem_map = contig_page_data.node_mem_map; diff -puN arch/ia64/mm/init.c~dont-pass-mem_map-into-init-functions arch/ia64/mm/init.c --- 25/arch/ia64/mm/init.c~dont-pass-mem_map-into-init-functions 2004-08-09 22:02:09.991110168 -0700 +++ 25-akpm/arch/ia64/mm/init.c 2004-08-09 22:02:10.003108344 -0700 @@ -439,7 +439,7 @@ memmap_init (struct page *start, unsigne unsigned long zone, unsigned long start_pfn) { if (!vmem_map) - memmap_init_zone(start, size, nid, zone, start_pfn); + memmap_init_zone(size, nid, zone, start_pfn); else { struct memmap_init_callback_data args; diff -puN arch/ppc64/mm/init.c~dont-pass-mem_map-into-init-functions arch/ppc64/mm/init.c --- 25/arch/ppc64/mm/init.c~dont-pass-mem_map-into-init-functions 2004-08-09 22:02:09.993109864 -0700 +++ 25-akpm/arch/ppc64/mm/init.c 2004-08-09 22:02:10.004108192 -0700 @@ -587,7 +587,7 @@ void __init paging_init(void) zones_size[ZONE_DMA] = top_of_ram >> PAGE_SHIFT; zholes_size[ZONE_DMA] = (top_of_ram - total_ram) >> PAGE_SHIFT; - free_area_init_node(0, &contig_page_data, NULL, zones_size, + free_area_init_node(0, &contig_page_data, zones_size, __pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size); mem_map = contig_page_data.node_mem_map; } diff -puN arch/sh/mm/init.c~dont-pass-mem_map-into-init-functions arch/sh/mm/init.c --- 25/arch/sh/mm/init.c~dont-pass-mem_map-into-init-functions 2004-08-09 22:02:09.996109408 -0700 +++ 25-akpm/arch/sh/mm/init.c 2004-08-09 22:02:10.004108192 -0700 @@ -225,7 +225,7 @@ void __init paging_init(void) */ zones_size[ZONE_DMA] = __MEMORY_SIZE_2ND >> PAGE_SHIFT; zones_size[ZONE_NORMAL] = 0; - free_area_init_node(1, NODE_DATA(1), 0, zones_size, __MEMORY_START_2ND >> PAGE_SHIFT, 0); + free_area_init_node(1, NODE_DATA(1), zones_size, __MEMORY_START_2ND >> PAGE_SHIFT, 0); #endif } diff -puN include/linux/mm.h~dont-pass-mem_map-into-init-functions include/linux/mm.h --- 25/include/linux/mm.h~dont-pass-mem_map-into-init-functions 2004-08-09 22:02:09.997109256 -0700 +++ 25-akpm/include/linux/mm.h 2004-08-09 22:02:10.005108040 -0700 @@ -590,11 +590,10 @@ static inline pmd_t *pmd_alloc(struct mm } extern void free_area_init(unsigned long * zones_size); -extern void free_area_init_node(int nid, pg_data_t *pgdat, struct page *pmap, +extern void free_area_init_node(int nid, pg_data_t *pgdat, unsigned long * zones_size, unsigned long zone_start_pfn, unsigned long *zholes_size); -extern void memmap_init_zone(struct page *, unsigned long, int, - unsigned long, unsigned long); +extern void memmap_init_zone(unsigned long, int, unsigned long, unsigned long); extern void mem_init(void); extern void show_mem(void); extern void si_meminfo(struct sysinfo * val); diff -puN mm/page_alloc.c~dont-pass-mem_map-into-init-functions mm/page_alloc.c --- 25/mm/page_alloc.c~dont-pass-mem_map-into-init-functions 2004-08-09 22:02:09.999108952 -0700 +++ 25-akpm/mm/page_alloc.c 2004-08-09 22:02:10.007107736 -0700 @@ -1385,9 +1385,10 @@ static void __init calculate_zone_totalp * up by free_all_bootmem() once the early boot process is * done. Non-atomic initialization, single-pass. */ -void __init memmap_init_zone(struct page *start, unsigned long size, int nid, - unsigned long zone, unsigned long start_pfn) +void __init memmap_init_zone(unsigned long size, int nid, unsigned long zone, + unsigned long start_pfn) { + struct page *start = pfn_to_page(start_pfn); struct page *page; for (page = start; page < (start + size); page++) { @@ -1451,8 +1452,8 @@ void zone_init_free_lists(struct pglist_ } #ifndef __HAVE_ARCH_MEMMAP_INIT -#define memmap_init(start, size, nid, zone, start_pfn) \ - memmap_init_zone((start), (size), (nid), (zone), (start_pfn)) +#define memmap_init(size, nid, zone, start_pfn) \ + memmap_init_zone((size), (nid), (zone), (start_pfn)) #endif /* @@ -1467,7 +1468,6 @@ static void __init free_area_init_core(s unsigned long i, j; const unsigned long zone_required_alignment = 1UL << (MAX_ORDER-1); int cpu, nid = pgdat->node_id; - struct page *lmem_map = pgdat->node_mem_map; unsigned long zone_start_pfn = pgdat->node_start_pfn; pgdat->nr_zones = 0; @@ -1555,35 +1555,39 @@ static void __init free_area_init_core(s pgdat->nr_zones = j+1; - zone->zone_mem_map = lmem_map; + zone->zone_mem_map = pfn_to_page(zone_start_pfn); zone->zone_start_pfn = zone_start_pfn; if ((zone_start_pfn) & (zone_required_alignment-1)) printk("BUG: wrong zone alignment, it will crash\n"); - memmap_init(lmem_map, size, nid, j, zone_start_pfn); + memmap_init(size, nid, j, zone_start_pfn); zone_start_pfn += size; - lmem_map += size; zone_init_free_lists(pgdat, zone, zone->spanned_pages); } } -void __init free_area_init_node(int nid, struct pglist_data *pgdat, - struct page *node_mem_map, unsigned long *zones_size, - unsigned long node_start_pfn, unsigned long *zholes_size) +void __init node_alloc_mem_map(struct pglist_data *pgdat) { unsigned long size; + size = (pgdat->node_spanned_pages + 1) * sizeof(struct page); + pgdat->node_mem_map = alloc_bootmem_node(pgdat, size); + mem_map = contig_page_data.node_mem_map; +} + +void __init free_area_init_node(int nid, struct pglist_data *pgdat, + unsigned long *zones_size, unsigned long node_start_pfn, + unsigned long *zholes_size) +{ pgdat->node_id = nid; pgdat->node_start_pfn = node_start_pfn; calculate_zone_totalpages(pgdat, zones_size, zholes_size); - if (!node_mem_map) { - size = (pgdat->node_spanned_pages + 1) * sizeof(struct page); - node_mem_map = alloc_bootmem_node(pgdat, size); - } - pgdat->node_mem_map = node_mem_map; + + if (!pfn_to_page(node_start_pfn)) + node_alloc_mem_map(pgdat); free_area_init_core(pgdat, zones_size, zholes_size); } @@ -1596,9 +1600,8 @@ EXPORT_SYMBOL(contig_page_data); void __init free_area_init(unsigned long *zones_size) { - free_area_init_node(0, &contig_page_data, NULL, zones_size, + free_area_init_node(0, &contig_page_data, zones_size, __pa(PAGE_OFFSET) >> PAGE_SHIFT, NULL); - mem_map = contig_page_data.node_mem_map; } #endif _