Singe zone per pdat optimization If we only have a single zone per node / pgdat then we do not need the zone_pgdat link but can directly calculate the pgdat address from zone since pgdat embedds the zone struct. This avoids one indirection on critical VM paths. Signed-off-by: Christoph Lameter Index: linux-2.6.18-rc6-mm1/include/linux/mmzone.h =================================================================== --- linux-2.6.18-rc6-mm1.orig/include/linux/mmzone.h 2006-09-11 20:55:13.828669134 -0500 +++ linux-2.6.18-rc6-mm1/include/linux/mmzone.h 2006-09-11 20:55:15.330748346 -0500 @@ -280,7 +280,12 @@ /* * Discontig memory support fields. */ +#ifdef MULTI_ZONE struct pglist_data *zone_pgdat; +#define get_pgdat(__zone) ((__zone)->zone_pgdat) +#else +#define get_pgdat(__zone) container_of((__zone), struct pglist_data, node_zones[0]) +#endif /* zone_start_pfn == zone_start_paddr >> PAGE_SHIFT */ unsigned long zone_start_pfn; Index: linux-2.6.18-rc6-mm1/mm/page_alloc.c =================================================================== --- linux-2.6.18-rc6-mm1.orig/mm/page_alloc.c 2006-09-11 20:50:24.795620827 -0500 +++ linux-2.6.18-rc6-mm1/mm/page_alloc.c 2006-09-11 20:55:15.350281236 -0500 @@ -960,7 +960,7 @@ do { zone = *z; if (unlikely((gfp_mask & __GFP_THISNODE) && - zone->zone_pgdat != zonelist->zones[0]->zone_pgdat)) + get_pgdat(zone) != get_pgdat(zonelist->zones[0]))) break; if ((alloc_flags & ALLOC_CPUSET) && !cpuset_zone_allowed(zone, gfp_mask)) @@ -2015,7 +2015,7 @@ int zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages) { int i; - struct pglist_data *pgdat = zone->zone_pgdat; + struct pglist_data *pgdat = get_pgdat(zone); size_t alloc_size; /* @@ -2077,7 +2077,7 @@ unsigned long zone_start_pfn, unsigned long size) { - struct pglist_data *pgdat = zone->zone_pgdat; + struct pglist_data *pgdat = get_pgdat(zone); int ret; ret = zone_wait_table_init(zone, size); if (ret) @@ -2518,7 +2518,9 @@ spin_lock_init(&zone->lock); spin_lock_init(&zone->lru_lock); zone_seqlock_init(zone); +#ifdef MULTI_ZONE zone->zone_pgdat = pgdat; +#endif zone->free_pages = 0; zone->temp_priority = zone->prev_priority = DEF_PRIORITY; Index: linux-2.6.18-rc6-mm1/mm/vmscan.c =================================================================== --- linux-2.6.18-rc6-mm1.orig/mm/vmscan.c 2006-09-11 18:15:47.174632184 -0500 +++ linux-2.6.18-rc6-mm1/mm/vmscan.c 2006-09-11 20:55:15.364930903 -0500 @@ -1298,7 +1298,7 @@ if (!populated_zone(zone)) return; - pgdat = zone->zone_pgdat; + pgdat = get_pgdat(zone); if (zone_watermark_ok(zone, order, zone->pages_low, 0, 0)) return; if (pgdat->kswapd_max_order < order) Index: linux-2.6.18-rc6-mm1/mm/vmstat.c =================================================================== --- linux-2.6.18-rc6-mm1.orig/mm/vmstat.c 2006-09-11 20:50:24.771204715 -0500 +++ linux-2.6.18-rc6-mm1/mm/vmstat.c 2006-09-11 20:55:15.374697348 -0500 @@ -364,13 +364,13 @@ */ void zone_statistics(struct zonelist *zonelist, struct zone *z) { - if (z->zone_pgdat == zonelist->zones[0]->zone_pgdat) { + if (get_pgdat(z) == get_pgdat(zonelist->zones[0])) { __inc_zone_state(z, NUMA_HIT); } else { __inc_zone_state(z, NUMA_MISS); __inc_zone_state(zonelist->zones[0], NUMA_FOREIGN); } - if (z->zone_pgdat == NODE_DATA(numa_node_id())) + if (get_pgdat(z) == NODE_DATA(numa_node_id())) __inc_zone_state(z, NUMA_LOCAL); else __inc_zone_state(z, NUMA_OTHER); Index: linux-2.6.18-rc6-mm1/mm/mmzone.c =================================================================== --- linux-2.6.18-rc6-mm1.orig/mm/mmzone.c 2006-09-11 18:15:47.189281864 -0500 +++ linux-2.6.18-rc6-mm1/mm/mmzone.c 2006-09-11 20:55:15.381533859 -0500 @@ -32,11 +32,14 @@ */ struct zone *next_zone(struct zone *zone) { - pg_data_t *pgdat = zone->zone_pgdat; + pg_data_t *pgdat = get_pgdat(zone); +#ifdef MULTI_ZONE if (zone < pgdat->node_zones + MAX_NR_ZONES - 1) zone++; - else { + else +#endif + { pgdat = next_online_pgdat(pgdat); if (pgdat) zone = pgdat->node_zones; Index: linux-2.6.18-rc6-mm1/mm/sparse.c =================================================================== --- linux-2.6.18-rc6-mm1.orig/mm/sparse.c 2006-09-11 18:15:47.199048317 -0500 +++ linux-2.6.18-rc6-mm1/mm/sparse.c 2006-09-11 20:55:15.389347015 -0500 @@ -274,7 +274,7 @@ int nr_pages) { unsigned long section_nr = pfn_to_section_nr(start_pfn); - struct pglist_data *pgdat = zone->zone_pgdat; + struct pglist_data *pgdat = get_pgdat(zone); struct mem_section *ms; struct page *memmap; unsigned long flags; Index: linux-2.6.18-rc6-mm1/include/linux/mm.h =================================================================== --- linux-2.6.18-rc6-mm1.orig/include/linux/mm.h 2006-09-11 20:50:12.491853422 -0500 +++ linux-2.6.18-rc6-mm1/include/linux/mm.h 2006-09-11 20:55:15.401066749 -0500 @@ -519,7 +519,7 @@ static inline unsigned long zone_to_nid(struct zone *zone) { - return zone->zone_pgdat->node_id; + return get_pgdat(zone)->node_id; } #if !FLAGS_HAS_NODE