mm/hotplug: fix an imbalance with DEBUG_PAGEALLOC
authorQian Cai <>
Tue, 5 Mar 2019 23:49:57 +0000 (15:49 -0800)
committerLinus Torvalds <>
Wed, 6 Mar 2019 05:07:21 +0000 (21:07 -0800)
When onlining a memory block with DEBUG_PAGEALLOC, it unmaps the pages
in the block from kernel, However, it does not map those pages while
offlining at the beginning.  As the result, it triggers a panic below
while onlining on ppc64le as it checks if the pages are mapped before
unmapping.  However, the imbalance exists for all arches where
double-unmappings could happen.  Therefore, let kernel map those pages
in generic_online_page() before they have being freed into the page
allocator for the first time where it will set the page count to one.

On the other hand, it works fine during the boot, because at least for
IBM POWER8, it does,

      htab_initialize [1]
        htab_bolt_mapping [2]

where it effectively map all memblock regions just like
kernel_map_linear_page(), so later mem_init() -> memblock_free_all()
will unmap them just fine without any imbalance.  On other arches
without this imbalance checking, it still unmap them once at the most.

for_each_memblock(memory, reg) {
        base = (unsigned long)__va(reg->base);
        size = reg->size;

        DBG("creating mapping for region: %lx..%lx (prot: %lx)\n",
                base, size, prot);

        BUG_ON(htab_bolt_mapping(base, base + size, __pa(base),
                prot, mmu_linear_psize, mmu_kernel_ssize));

[2] linear_map_hash_slots[paddr >> PAGE_SHIFT] = ret | 0x80;
    kernel BUG at arch/powerpc/mm/hash_utils_64.c:1815!
    Oops: Exception in kernel mode, sig: 5 [#1]
    CPU: 2 PID: 4298 Comm: bash Not tainted 5.0.0-rc7+ #15
    NIP:  c000000000062670 LR: c00000000006265c CTR: 0000000000000000
    REGS: c0000005bf8a75b0 TRAP: 0700   Not tainted  (5.0.0-rc7+)
    MSR:  800000000282b033 <SF,VEC,VSX,EE,FP,ME,IR,DR,RI,LE>  CR: 28422842
    XER: 00000000
    CFAR: c000000000804f44 IRQMASK: 1
    NIP [c000000000062670] __kernel_map_pages+0x2e0/0x4f0
    LR [c00000000006265c] __kernel_map_pages+0x2cc/0x4f0
    Call Trace:

Signed-off-by: Qian Cai <>
Reviewed-by: Andrew Morton <>
Cc: Benjamin Herrenschmidt <>
Cc: Paul Mackerras <>
Cc: Michael Ellerman <> [powerpc]
Cc: Michal Hocko <>
Cc: Souptick Joarder <>
Signed-off-by: Andrew Morton <>
Signed-off-by: Linus Torvalds <>

index ebc8c1e75355d2c217cea30923b7e8ac4bb8d3d7..6b05576fb4ec10ebc9d1c75ec461d54b349db306 100644 (file)
@@ -658,6 +658,7 @@ EXPORT_SYMBOL_GPL(__online_page_free);
 static void generic_online_page(struct page *page, unsigned int order)
+       kernel_map_pages(page, 1 << order, 1);
        __free_pages_core(page, order);
        totalram_pages_add(1UL << order);