]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - mm/compaction.c
mm, compaction: finish whole pageblock to reduce fragmentation
[mirror_ubuntu-bionic-kernel.git] / mm / compaction.c
index 206847d359786024d0054598389f05501d419aca..613c59e928cb5b07075c197126e01b9cdafff992 100644 (file)
@@ -1318,6 +1318,17 @@ static enum compact_result __compact_finished(struct zone *zone,
        if (is_via_compact_memory(cc->order))
                return COMPACT_CONTINUE;
 
+       if (cc->finishing_block) {
+               /*
+                * We have finished the pageblock, but better check again that
+                * we really succeeded.
+                */
+               if (IS_ALIGNED(cc->migrate_pfn, pageblock_nr_pages))
+                       cc->finishing_block = false;
+               else
+                       return COMPACT_CONTINUE;
+       }
+
        /* Direct compactor: Is a suitable page free? */
        for (order = cc->order; order < MAX_ORDER; order++) {
                struct free_area *area = &zone->free_area[order];
@@ -1338,8 +1349,29 @@ static enum compact_result __compact_finished(struct zone *zone,
                 * other migratetype buddy lists.
                 */
                if (find_suitable_fallback(area, order, migratetype,
-                                               true, &can_steal) != -1)
-                       return COMPACT_SUCCESS;
+                                               true, &can_steal) != -1) {
+
+                       /* movable pages are OK in any pageblock */
+                       if (migratetype == MIGRATE_MOVABLE)
+                               return COMPACT_SUCCESS;
+
+                       /*
+                        * We are stealing for a non-movable allocation. Make
+                        * sure we finish compacting the current pageblock
+                        * first so it is as free as possible and we won't
+                        * have to steal another one soon. This only applies
+                        * to sync compaction, as async compaction operates
+                        * on pageblocks of the same migratetype.
+                        */
+                       if (cc->mode == MIGRATE_ASYNC ||
+                                       IS_ALIGNED(cc->migrate_pfn,
+                                                       pageblock_nr_pages)) {
+                               return COMPACT_SUCCESS;
+                       }
+
+                       cc->finishing_block = true;
+                       return COMPACT_CONTINUE;
+               }
        }
 
        return COMPACT_NO_SUITABLE_PAGE;