mm/migrate: correct failure handling if !hugepage_migration_support()
[platform/adaptation/renesas_rcar/renesas_kernel.git] / mm / migrate.c
index 9194375..13bedcc 100644 (file)
@@ -199,7 +199,12 @@ out:
  */
 static void remove_migration_ptes(struct page *old, struct page *new)
 {
-       rmap_walk(new, remove_migration_pte, old);
+       struct rmap_walk_control rwc = {
+               .rmap_one = remove_migration_pte,
+               .arg = old,
+       };
+
+       rmap_walk(new, &rwc);
 }
 
 /*
@@ -1008,7 +1013,7 @@ static int unmap_and_move_huge_page(new_page_t get_new_page,
 {
        int rc = 0;
        int *result = NULL;
-       struct page *new_hpage = get_new_page(hpage, private, &result);
+       struct page *new_hpage;
        struct anon_vma *anon_vma = NULL;
 
        /*
@@ -1018,9 +1023,12 @@ static int unmap_and_move_huge_page(new_page_t get_new_page,
         * tables or check whether the hugepage is pmd-based or not before
         * kicking migration.
         */
-       if (!hugepage_migration_support(page_hstate(hpage)))
+       if (!hugepage_migration_support(page_hstate(hpage))) {
+               putback_active_hugepage(hpage);
                return -ENOSYS;
+       }
 
+       new_hpage = get_new_page(hpage, private, &result);
        if (!new_hpage)
                return -ENOMEM;
 
@@ -1120,7 +1128,12 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page,
                                nr_succeeded++;
                                break;
                        default:
-                               /* Permanent failure */
+                               /*
+                                * Permanent failure (-EBUSY, -ENOSYS, etc.):
+                                * unlike -EAGAIN case, the failed page is
+                                * removed from migration page list and not
+                                * retried in the next outer loop.
+                                */
                                nr_failed++;
                                break;
                        }
@@ -1594,31 +1607,38 @@ bool migrate_ratelimited(int node)
 }
 
 /* Returns true if the node is migrate rate-limited after the update */
-bool numamigrate_update_ratelimit(pg_data_t *pgdat, unsigned long nr_pages)
+static bool numamigrate_update_ratelimit(pg_data_t *pgdat,
+                                       unsigned long nr_pages)
 {
-       bool rate_limited = false;
-
        /*
         * Rate-limit the amount of data that is being migrated to a node.
         * Optimal placement is no good if the memory bus is saturated and
         * all the time is being spent migrating!
         */
-       spin_lock(&pgdat->numabalancing_migrate_lock);
        if (time_after(jiffies, pgdat->numabalancing_migrate_next_window)) {
+               spin_lock(&pgdat->numabalancing_migrate_lock);
                pgdat->numabalancing_migrate_nr_pages = 0;
                pgdat->numabalancing_migrate_next_window = jiffies +
                        msecs_to_jiffies(migrate_interval_millisecs);
+               spin_unlock(&pgdat->numabalancing_migrate_lock);
        }
-       if (pgdat->numabalancing_migrate_nr_pages > ratelimit_pages)
-               rate_limited = true;
-       else
-               pgdat->numabalancing_migrate_nr_pages += nr_pages;
-       spin_unlock(&pgdat->numabalancing_migrate_lock);
-       
-       return rate_limited;
+       if (pgdat->numabalancing_migrate_nr_pages > ratelimit_pages) {
+               trace_mm_numa_migrate_ratelimit(current, pgdat->node_id,
+                                                               nr_pages);
+               return true;
+       }
+
+       /*
+        * This is an unlocked non-atomic update so errors are possible.
+        * The consequences are failing to migrate when we potentiall should
+        * have which is not severe enough to warrant locking. If it is ever
+        * a problem, it can be converted to a per-cpu counter.
+        */
+       pgdat->numabalancing_migrate_nr_pages += nr_pages;
+       return false;
 }
 
-int numamigrate_isolate_page(pg_data_t *pgdat, struct page *page)
+static int numamigrate_isolate_page(pg_data_t *pgdat, struct page *page)
 {
        int page_lru;