From 523b945855a1427000ffc707c610abe5947ae607 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Tue, 16 Oct 2007 01:25:37 -0700 Subject: Memoryless nodes: Fix GFP_THISNODE behavior GFP_THISNODE checks that the zone selected is within the pgdat (node) of the first zone of a nodelist. That only works if the node has memory. A memoryless node will have its first node on another pgdat (node). GFP_THISNODE currently will return simply memory on the first pgdat. Thus it is returning memory on other nodes. GFP_THISNODE should fail if there is no local memory on a node. Add a new set of zonelists for each node that only contain the nodes that belong to the zones itself so that no fallback is possible. Then modify gfp_type to pickup the right zone based on the presence of __GFP_THISNODE. Drop the existing GFP_THISNODE checks from the page_allocators hot path. Signed-off-by: Christoph Lameter Acked-by: Nishanth Aravamudan Tested-by: Lee Schermerhorn Acked-by: Bob Picco Cc: KAMEZAWA Hiroyuki Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/gfp.h | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'include/linux/gfp.h') diff --git a/include/linux/gfp.h b/include/linux/gfp.h index bc68dd9a6d4..12a90a191c1 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -98,22 +98,29 @@ struct vm_area_struct; static inline enum zone_type gfp_zone(gfp_t flags) { + int base = 0; + +#ifdef CONFIG_NUMA + if (flags & __GFP_THISNODE) + base = MAX_NR_ZONES; +#endif + #ifdef CONFIG_ZONE_DMA if (flags & __GFP_DMA) - return ZONE_DMA; + return base + ZONE_DMA; #endif #ifdef CONFIG_ZONE_DMA32 if (flags & __GFP_DMA32) - return ZONE_DMA32; + return base + ZONE_DMA32; #endif if ((flags & (__GFP_HIGHMEM | __GFP_MOVABLE)) == (__GFP_HIGHMEM | __GFP_MOVABLE)) - return ZONE_MOVABLE; + return base + ZONE_MOVABLE; #ifdef CONFIG_HIGHMEM if (flags & __GFP_HIGHMEM) - return ZONE_HIGHMEM; + return base + ZONE_HIGHMEM; #endif - return ZONE_NORMAL; + return base + ZONE_NORMAL; } /* -- cgit v1.2.3