mm/demotion: update node_is_toptier to work with memory tiers
[linux-2.6-block.git] / mm / memory-tiers.c
index 45dd6fa4e2d169d2696ade491177804e9c01c94b..c82eb0111383bbb1d869ad7397d156cf017b0eb3 100644 (file)
@@ -37,6 +37,7 @@ static LIST_HEAD(memory_tiers);
 static struct node_memory_type_map node_memory_types[MAX_NUMNODES];
 static struct memory_dev_type *default_dram_type;
 #ifdef CONFIG_MIGRATION
+static int top_tier_adistance;
 /*
  * node_demotion[] examples:
  *
@@ -162,6 +163,31 @@ static struct memory_tier *__node_get_memory_tier(int node)
 }
 
 #ifdef CONFIG_MIGRATION
+bool node_is_toptier(int node)
+{
+       bool toptier;
+       pg_data_t *pgdat;
+       struct memory_tier *memtier;
+
+       pgdat = NODE_DATA(node);
+       if (!pgdat)
+               return false;
+
+       rcu_read_lock();
+       memtier = rcu_dereference(pgdat->memtier);
+       if (!memtier) {
+               toptier = true;
+               goto out;
+       }
+       if (memtier->adistance_start <= top_tier_adistance)
+               toptier = true;
+       else
+               toptier = false;
+out:
+       rcu_read_unlock();
+       return toptier;
+}
+
 void node_get_allowed_targets(pg_data_t *pgdat, nodemask_t *targets)
 {
        struct memory_tier *memtier;
@@ -319,6 +345,27 @@ static void establish_demotion_targets(void)
                        }
                } while (1);
        }
+       /*
+        * Promotion is allowed from a memory tier to higher
+        * memory tier only if the memory tier doesn't include
+        * compute. We want to skip promotion from a memory tier,
+        * if any node that is part of the memory tier have CPUs.
+        * Once we detect such a memory tier, we consider that tier
+        * as top tiper from which promotion is not allowed.
+        */
+       list_for_each_entry_reverse(memtier, &memory_tiers, list) {
+               tier_nodes = get_memtier_nodemask(memtier);
+               nodes_and(tier_nodes, node_states[N_CPU], tier_nodes);
+               if (!nodes_empty(tier_nodes)) {
+                       /*
+                        * abstract distance below the max value of this memtier
+                        * is considered toptier.
+                        */
+                       top_tier_adistance = memtier->adistance_start +
+                                               MEMTIER_CHUNK_SIZE - 1;
+                       break;
+               }
+       }
        /*
         * Now build the lower_tier mask for each node collecting node mask from
         * all memory tier below it. This allows us to fallback demotion page