From: Yuan Liu set_zone_contiguous() uses __pageblock_pfn_to_page() to detect pageblocks that either do not exist (hole) or that do not belong to the same zone. __pageblock_pfn_to_page(), however, relies on pfn_to_online_page(), effectively always returning NULL for memory ranges that were not onlined yet. So when called on a range-to-be-onlined, it indicates a memory hole to set_zone_contiguous(). Consequently, the set_zone_contiguous() call in move_pfn_range_to_zone(), which happens early during memory onlining, will never detect a zone as being contiguous. Bad. To fix the issue, move the set_zone_contiguous() call to a later stage in memory onlining, where pfn_to_online_page() will succeed: after we mark the memory sections to be online. Fixes: 2d070eab2e82 ("mm: consider zone which is not fully populated to have holes") Cc: Michal Hocko Reviewed-by: Nanhai Zou Signed-off-by: Yuan Liu Signed-off-by: Tianyou Li --- mm/memory_hotplug.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index a63ec679d861..c8f492b5daf0 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -782,8 +782,6 @@ void move_pfn_range_to_zone(struct zone *zone, unsigned long start_pfn, memmap_init_range(nr_pages, nid, zone_idx(zone), start_pfn, 0, MEMINIT_HOTPLUG, altmap, migratetype, isolate_pageblock); - - set_zone_contiguous(zone); } struct auto_movable_stats { @@ -1205,6 +1203,13 @@ int online_pages(unsigned long pfn, unsigned long nr_pages, } online_pages_range(pfn, nr_pages); + + /* + * Now that the ranges are indicated as online, check whether the whole + * zone is contiguous. + */ + set_zone_contiguous(zone); + adjust_present_page_count(pfn_to_page(pfn), group, nr_pages); if (node_arg.nid >= 0) -- 2.47.1