With sparse, pfn_to_page() becomes a somewhat more expensive operation. This patch makes use of the guarentee that *_mem_map will be contigious in sections aligned at MAX_ORDER to reduce the number of pfn_to_page() calls. By: Andy Whitcroft Signed-off-by: Dave Hansen --- memhotplug-dave/arch/i386/mm/discontig.c | 10 ++++++++-- memhotplug-dave/mm/bootmem.c | 14 +++++++++++++- memhotplug-dave/mm/page_alloc.c | 10 ++++++++-- 3 files changed, 29 insertions(+), 5 deletions(-) diff -puN arch/i386/mm/discontig.c~B-sparse-215-MAX_ORDER-optimisations arch/i386/mm/discontig.c --- memhotplug/arch/i386/mm/discontig.c~B-sparse-215-MAX_ORDER-optimisations 2005-02-17 15:25:42.000000000 -0800 +++ memhotplug-dave/arch/i386/mm/discontig.c 2005-02-17 15:25:42.000000000 -0800 @@ -392,10 +392,16 @@ void __init set_highmem_pages_init(int b zone->name, zone->zone_pgdat->node_id, zone_start_pfn, zone_end_pfn); - for (node_pfn = zone_start_pfn; node_pfn < zone_end_pfn; node_pfn++) { + /* + * Make use of the guarentee that *_mem_map will be + * contigious in sections aligned at MAX_ORDER. + */ + page = pfn_to_page(zone_start_pfn); + for (node_pfn = zone_start_pfn; node_pfn < zone_end_pfn; node_pfn++, page++) { if (!pfn_valid(node_pfn)) continue; - page = pfn_to_page(node_pfn); + if ((node_pfn & ((1 << MAX_ORDER) - 1)) == 0) + page = pfn_to_page(node_pfn); one_highpage_init(page, node_pfn, bad_ppro); } } diff -puN mm/bootmem.c~B-sparse-215-MAX_ORDER-optimisations mm/bootmem.c --- memhotplug/mm/bootmem.c~B-sparse-215-MAX_ORDER-optimisations 2005-02-17 15:25:42.000000000 -0800 +++ memhotplug-dave/mm/bootmem.c 2005-02-17 15:25:42.000000000 -0800 @@ -274,10 +274,21 @@ static unsigned long __init free_all_boo if (bdata->node_boot_start == 0 || ffs(bdata->node_boot_start) - PAGE_SHIFT > ffs(BITS_PER_LONG)) gofast = 1; + + /* + * APW/XXX: we are making an assumption that our node_boot_start + * is aligned to BITS_PER_LONG ... is this valid/enforced. + */ + /* + * Make use of the guarentee that *_mem_map will be + * contigious in sections aligned at MAX_ORDER. + */ + page = pfn_to_page(pfn); for (i = 0; i < idx; ) { unsigned long v = ~map[i / BITS_PER_LONG]; - page = pfn_to_page(pfn); + if ((pfn & ((1 << MAX_ORDER) - 1)) == 0) + page = pfn_to_page(pfn); if (gofast && v == ~0UL) { int j, order; @@ -306,6 +317,7 @@ static unsigned long __init free_all_boo } } else { i+=BITS_PER_LONG; + page += BITS_PER_LONG; } pfn += BITS_PER_LONG; } diff -puN mm/page_alloc.c~B-sparse-215-MAX_ORDER-optimisations mm/page_alloc.c --- memhotplug/mm/page_alloc.c~B-sparse-215-MAX_ORDER-optimisations 2005-02-17 15:25:42.000000000 -0800 +++ memhotplug-dave/mm/page_alloc.c 2005-02-17 15:25:42.000000000 -0800 @@ -1560,10 +1560,16 @@ void __init memmap_init_zone(unsigned lo struct page *page; int pfn; - for (pfn = start_pfn; pfn < (start_pfn + size); pfn++) { + /* + * Make use of the guarentee that *_mem_map will be + * contigious in sections aligned at MAX_ORDER. + */ + page = pfn_to_page(start_pfn); + for (pfn = start_pfn; pfn < (start_pfn + size); pfn++, page++) { if (!early_pfn_valid(pfn)) continue; - page = pfn_to_page(pfn); + if ((pfn & ((1 << MAX_ORDER) - 1)) == 0) + page = pfn_to_page(pfn); set_page_links(page, zone, nid, pfn); set_page_count(page, 0); reset_page_mapcount(page); _