mm, compaction: more robust check for scanners meeting
[firefly-linux-kernel-4.4.55.git] / mm / compaction.c
index 018f08da99a2ece0aa25475c5f8f54bcc436f0eb..7077b81a4893710f415bd6d47976beefcff3b6b8 100644 (file)
@@ -897,6 +897,16 @@ static bool suitable_migration_target(struct page *page)
        return false;
 }
 
+/*
+ * Test whether the free scanner has reached the same or lower pageblock than
+ * the migration scanner, and compaction should thus terminate.
+ */
+static inline bool compact_scanners_met(struct compact_control *cc)
+{
+       return (cc->free_pfn >> pageblock_order)
+               <= (cc->migrate_pfn >> pageblock_order);
+}
+
 /*
  * Based on information in the current compact_control, find blocks
  * suitable for isolating free pages from and then isolate them.
@@ -1127,12 +1137,8 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,
        }
 
        acct_isolated(zone, cc);
-       /*
-        * Record where migration scanner will be restarted. If we end up in
-        * the same pageblock as the free scanner, make the scanners fully
-        * meet so that compact_finished() terminates compaction.
-        */
-       cc->migrate_pfn = (end_pfn <= cc->free_pfn) ? low_pfn : cc->free_pfn;
+       /* Record where migration scanner will be restarted. */
+       cc->migrate_pfn = low_pfn;
 
        return cc->nr_migratepages ? ISOLATE_SUCCESS : ISOLATE_NONE;
 }
@@ -1147,7 +1153,7 @@ static int __compact_finished(struct zone *zone, struct compact_control *cc,
                return COMPACT_PARTIAL;
 
        /* Compaction run completes if the migrate and free scanner meet */
-       if (cc->free_pfn <= cc->migrate_pfn) {
+       if (compact_scanners_met(cc)) {
                /* Let the next compaction start anew. */
                zone->compact_cached_migrate_pfn[0] = zone->zone_start_pfn;
                zone->compact_cached_migrate_pfn[1] = zone->zone_start_pfn;
@@ -1376,7 +1382,7 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
                         * migrate_pages() may return -ENOMEM when scanners meet
                         * and we want compact_finished() to detect it
                         */
-                       if (err == -ENOMEM && cc->free_pfn > cc->migrate_pfn) {
+                       if (err == -ENOMEM && !compact_scanners_met(cc)) {
                                ret = COMPACT_PARTIAL;
                                goto out;
                        }