@@ -1001,6 +1001,9 @@ struct zoneref *__next_zones_zonelist(struct zoneref *z,
enum zone_type highest_zoneidx,
nodemask_t *nodes);
+struct zonelist *preferred_zonelist(gfp_t gfp_mask, const nodemask_t *prefmask,
+ const nodemask_t *bindmask);
+
/**
* next_zones_zonelist - Returns the next zone at or below highest_zoneidx within the allowed nodemask using a cursor within a zonelist as a starting point
* @z - The cursor used as a starting point for the search
@@ -1995,7 +1995,6 @@ unsigned int mempolicy_slab_node(void)
return node;
switch (policy->mode) {
- case MPOL_PREFERRED_MANY:
case MPOL_PREFERRED:
/*
* handled MPOL_F_LOCAL above
@@ -2020,6 +2019,18 @@ unsigned int mempolicy_slab_node(void)
return z->zone ? zone_to_nid(z->zone) : node;
}
+ case MPOL_PREFERRED_MANY: {
+ struct zoneref *z;
+ struct zonelist *zonelist;
+ enum zone_type highest_zoneidx = gfp_zone(GFP_KERNEL);
+
+ zonelist = preferred_zonelist(GFP_KERNEL,
+ &policy->v.preferred_nodes, NULL);
+ z = first_zones_zonelist(zonelist, highest_zoneidx,
+ &policy->v.nodes);
+ return z->zone ? zone_to_nid(z->zone) : node;
+ }
+
default:
BUG();
}
@@ -2585,7 +2596,12 @@ int mpol_misplaced(struct page *page, struct vm_area_struct *vma, unsigned long
polnid = zone_to_nid(z->zone);
break;
- /* case MPOL_PREFERRED_MANY: */
+ case MPOL_PREFERRED_MANY:
+ z = first_zones_zonelist(preferred_zonelist(GFP_HIGHUSER,
+ &pol->v.preferred_nodes, NULL),
+ gfp_zone(GFP_HIGHUSER), &pol->v.preferred_nodes);
+ polnid = zone_to_nid(z->zone);
+ break;
default:
BUG();
@@ -4861,9 +4861,8 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
* NB: That zonelist will have *all* zones in the fallback case, and not all of
* those zones will belong to preferred nodes.
*/
-static struct zonelist *preferred_zonelist(gfp_t gfp_mask,
- const nodemask_t *prefmask,
- const nodemask_t *bindmask)
+struct zonelist *preferred_zonelist(gfp_t gfp_mask, const nodemask_t *prefmask,
+ const nodemask_t *bindmask)
{
nodemask_t pref;
int nid, local_node = numa_mem_id();
Now that there is a function to generate the preferred zonelist given a preferred mask, bindmask, and flags it is possible to support MPOL_PREFERRED_MANY policy easily in more places. This patch was developed on top of Dave's original work. When Dave wrote his patches there was no clean way to implement MPOL_PREFERRED_MANY. Now that the other bits are in place, this is easy to drop on top. Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Dan Williams <dan.j.williams@intel.com> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Mel Gorman <mgorman@techsingularity.net> Signed-off-by: Ben Widawsky <ben.widawsky@intel.com> --- include/linux/mmzone.h | 3 +++ mm/mempolicy.c | 20 ++++++++++++++++++-- mm/page_alloc.c | 5 ++--- 3 files changed, 23 insertions(+), 5 deletions(-)