]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - mm/compaction.c
mm, compaction: defer each zone individually instead of preferred zone
[mirror_ubuntu-jammy-kernel.git] / mm / compaction.c
index 21bf292b642a6c67fcf953a631ba0bb4534a0215..1c7195d42e837df8af55e12f35c17a1b893f2fd3 100644 (file)
@@ -1125,27 +1125,26 @@ int sysctl_extfrag_threshold = 500;
  * @nodemask: The allowed nodes to allocate from
  * @mode: The migration mode for async, sync light, or sync migration
  * @contended: Return value that is true if compaction was aborted due to lock contention
- * @page: Optionally capture a free page of the requested order during compaction
+ * @candidate_zone: Return the zone where we think allocation should succeed
  *
  * This is the main entry point for direct page compaction.
  */
 unsigned long try_to_compact_pages(struct zonelist *zonelist,
                        int order, gfp_t gfp_mask, nodemask_t *nodemask,
-                       enum migrate_mode mode, bool *contended)
+                       enum migrate_mode mode, bool *contended,
+                       struct zone **candidate_zone)
 {
        enum zone_type high_zoneidx = gfp_zone(gfp_mask);
        int may_enter_fs = gfp_mask & __GFP_FS;
        int may_perform_io = gfp_mask & __GFP_IO;
        struct zoneref *z;
        struct zone *zone;
-       int rc = COMPACT_SKIPPED;
+       int rc = COMPACT_DEFERRED;
        int alloc_flags = 0;
 
        /* Check if the GFP flags allow compaction */
        if (!order || !may_enter_fs || !may_perform_io)
-               return rc;
-
-       count_compact_event(COMPACTSTALL);
+               return COMPACT_SKIPPED;
 
 #ifdef CONFIG_CMA
        if (allocflags_to_migratetype(gfp_mask) == MIGRATE_MOVABLE)
@@ -1156,14 +1155,33 @@ unsigned long try_to_compact_pages(struct zonelist *zonelist,
                                                                nodemask) {
                int status;
 
+               if (compaction_deferred(zone, order))
+                       continue;
+
                status = compact_zone_order(zone, order, gfp_mask, mode,
                                                contended);
                rc = max(status, rc);
 
                /* If a normal allocation would succeed, stop compacting */
                if (zone_watermark_ok(zone, order, low_wmark_pages(zone), 0,
-                                     alloc_flags))
+                                     alloc_flags)) {
+                       *candidate_zone = zone;
+                       /*
+                        * We think the allocation will succeed in this zone,
+                        * but it is not certain, hence the false. The caller
+                        * will repeat this with true if allocation indeed
+                        * succeeds in this zone.
+                        */
+                       compaction_defer_reset(zone, order, false);
                        break;
+               } else if (mode != MIGRATE_ASYNC) {
+                       /*
+                        * We think that allocation won't succeed in this zone
+                        * so we defer compaction there. If it ends up
+                        * succeeding after all, it will be reset.
+                        */
+                       defer_compaction(zone, order);
+               }
        }
 
        return rc;