• Johannes Weiner's avatar
    mm: compaction: fix endless looping over same migrate block · 493614da
    Johannes Weiner authored
    During stress testing, the following situation was observed:
    
         70 root      39  19       0      0      0 R 100.0   0.0 959:29.92 khugepaged
     310936 root      20   0   84416  25620    512 R  99.7   1.5 642:37.22 hugealloc
    
    Tracing shows isolate_migratepages_block() endlessly looping over the
    first block in the DMA zone:
    
           hugealloc-310936  [001] ..... 237297.415718: mm_compaction_finished: node=0 zone=DMA      order=9 ret=no_suitable_page
           hugealloc-310936  [001] ..... 237297.415718: mm_compaction_isolate_migratepages: range=(0x1 ~ 0x400) nr_scanned=513 nr_taken=0
           hugealloc-310936  [001] ..... 237297.415718: mm_compaction_finished: node=0 zone=DMA      order=9 ret=no_suitable_page
           hugealloc-310936  [001] ..... 237297.415718: mm_compaction_isolate_migratepages: range=(0x1 ~ 0x400) nr_scanned=513 nr_taken=0
           hugealloc-310936  [001] ..... 237297.415718: mm_compaction_finished: node=0 zone=DMA      order=9 ret=no_suitable_page
           hugealloc-310936  [001] ..... 237297.415718: mm_compaction_isolate_migratepages: range=(0x1 ~ 0x400) nr_scanned=513 nr_taken=0
           hugealloc-310936  [001] ..... 237297.415718: mm_compaction_finished: node=0 zone=DMA      order=9 ret=no_suitable_page
           hugealloc-310936  [001] ..... 237297.415718: mm_compaction_isolate_migratepages: range=(0x1 ~ 0x400) nr_scanned=513 nr_taken=0
    
    The problem is that the functions tries to test and set the skip bit once
    on the block, to avoid skipping on its own skip-set, using
    pageblock_aligned() on the pfn as a test.  But because this is the DMA
    zone which starts at pfn 1, this is never true for the first block, and
    the skip bit isn't set or tested at all.  As a result,
    fast_find_migrateblock() returns the same pageblock over and over.
    
    If the pfn isn't pageblock-aligned, also check if it's the start of the
    zone to ensure test-and-set-exactly-once on unaligned ranges.
    
    Thanks to Vlastimil Babka for the help in debugging this.
    
    Link: https://lkml.kernel.org/r/20230731172450.1632195-1-hannes@cmpxchg.org
    Fixes: 90ed667c ("Revert "Revert "mm/compaction: fix set skip in fast_find_migrateblock""")
    Signed-off-by: default avatarJohannes Weiner <hannes@cmpxchg.org>
    Reviewed-by: default avatarVlastimil Babka <vbabka@suse.cz>
    Acked-by: default avatarMel Gorman <mgorman@techsingularity.net>
    Reviewed-by: default avatarBaolin Wang <baolin.wang@linux.alibaba.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    493614da
compaction.c 87.9 KB