From: Matthew Dobson This patch does the following: 1) Rename ZONE_SHIFT to NODEZONE_SHIFT. This value is the number of bits to shift page->flags to get the node/zone part of the bitfield. 2) Add a macro called NODEZONE which takes a node number and zone number and returns a 'nodezone', a bitshifted composition of the two. 3) Create page_zonenum & page_nodenum, inline functions to return the node/zone a page belongs to with some simple bit twiddling, no pointer dereferences necessary. 4) Modify page_zone() and set_page_zone() to use the new NODEZONE_SHIFT. 5) Modify memmap_init_zone() & free_area_init_core() to use the new NODEZONE macros. 6) Fix up some comments to reflect the above changes. 25-akpm/include/linux/mm.h | 24 +++++++++++++++++------- 25-akpm/include/linux/mmzone.h | 15 +++++++++++---- 25-akpm/mm/page_alloc.c | 6 +++--- 3 files changed, 31 insertions(+), 14 deletions(-) diff -puN include/linux/mm.h~simplify-node-zone-fields-3 include/linux/mm.h --- 25/include/linux/mm.h~simplify-node-zone-fields-3 Tue Jan 6 14:44:12 2004 +++ 25-akpm/include/linux/mm.h Tue Jan 6 14:44:12 2004 @@ -330,23 +330,33 @@ static inline void put_page(struct page /* * The zone field is never updated after free_area_init_core() * sets it, so none of the operations on it need to be atomic. - * We'll have up to log2(MAX_NUMNODES * MAX_NR_ZONES) zones - * total, so we use NODES_SHIFT here to get enough bits. + * We'll have up to (MAX_NUMNODES * MAX_NR_ZONES) zones total, + * so we use (MAX_NODES_SHIFT + MAX_ZONES_SHIFT) here to get enough bits. */ -#define ZONE_SHIFT (BITS_PER_LONG - NODES_SHIFT - MAX_NR_ZONES_SHIFT) +#define NODEZONE_SHIFT (BITS_PER_LONG - MAX_NODES_SHIFT - MAX_ZONES_SHIFT) +#define NODEZONE(node, zone) ((node << ZONES_SHIFT) | zone) + +static inline unsigned long page_zonenum(struct page *page) +{ + return (page->flags >> NODEZONE_SHIFT) & (~(~0UL << ZONES_SHIFT)); +} +static inline unsigned long page_nodenum(struct page *page) +{ + return (page->flags >> (NODEZONE_SHIFT + ZONES_SHIFT)); +} struct zone; extern struct zone *zone_table[]; static inline struct zone *page_zone(struct page *page) { - return zone_table[page->flags >> ZONE_SHIFT]; + return zone_table[page->flags >> NODEZONE_SHIFT]; } -static inline void set_page_zone(struct page *page, unsigned long zone_num) +static inline void set_page_zone(struct page *page, unsigned long nodezone_num) { - page->flags &= ~(~0UL << ZONE_SHIFT); - page->flags |= zone_num << ZONE_SHIFT; + page->flags &= ~(~0UL << NODEZONE_SHIFT); + page->flags |= nodezone_num << NODEZONE_SHIFT; } #ifndef CONFIG_DISCONTIGMEM diff -puN include/linux/mmzone.h~simplify-node-zone-fields-3 include/linux/mmzone.h --- 25/include/linux/mmzone.h~simplify-node-zone-fields-3 Tue Jan 6 14:44:12 2004 +++ 25-akpm/include/linux/mmzone.h Tue Jan 6 14:44:12 2004 @@ -160,8 +160,8 @@ struct zone { #define ZONE_NORMAL 1 #define ZONE_HIGHMEM 2 -#define MAX_NR_ZONES 3 /* Sync this with MAX_NR_ZONES_SHIFT */ -#define MAX_NR_ZONES_SHIFT 2 /* ceil(log2(MAX_NR_ZONES)) */ +#define MAX_NR_ZONES 3 /* Sync this with ZONES_SHIFT */ +#define ZONES_SHIFT 2 /* ceil(log2(MAX_NR_ZONES)) */ #define GFP_ZONEMASK 0x03 @@ -303,7 +303,7 @@ int min_free_kbytes_sysctl_handler(struc extern struct pglist_data contig_page_data; #define NODE_DATA(nid) (&contig_page_data) #define NODE_MEM_MAP(nid) mem_map -#define MAX_NODES_SHIFT 0 +#define MAX_NODES_SHIFT 1 #else /* CONFIG_DISCONTIGMEM */ @@ -311,7 +311,7 @@ extern struct pglist_data contig_page_da #if BITS_PER_LONG == 32 /* - * with 32 bit flags field, page->zone is currently 8 bits. + * with 32 bit page->flags field, we reserve 8 bits for node/zone info. * there are 3 zones (2 bits) and this leaves 8-2=6 bits for nodes. */ #define MAX_NODES_SHIFT 6 @@ -328,6 +328,13 @@ extern struct pglist_data contig_page_da #error NODES_SHIFT > MAX_NODES_SHIFT #endif +/* There are currently 3 zones: DMA, Normal & Highmem, thus we need 2 bits */ +#define MAX_ZONES_SHIFT 2 + +#if ZONES_SHIFT > MAX_ZONES_SHIFT +#error ZONES_SHIFT > MAX_ZONES_SHIFT +#endif + extern DECLARE_BITMAP(node_online_map, MAX_NUMNODES); extern DECLARE_BITMAP(memblk_online_map, MAX_NR_MEMBLKS); diff -puN mm/page_alloc.c~simplify-node-zone-fields-3 mm/page_alloc.c --- 25/mm/page_alloc.c~simplify-node-zone-fields-3 Tue Jan 6 14:44:12 2004 +++ 25-akpm/mm/page_alloc.c Tue Jan 6 14:44:12 2004 @@ -50,7 +50,7 @@ EXPORT_SYMBOL(nr_swap_pages); * Used by page_zone() to look up the address of the struct zone whose * id is encoded in the upper bits of page->flags */ -struct zone *zone_table[MAX_NR_ZONES*MAX_NUMNODES]; +struct zone *zone_table[1 << (ZONES_SHIFT + NODES_SHIFT)]; EXPORT_SYMBOL(zone_table); static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" }; @@ -1212,7 +1212,7 @@ void __init memmap_init_zone(struct page struct page *page; for (page = start; page < (start + size); page++) { - set_page_zone(page, nid * MAX_NR_ZONES + zone); + set_page_zone(page, NODEZONE(nid, zone)); set_page_count(page, 0); SetPageReserved(page); INIT_LIST_HEAD(&page->list); @@ -1253,7 +1253,7 @@ static void __init free_area_init_core(s unsigned long size, realsize; unsigned long batch; - zone_table[nid * MAX_NR_ZONES + j] = zone; + zone_table[NODEZONE(nid, j)] = zone; realsize = size = zones_size[j]; if (zholes_size) realsize -= zholes_size[j]; _