From: Dave Hansen This patch fixes this bug: http://bugme.osdl.org/show_bug.cgi?id=818 I decided to use the spanned_pages terminology to describe the whole physical range, instead of plain total pages. arch/i386/mm/pgtable.c | 2 +- include/asm-i386/mmzone.h | 3 +-- include/linux/mmzone.h | 3 ++- mm/page_alloc.c | 5 +++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff -puN arch/i386/mm/pgtable.c~numa-memory-reporting-fix arch/i386/mm/pgtable.c --- 25/arch/i386/mm/pgtable.c~numa-memory-reporting-fix 2003-06-26 18:41:57.000000000 -0700 +++ 25-akpm/arch/i386/mm/pgtable.c 2003-06-26 18:41:57.000000000 -0700 @@ -35,7 +35,7 @@ void show_mem(void) show_free_areas(); printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); for_each_pgdat(pgdat) { - for (i = 0; i < pgdat->node_size; ++i) { + for (i = 0; i < pgdat->node_spanned_size; ++i) { page = pgdat->node_mem_map + i; total++; if (PageHighMem(page)) diff -puN include/asm-i386/mmzone.h~numa-memory-reporting-fix include/asm-i386/mmzone.h --- 25/include/asm-i386/mmzone.h~numa-memory-reporting-fix 2003-06-26 18:41:57.000000000 -0700 +++ 25-akpm/include/asm-i386/mmzone.h 2003-06-26 18:41:57.000000000 -0700 @@ -32,7 +32,6 @@ extern struct pglist_data *node_data[]; #define alloc_bootmem_low_pages_node(ignore, x) \ __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0) -#define node_size(nid) (node_data[nid]->node_size) #define node_localnr(pfn, nid) ((pfn) - node_data[nid]->node_start_pfn) /* @@ -54,7 +53,7 @@ extern struct pglist_data *node_data[]; #define node_end_pfn(nid) \ ({ \ pg_data_t *__pgdat = NODE_DATA(nid); \ - __pgdat->node_start_pfn + __pgdat->node_size; \ + __pgdat->node_start_pfn + __pgdat->node_spanned_size; \ }) #define local_mapnr(kvaddr) \ diff -puN include/linux/mmzone.h~numa-memory-reporting-fix include/linux/mmzone.h --- 25/include/linux/mmzone.h~numa-memory-reporting-fix 2003-06-26 18:41:57.000000000 -0700 +++ 25-akpm/include/linux/mmzone.h 2003-06-26 18:41:57.000000000 -0700 @@ -184,7 +184,8 @@ typedef struct pglist_data { unsigned long *valid_addr_bitmap; struct bootmem_data *bdata; unsigned long node_start_pfn; - unsigned long node_size; + unsigned long node_spanned_size; /* size of the node with holes */ + unsigned long node_size; /* actual memory contained in the node */ int node_id; struct pglist_data *pgdat_next; wait_queue_head_t kswapd_wait; diff -puN mm/page_alloc.c~numa-memory-reporting-fix mm/page_alloc.c --- 25/mm/page_alloc.c~numa-memory-reporting-fix 2003-06-26 18:41:57.000000000 -0700 +++ 25-akpm/mm/page_alloc.c 2003-06-26 18:41:57.000000000 -0700 @@ -1143,12 +1143,13 @@ static void __init calculate_zone_totalp for (i = 0; i < MAX_NR_ZONES; i++) totalpages += zones_size[i]; - pgdat->node_size = totalpages; + pgdat->node_spanned_size = totalpages; realtotalpages = totalpages; if (zholes_size) for (i = 0; i < MAX_NR_ZONES; i++) realtotalpages -= zholes_size[i]; + pgdat->node_size = realtotalpages; printk("On node %d totalpages: %lu\n", pgdat->node_id, realtotalpages); } @@ -1354,7 +1355,7 @@ void __init free_area_init_node(int nid, pgdat->node_start_pfn = node_start_pfn; calculate_zone_totalpages(pgdat, zones_size, zholes_size); if (!node_mem_map) { - size = (pgdat->node_size + 1) * sizeof(struct page); + size = (pgdat->node_spanned_size + 1) * sizeof(struct page); node_mem_map = alloc_bootmem_node(pgdat, size); } pgdat->node_mem_map = node_mem_map; _