sparc does not select CONFIG_HAVE_BOOTMEM_INFO_NODE, therefore, register_page_bootmem_info_node() is a nop. Let's just get rid of register_page_bootmem_info(). Signed-off-by: David Hildenbrand (Arm) --- arch/sparc/mm/init_64.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 367c269305e5..3b679b1d1d72 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -2477,17 +2476,6 @@ int page_in_phys_avail(unsigned long paddr) return 0; } -static void __init register_page_bootmem_info(void) -{ -#ifdef CONFIG_NUMA - int i; - - for_each_online_node(i) - if (NODE_DATA(i)->node_spanned_pages) - register_page_bootmem_info_node(NODE_DATA(i)); -#endif -} - void __init arch_setup_zero_pages(void) { phys_addr_t zero_page_pa = kern_base + @@ -2498,14 +2486,6 @@ void __init arch_setup_zero_pages(void) void __init mem_init(void) { - /* - * Must be done after boot memory is put on freelist, because here we - * might set fields in deferred struct pages that have not yet been - * initialized, and memblock_free_all() initializes all the reserved - * deferred pages for us. - */ - register_page_bootmem_info(); - if (tlb_type == cheetah || tlb_type == cheetah_plus) cheetah_ecache_flush_init(); } -- 2.43.0 In the past, we used to store the type in page->lru.next, introduced by commit 5f24ce5fd34c ("thp: remove PG_buddy"). The location changed over the years; ever since commit 0386aaa6e9c8 ("bootmem: stop using page->index"), we store it alongside the info in page->private. Consequently, there is no need to reset page->lru anymore. Signed-off-by: David Hildenbrand (Arm) --- mm/bootmem_info.c | 1 - 1 file changed, 1 deletion(-) diff --git a/mm/bootmem_info.c b/mm/bootmem_info.c index 3d7675a3ae04..a0a1ecdec8d0 100644 --- a/mm/bootmem_info.c +++ b/mm/bootmem_info.c @@ -34,7 +34,6 @@ void put_page_bootmem(struct page *page) if (page_ref_dec_return(page) == 1) { ClearPagePrivate(page); set_page_private(page, 0); - INIT_LIST_HEAD(&page->lru); kmemleak_free_part_phys(PFN_PHYS(page_to_pfn(page)), PAGE_SIZE); free_reserved_page(page); } -- 2.43.0 Nobody checks PG_private for these pages, and we can happily use set_page_private() without setting PG_private. So let's just stop setting/clearing PG_private. Signed-off-by: David Hildenbrand (Arm) --- mm/bootmem_info.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/mm/bootmem_info.c b/mm/bootmem_info.c index a0a1ecdec8d0..6e2aaab3dca9 100644 --- a/mm/bootmem_info.c +++ b/mm/bootmem_info.c @@ -19,7 +19,6 @@ void get_page_bootmem(unsigned long info, struct page *page, { BUG_ON(type > 0xf); BUG_ON(info > (ULONG_MAX >> 4)); - SetPagePrivate(page); set_page_private(page, info << 4 | type); page_ref_inc(page); } @@ -32,7 +31,6 @@ void put_page_bootmem(struct page *page) type > MEMORY_HOTPLUG_MAX_BOOTMEM_TYPE); if (page_ref_dec_return(page) == 1) { - ClearPagePrivate(page); set_page_private(page, 0); kmemleak_free_part_phys(PFN_PHYS(page_to_pfn(page)), PAGE_SIZE); free_reserved_page(page); -- 2.43.0 The call to kmemleak_free_part_phys() was added in 2022 in commit dd0ff4d12dd2 ("bootmem: remove the vmemmap pages from kmemleak in put_page_bootmem"). In 2025, commit b2aad24b5333 ("mm/memmap: prevent double scanning of memmap by kmemleak") started to use MEMBLOCK_ALLOC_NOLEAKTRACE when allocating the memmap to skip the kmemleak_alloc_phys() in the buddy. So remove the call to kmemleak_free_part_phys(). If this would still be required for other purposes, either free_reserved_page() should take care of it, or selected users. Signed-off-by: David Hildenbrand (Arm) --- include/linux/bootmem_info.h | 1 - mm/bootmem_info.c | 1 - 2 files changed, 2 deletions(-) diff --git a/include/linux/bootmem_info.h b/include/linux/bootmem_info.h index 492ceeb1cdf8..f724340755e5 100644 --- a/include/linux/bootmem_info.h +++ b/include/linux/bootmem_info.h @@ -82,7 +82,6 @@ static inline void get_page_bootmem(unsigned long info, struct page *page, static inline void free_bootmem_page(struct page *page) { - kmemleak_free_part_phys(PFN_PHYS(page_to_pfn(page)), PAGE_SIZE); free_reserved_page(page); } #endif diff --git a/mm/bootmem_info.c b/mm/bootmem_info.c index 6e2aaab3dca9..74c1116626c8 100644 --- a/mm/bootmem_info.c +++ b/mm/bootmem_info.c @@ -32,7 +32,6 @@ void put_page_bootmem(struct page *page) if (page_ref_dec_return(page) == 1) { set_page_private(page, 0); - kmemleak_free_part_phys(PFN_PHYS(page_to_pfn(page)), PAGE_SIZE); free_reserved_page(page); } } -- 2.43.0 We removed the last user of NODE_INFO in commit 119c31caa59e ("mm/sparse: remove !CONFIG_SPARSEMEM_VMEMMAP leftovers for CONFIG_MEMORY_HOTPLUG"). But it really was never used it besides for safety-checks ever since it was introduced in commit 04753278769f ("memory hotplug: register section/node id to free"), where we had the comment: 5) The node information like pgdat has similar issues. But, this will be able to be solved too by this. (Not implemented yet, but, remembering node id in the pages.) Of course, that never happened, and we are not planning on freeing the node data (pgdat/pglist_data), during memory hotunplug. So let's just stop marking the pgdat as NODE_INFO. Signed-off-by: David Hildenbrand (Arm) --- mm/bootmem_info.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/mm/bootmem_info.c b/mm/bootmem_info.c index 74c1116626c8..cce1d560f094 100644 --- a/mm/bootmem_info.c +++ b/mm/bootmem_info.c @@ -62,15 +62,8 @@ static void __init register_page_bootmem_info_section(unsigned long start_pfn) void __init register_page_bootmem_info_node(struct pglist_data *pgdat) { - unsigned long i, pfn, end_pfn, nr_pages; + unsigned long pfn, end_pfn; int node = pgdat->node_id; - struct page *page; - - nr_pages = PAGE_ALIGN(sizeof(struct pglist_data)) >> PAGE_SHIFT; - page = virt_to_page(pgdat); - - for (i = 0; i < nr_pages; i++, page++) - get_page_bootmem(node, page, NODE_INFO); pfn = pgdat->node_start_pfn; end_pfn = pgdat_end_pfn(pgdat); -- 2.43.0 We never free the ms->usage data for boot memory sections (see section_deactivate()). And to identify whether ms->usage was allocated from memblock, we simply identify it by looking at PG_reserved. Consequently, there is no need to mark ms->usage as MIX_SECTION_INFO. Let's just stop doing that. Signed-off-by: David Hildenbrand (Arm) --- mm/bootmem_info.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/mm/bootmem_info.c b/mm/bootmem_info.c index cce1d560f094..0fa78db7fbc0 100644 --- a/mm/bootmem_info.c +++ b/mm/bootmem_info.c @@ -38,10 +38,8 @@ void put_page_bootmem(struct page *page) static void __init register_page_bootmem_info_section(unsigned long start_pfn) { - unsigned long mapsize, section_nr, i; + unsigned long section_nr; struct mem_section *ms; - struct mem_section_usage *usage; - struct page *page; start_pfn = SECTION_ALIGN_DOWN(start_pfn); section_nr = pfn_to_section_nr(start_pfn); @@ -50,14 +48,6 @@ static void __init register_page_bootmem_info_section(unsigned long start_pfn) if (!preinited_vmemmap_section(ms)) register_page_bootmem_memmap(section_nr, pfn_to_page(start_pfn), PAGES_PER_SECTION); - - usage = ms->usage; - page = virt_to_page(usage); - - mapsize = PAGE_ALIGN(mem_section_usage_size()) >> PAGE_SHIFT; - - for (i = 0; i < mapsize; i++, page++) - get_page_bootmem(section_nr, page, MIX_SECTION_INFO); } void __init register_page_bootmem_info_node(struct pglist_data *pgdat) -- 2.43.0 We never select CONFIG_HAVE_BOOTMEM_INFO_NODE on s390. Therefore, free_bootmem_page() nowadays always translates to free_reserved_page(). Let's use free_reserved_page() to replace the free_bootmem_page() loop. We can stop including bootmem_info.h. Likely, vmemmap freeing code could be factored out into the core in the future. Signed-off-by: David Hildenbrand (Arm) --- arch/s390/mm/vmem.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c index eeadff45e0e1..d8b2a60e0c33 100644 --- a/arch/s390/mm/vmem.c +++ b/arch/s390/mm/vmem.c @@ -4,7 +4,6 @@ */ #include -#include #include #include #include @@ -51,7 +50,7 @@ static void vmem_free_pages(unsigned long addr, int order, struct vmem_altmap *a if (PageReserved(page)) { /* allocated from memblock */ while (nr_pages--) - free_bootmem_page(page++); + free_reserved_page(page++); } else { free_pages(addr, order); } -- 2.43.0 register_page_bootmem_info_node() essentially only calls register_page_bootmem_memmap(). However, on powerpc that function is a nop. So there is not benefit in using CONFIG_HAVE_BOOTMEM_INFO_NODE anymore, let's just drop it. We can stop including bootmem_info.h. Signed-off-by: David Hildenbrand (Arm) --- arch/powerpc/mm/init_64.c | 8 -------- mm/Kconfig | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index b6f3ae03ca9e..64f0df5bb5cd 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include @@ -388,13 +387,6 @@ void __ref vmemmap_free(unsigned long start, unsigned long end, #endif -#ifdef CONFIG_HAVE_BOOTMEM_INFO_NODE -void register_page_bootmem_memmap(unsigned long section_nr, - struct page *start_page, unsigned long size) -{ -} -#endif /* CONFIG_HAVE_BOOTMEM_INFO_NODE */ - #endif /* CONFIG_SPARSEMEM_VMEMMAP */ #ifdef CONFIG_PPC_BOOK3S_64 diff --git a/mm/Kconfig b/mm/Kconfig index e221fa1dc54d..97b079372325 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -537,7 +537,7 @@ endchoice config MEMORY_HOTREMOVE bool "Allow for memory hot remove" - select HAVE_BOOTMEM_INFO_NODE if (X86_64 || PPC64) + select HAVE_BOOTMEM_INFO_NODE if X86_64 depends on MEMORY_HOTPLUG select MIGRATION -- 2.43.0