On Mon 26-09-16 18:20:24, Vlastimil Babka wrote:
> The compaction_zonelist_suitable() function tries to determine if compaction
> will be able to proceed after sufficient reclaim, i.e. whether there are
> enough reclaimable pages to provide enough order-0 freepages for compaction.
> 
> This addition of reclaimable pages to the free pages works well for the 
> order-0
> watermark check, but in the fragmentation index check we only consider truly
> free pages. Thus we can get fragindex value close to 0 which indicates failure
> do to lack of memory, and wrongly decide that compaction won't be suitable 
> even
> after reclaim.
> 
> Instead of trying to somehow adjust fragindex for reclaimable pages, let's 
> just
> skip it from compaction_zonelist_suitable().

Yes this makes a lot of sense to me. The fragidx should be mostly about
a balance between reclaim and the compaction so it shouldn't be used for
fail or retry decisions.

> 
> Signed-off-by: Vlastimil Babka <vba...@suse.cz>
> Cc: Michal Hocko <mho...@kernel.org>
> Cc: Mel Gorman <mgor...@techsingularity.net>
> Cc: Joonsoo Kim <iamjoonsoo....@lge.com>
> Cc: David Rientjes <rient...@google.com>
> Cc: Rik van Riel <r...@redhat.com>

Acked-by: Michal Hocko <mho...@suse.com>

> ---
>  mm/compaction.c | 35 ++++++++++++++++++-----------------
>  1 file changed, 18 insertions(+), 17 deletions(-)
> 
> diff --git a/mm/compaction.c b/mm/compaction.c
> index 86d4d0bbfc7c..5ff7f801c345 100644
> --- a/mm/compaction.c
> +++ b/mm/compaction.c
> @@ -1379,7 +1379,6 @@ static enum compact_result __compaction_suitable(struct 
> zone *zone, int order,
>                                       int classzone_idx,
>                                       unsigned long wmark_target)
>  {
> -     int fragindex;
>       unsigned long watermark;
>  
>       if (is_via_compact_memory(order))
> @@ -1415,6 +1414,18 @@ static enum compact_result 
> __compaction_suitable(struct zone *zone, int order,
>                                               ALLOC_CMA, wmark_target))
>               return COMPACT_SKIPPED;
>  
> +     return COMPACT_CONTINUE;
> +}
> +
> +enum compact_result compaction_suitable(struct zone *zone, int order,
> +                                     unsigned int alloc_flags,
> +                                     int classzone_idx)
> +{
> +     enum compact_result ret;
> +     int fragindex;
> +
> +     ret = __compaction_suitable(zone, order, alloc_flags, classzone_idx,
> +                                 zone_page_state(zone, NR_FREE_PAGES));
>       /*
>        * fragmentation index determines if allocation failures are due to
>        * low memory or external fragmentation
> @@ -1426,21 +1437,12 @@ static enum compact_result 
> __compaction_suitable(struct zone *zone, int order,
>        *
>        * Only compact if a failure would be due to fragmentation.
>        */
> -     fragindex = fragmentation_index(zone, order);
> -     if (fragindex >= 0 && fragindex <= sysctl_extfrag_threshold)
> -             return COMPACT_NOT_SUITABLE_ZONE;
> -
> -     return COMPACT_CONTINUE;
> -}
> -
> -enum compact_result compaction_suitable(struct zone *zone, int order,
> -                                     unsigned int alloc_flags,
> -                                     int classzone_idx)
> -{
> -     enum compact_result ret;
> +     if (ret == COMPACT_CONTINUE) {
> +             fragindex = fragmentation_index(zone, order);
> +             if (fragindex >= 0 && fragindex <= sysctl_extfrag_threshold)
> +                     return COMPACT_NOT_SUITABLE_ZONE;
> +     }
>  
> -     ret = __compaction_suitable(zone, order, alloc_flags, classzone_idx,
> -                                 zone_page_state(zone, NR_FREE_PAGES));
>       trace_mm_compaction_suitable(zone, order, ret);
>       if (ret == COMPACT_NOT_SUITABLE_ZONE)
>               ret = COMPACT_SKIPPED;
> @@ -1473,8 +1475,7 @@ bool compaction_zonelist_suitable(struct alloc_context 
> *ac, int order,
>               available += zone_page_state_snapshot(zone, NR_FREE_PAGES);
>               compact_result = __compaction_suitable(zone, order, alloc_flags,
>                               ac_classzone_idx(ac), available);
> -             if (compact_result != COMPACT_SKIPPED &&
> -                             compact_result != COMPACT_NOT_SUITABLE_ZONE)
> +             if (compact_result != COMPACT_SKIPPED)
>                       return true;
>       }
>  
> -- 
> 2.10.0

-- 
Michal Hocko
SUSE Labs

Reply via email to