With MPOL_HYBRID the memory allocation may end up on non-DRAM node, this
may be not optimal for performance.  Promote pages to DRAM with NUMA
balancing for MPOL_HYBRID.

If DRAM nodes are specified, migrate to the specified nodes.  If no DRAM
node is specified, migrate to the local DRAM node.

Signed-off-by: Yang Shi <yang....@linux.alibaba.com>
---
 mm/mempolicy.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 7d0a432..87bc691 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -2339,6 +2339,7 @@ int mpol_misplaced(struct page *page, struct 
vm_area_struct *vma, unsigned long
        struct zoneref *z;
        int curnid = page_to_nid(page);
        unsigned long pgoff;
+       nodemask_t nmask;
        int thiscpu = raw_smp_processor_id();
        int thisnid = cpu_to_node(thiscpu);
        int polnid = NUMA_NO_NODE;
@@ -2363,7 +2364,24 @@ int mpol_misplaced(struct page *page, struct 
vm_area_struct *vma, unsigned long
                break;
 
        case MPOL_HYBRID:
-               /* Fall through */
+               if (node_isset(curnid, pol->v.nodes) &&
+                   node_isset(curnid, def_alloc_nodemask))
+                       /* The page is already on DRAM node */
+                       goto out;
+
+               /*
+                * Promote to the DRAM node specified by the policy, or
+                * the local DRAM node if no DRAM node is specified.
+                */
+               nodes_and(nmask, pol->v.nodes, def_alloc_nodemask);
+
+               z = first_zones_zonelist(
+                       node_zonelist(numa_node_id(), GFP_HIGHUSER),
+                       gfp_zone(GFP_HIGHUSER),
+                       nodes_empty(nmask) ? &def_alloc_nodemask : &nmask);
+               polnid = z->zone->node;
+
+               break;
 
        case MPOL_BIND:
 
-- 
1.8.3.1

Reply via email to