tools headers UAPI: Sync files changed by new process_mrelease syscall and the remova...
[linux-2.6-microblaze.git] / mm / memory_hotplug.c
index 248e2ba..9fd0be3 100644 (file)
@@ -477,15 +477,13 @@ void __ref remove_pfn_range_from_zone(struct zone *zone,
                                 sizeof(struct page) * cur_nr_pages);
        }
 
-#ifdef CONFIG_ZONE_DEVICE
        /*
         * Zone shrinking code cannot properly deal with ZONE_DEVICE. So
         * we will not try to shrink the zones - which is okay as
         * set_zone_contiguous() cannot deal with ZONE_DEVICE either way.
         */
-       if (zone_idx(zone) == ZONE_DEVICE)
+       if (zone_is_zone_device(zone))
                return;
-#endif
 
        clear_zone_contiguous(zone);
 
@@ -752,11 +750,44 @@ static void auto_movable_stats_account_zone(struct auto_movable_stats *stats,
 #endif /* CONFIG_CMA */
        }
 }
+struct auto_movable_group_stats {
+       unsigned long movable_pages;
+       unsigned long req_kernel_early_pages;
+};
 
-static bool auto_movable_can_online_movable(int nid, unsigned long nr_pages)
+static int auto_movable_stats_account_group(struct memory_group *group,
+                                          void *arg)
+{
+       const int ratio = READ_ONCE(auto_movable_ratio);
+       struct auto_movable_group_stats *stats = arg;
+       long pages;
+
+       /*
+        * We don't support modifying the config while the auto-movable online
+        * policy is already enabled. Just avoid the division by zero below.
+        */
+       if (!ratio)
+               return 0;
+
+       /*
+        * Calculate how many early kernel pages this group requires to
+        * satisfy the configured zone ratio.
+        */
+       pages = group->present_movable_pages * 100 / ratio;
+       pages -= group->present_kernel_pages;
+
+       if (pages > 0)
+               stats->req_kernel_early_pages += pages;
+       stats->movable_pages += group->present_movable_pages;
+       return 0;
+}
+
+static bool auto_movable_can_online_movable(int nid, struct memory_group *group,
+                                           unsigned long nr_pages)
 {
-       struct auto_movable_stats stats = {};
        unsigned long kernel_early_pages, movable_pages;
+       struct auto_movable_group_stats group_stats = {};
+       struct auto_movable_stats stats = {};
        pg_data_t *pgdat = NODE_DATA(nid);
        struct zone *zone;
        int i;
@@ -777,6 +808,21 @@ static bool auto_movable_can_online_movable(int nid, unsigned long nr_pages)
        kernel_early_pages = stats.kernel_early_pages;
        movable_pages = stats.movable_pages;
 
+       /*
+        * Kernel memory inside dynamic memory group allows for more MOVABLE
+        * memory within the same group. Remove the effect of all but the
+        * current group from the stats.
+        */
+       walk_dynamic_memory_groups(nid, auto_movable_stats_account_group,
+                                  group, &group_stats);
+       if (kernel_early_pages <= group_stats.req_kernel_early_pages)
+               return false;
+       kernel_early_pages -= group_stats.req_kernel_early_pages;
+       movable_pages -= group_stats.movable_pages;
+
+       if (group && group->is_dynamic)
+               kernel_early_pages += group->present_kernel_pages;
+
        /*
         * Test if we could online the given number of pages to ZONE_MOVABLE
         * and still stay in the configured ratio.
@@ -834,6 +880,10 @@ static struct zone *default_kernel_zone_for_pfn(int nid, unsigned long start_pfn
  *    with unmovable allocations). While there are corner cases where it might
  *    still work, it is barely relevant in practice.
  *
+ * Exceptions are dynamic memory groups, which allow for more MOVABLE
+ * memory within the same memory group -- because in that case, there is
+ * coordination within the single memory device managed by a single driver.
+ *
  * We rely on "present pages" instead of "managed pages", as the latter is
  * highly unreliable and dynamic in virtualized environments, and does not
  * consider boot time allocations. For example, memory ballooning adjusts the
@@ -899,12 +949,12 @@ static struct zone *auto_movable_zone_for_pfn(int nid,
         * nobody interferes, all will be MOVABLE if possible.
         */
        nr_pages = max_pages - online_pages;
-       if (!auto_movable_can_online_movable(NUMA_NO_NODE, nr_pages))
+       if (!auto_movable_can_online_movable(NUMA_NO_NODE, group, nr_pages))
                goto kernel_zone;
 
 #ifdef CONFIG_NUMA
        if (auto_movable_numa_aware &&
-           !auto_movable_can_online_movable(nid, nr_pages))
+           !auto_movable_can_online_movable(nid, group, nr_pages))
                goto kernel_zone;
 #endif /* CONFIG_NUMA */
 
@@ -1720,7 +1770,7 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
                if (nodes_empty(nmask))
                        node_set(mtc.nid, nmask);
                ret = migrate_pages(&source, alloc_migration_target, NULL,
-                       (unsigned long)&mtc, MIGRATE_SYNC, MR_MEMORY_HOTPLUG);
+                       (unsigned long)&mtc, MIGRATE_SYNC, MR_MEMORY_HOTPLUG, NULL);
                if (ret) {
                        list_for_each_entry(page, &source, lru) {
                                if (__ratelimit(&migrate_rs)) {