For PAGE_ALLOC_COSTLY_ORDER allocations, MIN_COMPACT_COSTLY_PRIORITY is
minimum (highest priority).  Other places in the compaction code key off
of MIN_COMPACT_PRIORITY.  Costly order allocations will never get to
MIN_COMPACT_PRIORITY.  Therefore, some conditions will never be met for
costly order allocations.

This was observed when hugetlb allocations could stall for minutes or
hours when should_compact_retry() would return true more often then it
should.  Specifically, this was in the case where compact_result was
COMPACT_DEFERRED and COMPACT_PARTIAL_SKIPPED and no progress was being
made.

Signed-off-by: Mike Kravetz <[email protected]>
---
 mm/compaction.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/mm/compaction.c b/mm/compaction.c
index 952dc2fb24e5..325b746068d1 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -2294,9 +2294,15 @@ static enum compact_result compact_zone_order(struct 
zone *zone, int order,
                .alloc_flags = alloc_flags,
                .classzone_idx = classzone_idx,
                .direct_compaction = true,
-               .whole_zone = (prio == MIN_COMPACT_PRIORITY),
-               .ignore_skip_hint = (prio == MIN_COMPACT_PRIORITY),
-               .ignore_block_suitable = (prio == MIN_COMPACT_PRIORITY)
+               .whole_zone = ((order > PAGE_ALLOC_COSTLY_ORDER) ?
+                               (prio == MIN_COMPACT_COSTLY_PRIORITY) :
+                               (prio == MIN_COMPACT_PRIORITY)),
+               .ignore_skip_hint = ((order > PAGE_ALLOC_COSTLY_ORDER) ?
+                               (prio == MIN_COMPACT_COSTLY_PRIORITY) :
+                               (prio == MIN_COMPACT_PRIORITY)),
+               .ignore_block_suitable = ((order > PAGE_ALLOC_COSTLY_ORDER) ?
+                               (prio == MIN_COMPACT_COSTLY_PRIORITY) :
+                               (prio == MIN_COMPACT_PRIORITY))
        };
        struct capture_control capc = {
                .cc = &cc,
@@ -2338,6 +2344,7 @@ enum compact_result try_to_compact_pages(gfp_t gfp_mask, 
unsigned int order,
        int may_perform_io = gfp_mask & __GFP_IO;
        struct zoneref *z;
        struct zone *zone;
+       int min_priority;
        enum compact_result rc = COMPACT_SKIPPED;
 
        /*
@@ -2350,12 +2357,13 @@ enum compact_result try_to_compact_pages(gfp_t 
gfp_mask, unsigned int order,
        trace_mm_compaction_try_to_compact_pages(order, gfp_mask, prio);
 
        /* Compact each zone in the list */
+       min_priority = (order > PAGE_ALLOC_COSTLY_ORDER) ?
+                       MIN_COMPACT_COSTLY_PRIORITY : MIN_COMPACT_PRIORITY;
        for_each_zone_zonelist_nodemask(zone, z, ac->zonelist, ac->high_zoneidx,
                                                                ac->nodemask) {
                enum compact_result status;
 
-               if (prio > MIN_COMPACT_PRIORITY
-                                       && compaction_deferred(zone, order)) {
+               if (prio > min_priority && compaction_deferred(zone, order)) {
                        rc = max_t(enum compact_result, COMPACT_DEFERRED, rc);
                        continue;
                }
-- 
2.20.1

Reply via email to