From 156cdd5548ced1c9102ecadf07e08bb2d2aabd68 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Wed, 22 Aug 2007 14:02:05 -0700 Subject: [PATCH] --- yaml --- r: 64271 b: refs/heads/master c: b377fd3982ad957c796758a90e2988401a884241 h: refs/heads/master i: 64269: 6bf20b91584649e75642a50531c452cfa40c280f 64267: 7f8fba42161f7d469ebb9ab6e8054b13886180ed 64263: df7a7792fc4f65845d3a3e650cd21b76aebf0e31 64255: 4024b621af56498fcaba69dcce0aabcd7ce79757 v: v3 --- [refs] | 2 +- trunk/include/linux/mempolicy.h | 2 +- trunk/include/linux/mmzone.h | 18 ++++++++++++++++++ trunk/mm/mempolicy.c | 2 +- trunk/mm/page_alloc.c | 13 +++++++++++++ 5 files changed, 34 insertions(+), 3 deletions(-) diff --git a/[refs] b/[refs] index fcef18377436..d1d3448d2a0d 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 8e92f21ba3ea3f54e4be062b87ef9fc4af2d33e2 +refs/heads/master: b377fd3982ad957c796758a90e2988401a884241 diff --git a/trunk/include/linux/mempolicy.h b/trunk/include/linux/mempolicy.h index e147cf50529f..5bdd656e88cf 100644 --- a/trunk/include/linux/mempolicy.h +++ b/trunk/include/linux/mempolicy.h @@ -166,7 +166,7 @@ extern enum zone_type policy_zone; static inline void check_highest_zone(enum zone_type k) { - if (k > policy_zone) + if (k > policy_zone && k != ZONE_MOVABLE) policy_zone = k; } diff --git a/trunk/include/linux/mmzone.h b/trunk/include/linux/mmzone.h index 3ea68cd3b61f..4e5627379b09 100644 --- a/trunk/include/linux/mmzone.h +++ b/trunk/include/linux/mmzone.h @@ -410,6 +410,24 @@ struct zonelist { #endif }; +#ifdef CONFIG_NUMA +/* + * Only custom zonelists like MPOL_BIND need to be filtered as part of + * policies. As described in the comment for struct zonelist_cache, these + * zonelists will not have a zlcache so zlcache_ptr will not be set. Use + * that to determine if the zonelists needs to be filtered or not. + */ +static inline int alloc_should_filter_zonelist(struct zonelist *zonelist) +{ + return !zonelist->zlcache_ptr; +} +#else +static inline int alloc_should_filter_zonelist(struct zonelist *zonelist) +{ + return 0; +} +#endif /* CONFIG_NUMA */ + #ifdef CONFIG_ARCH_POPULATES_NODE_MAP struct node_active_region { unsigned long start_pfn; diff --git a/trunk/mm/mempolicy.c b/trunk/mm/mempolicy.c index 71b84b45154a..172abffeb2e3 100644 --- a/trunk/mm/mempolicy.c +++ b/trunk/mm/mempolicy.c @@ -149,7 +149,7 @@ static struct zonelist *bind_zonelist(nodemask_t *nodes) lower zones etc. Avoid empty zones because the memory allocator doesn't like them. If you implement node hot removal you have to fix that. */ - k = policy_zone; + k = MAX_NR_ZONES - 1; while (1) { for_each_node_mask(nd, *nodes) { struct zone *z = &NODE_DATA(nd)->node_zones[k]; diff --git a/trunk/mm/page_alloc.c b/trunk/mm/page_alloc.c index 3da85b81dabb..6427653023aa 100644 --- a/trunk/mm/page_alloc.c +++ b/trunk/mm/page_alloc.c @@ -1157,6 +1157,7 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, nodemask_t *allowednodes = NULL;/* zonelist_cache approximation */ int zlc_active = 0; /* set if using zonelist_cache */ int did_zlc_setup = 0; /* just call zlc_setup() one time */ + enum zone_type highest_zoneidx = -1; /* Gets set for policy zonelists */ zonelist_scan: /* @@ -1166,6 +1167,18 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, z = zonelist->zones; do { + /* + * In NUMA, this could be a policy zonelist which contains + * zones that may not be allowed by the current gfp_mask. + * Check the zone is allowed by the current flags + */ + if (unlikely(alloc_should_filter_zonelist(zonelist))) { + if (highest_zoneidx == -1) + highest_zoneidx = gfp_zone(gfp_mask); + if (zone_idx(*z) > highest_zoneidx) + continue; + } + if (NUMA_BUILD && zlc_active && !zlc_zone_worth_trying(zonelist, z, allowednodes)) continue;