The patch titled Subject: mm/page_alloc: skip non present sections on zone initialization has been added to the -mm tree. Its filename is mm-page_alloc-skip-non-present-sections-on-zone-initialization.patch This patch should soon appear at http://ozlabs.org/~akpm/mmots/broken-out/mm-page_alloc-skip-non-present-sections-on-zone-initialization.patch and later at http://ozlabs.org/~akpm/mmotm/broken-out/mm-page_alloc-skip-non-present-sections-on-zone-initialization.patch Before you just go and hit "reply", please: a) Consider who else should be cc'ed b) Prefer to cc a suitable mailing list as well c) Ideally: find the original patch on the mailing list and do a reply-to-all to that, adding suitable additional cc's *** Remember to use Documentation/process/submit-checklist.rst when testing your code *** The -mm tree is included into linux-next and is updated there every 3-4 working days ------------------------------------------------------ From: "Kirill A. Shutemov" <kirill@xxxxxxxxxxxxx> Subject: mm/page_alloc: skip non present sections on zone initialization memmap_init_zone() can be called on the ranges with holes during the boot. It will skip any non-valid PFNs one-by-one. It works fine as long as holes are not too big. But huge holes in the memory map causes a problem. It takes over 20 seconds to walk 32TiB hole. x86-64 with 5-level paging allows for much larger holes in the memory map which would practically hang the system. Deferred struct page init doesn't help here. It only works on the present ranges. Skipping non-present sections would fix the issue. Link: http://lkml.kernel.org/r/20191230093828.24613-1-kirill.shutemov@xxxxxxxxxxxxxxx Signed-off-by: Kirill A. Shutemov <kirill.shutemov@xxxxxxxxxxxxxxx> Reviewed-by: Baoquan He <bhe@xxxxxxxxxx> Cc: Dan Williams <dan.j.williams@xxxxxxxxx> Cc: Michal Hocko <mhocko@xxxxxxxx> Cc: Vlastimil Babka <vbabka@xxxxxxx> Cc: Mel Gorman <mgorman@xxxxxxx> Cc: "Jin, Zhi" <zhi.jin@xxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- mm/page_alloc.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) --- a/mm/page_alloc.c~mm-page_alloc-skip-non-present-sections-on-zone-initialization +++ a/mm/page_alloc.c @@ -5847,6 +5847,30 @@ overlap_memmap_init(unsigned long zone, return false; } +#ifdef CONFIG_SPARSEMEM +/* Skip PFNs that belong to non-present sections */ +static inline __meminit unsigned long next_pfn(unsigned long pfn) +{ + unsigned long section_nr; + + section_nr = pfn_to_section_nr(++pfn); + if (present_section_nr(section_nr)) + return pfn; + + while (++section_nr <= __highest_present_section_nr) { + if (present_section_nr(section_nr)) + return section_nr_to_pfn(section_nr); + } + + return -1; +} +#else +static inline __meminit unsigned long next_pfn(unsigned long pfn) +{ + return pfn++; +} +#endif + /* * Initially all pages are reserved - free ones are freed * up by memblock_free_all() once the early boot process is @@ -5886,8 +5910,10 @@ void __meminit memmap_init_zone(unsigned * function. They do not exist on hotplugged memory. */ if (context == MEMMAP_EARLY) { - if (!early_pfn_valid(pfn)) + if (!early_pfn_valid(pfn)) { + pfn = next_pfn(pfn) - 1; continue; + } if (!early_pfn_in_nid(pfn, nid)) continue; if (overlap_memmap_init(zone, &pfn)) _ Patches currently in -mm which might be from kirill@xxxxxxxxxxxxx are thp-fix-conflict-of-above-47bit-hint-address-and-pmd-alignment.patch thp-shmem-fix-conflict-of-above-47bit-hint-address-and-pmd-alignment.patch thp-shmem-fix-conflict-of-above-47bit-hint-address-and-pmd-alignment-fix.patch mm-page_alloc-skip-non-present-sections-on-zone-initialization.patch