• Vlastimil Babka's avatar
    mm, page_alloc: restructure direct compaction handling in slowpath · a8161d1e
    Vlastimil Babka authored
    The retry loop in __alloc_pages_slowpath is supposed to keep trying
    reclaim and compaction (and OOM), until either the allocation succeeds,
    or returns with failure.  Success here is more probable when reclaim
    precedes compaction, as certain watermarks have to be met for compaction
    to even try, and more free pages increase the probability of compaction
    success.  On the other hand, starting with light async compaction (if
    the watermarks allow it), can be more efficient, especially for smaller
    orders, if there's enough free memory which is just fragmented.
    
    Thus, the current code starts with compaction before reclaim, and to
    make sure that the last reclaim is always followed by a final
    compaction, there's another direct compaction call at the end of the
    loop.  This makes the code hard to follow and adds some duplicated
    handling of migration_mode decisions.  It's also somewhat inefficient
    that even if reclaim or compaction decides not to retry, the final
    compaction is still attempted.  Some gfp flags combination also shortcut
    these retry decisions by "goto noretry;", making it even harder to
    follow.
    
    This patch attempts to restructure the code with only minimal functional
    changes.  The call to the first compaction and THP-specific checks are
    now placed above the retry loop, and the "noretry" direct compaction is
    removed.
    
    The initial compaction is additionally restricted only to costly orders,
    as we can expect smaller orders to be held back by watermarks, and only
    larger orders to suffer primarily from fragmentation.  This better
    matches the checks in reclaim's shrink_zones().
    
    There are two other smaller functional changes.  One is that the upgrade
    from async migration to light sync migration will always occur after the
    initial compaction.  This is how it has been until recent patch "mm,
    oom: protect !costly allocations some more", which introduced upgrading
    the mode based on COMPACT_COMPLETE result, but kept the final compaction
    always upgraded, which made it even more special.  It's better to return
    to the simpler handling for now, as migration modes will be further
    modified later in the series.
    
    The second change is that once both reclaim and compaction declare it's
    not worth to retry the reclaim/compact loop, there is no final
    compaction attempt.  As argued above, this is intentional.  If that
    final compaction were to succeed, it would be due to a wrong retry
    decision, or simply a race with somebody else freeing memory for us.
    
    The main outcome of this patch should be simpler code.  Logically, the
    initial compaction without reclaim is the exceptional case to the
    reclaim/compaction scheme, but prior to the patch, it was the last loop
    iteration that was exceptional.  Now the code matches the logic better.
    The change also enable the following patches.
    
    Link: http://lkml.kernel.org/r/20160721073614.24395-5-vbabka@suse.czSigned-off-by: default avatarVlastimil Babka <vbabka@suse.cz>
    Acked-by: default avatarMichal Hocko <mhocko@suse.com>
    Acked-by: default avatarMel Gorman <mgorman@techsingularity.net>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    a8161d1e
page_alloc.c 205 KB