linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] mm: Fix memblock_free_late() when using deferred struct page
@ 2026-02-03  8:02 Benjamin Herrenschmidt
  2026-02-03 18:40 ` Mike Rapoport
  2026-02-17  8:28 ` [PATCH v2] " Benjamin Herrenschmidt
  0 siblings, 2 replies; 33+ messages in thread
From: Benjamin Herrenschmidt @ 2026-02-03  8:02 UTC (permalink / raw)
  To: linux-mm; +Cc: Mike Rapoport

Currently, when using deferred struct page init, we may end up not
freeing the pages depending on where they are. Typically this happens
when efi_free_boot_services() tries to free UEFI Boot Services pages.

We can hit the !early_page_initialised() test in memblock_free_pages()
since the deferred initializer hasn't even started yet. As a result we
drop the pages on the floor.

Now, memblock_free_late() should only ever be called for pages that
are reserved, and thus for which the struct page has already been
initialized by memmap_init_reserved_pages().

So it should be safe to just free them normally and ignore the deferred
initializer, which will skip over them as it skips over anything still
in the memblock reserved list.

This recovers something like 130MB of RAM on EC2 t3a.nano instances who
only have 512MB to begin with (as to why UEFI uses that much, that's a
question for another day).

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 mm/internal.h | 2 +-
 mm/memblock.c | 6 ++++--
 mm/mm_init.c  | 4 ++--
 3 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/mm/internal.h b/mm/internal.h
index 9e0577413087c..fe6da7c30caf0 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -660,7 +660,7 @@ extern int __isolate_free_page(struct page *page,
unsigned int order);
 extern void __putback_isolated_page(struct page *page, unsigned int
order,
 				    int mt);
 extern void memblock_free_pages(struct page *page, unsigned long pfn,
-					unsigned int order);
+				unsigned int order, bool reserved);
 extern void __free_pages_core(struct page *page, unsigned int order,
 		enum meminit_context context);
 
diff --git a/mm/memblock.c b/mm/memblock.c
index 3d7b0114442c4..b836b638615d0 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -1718,8 +1718,10 @@ void __init memblock_free_late(phys_addr_t base,
phys_addr_t size)
 	cursor = PFN_UP(base);
 	end = PFN_DOWN(base + size);
 
+	/* Only free pages that were reserved */
+	VM_WARN_ON(!memblock_is_region_reserved(base, size));
 	for (; cursor < end; cursor++) {
-		memblock_free_pages(pfn_to_page(cursor), cursor, 0);
+		memblock_free_pages(pfn_to_page(cursor), cursor, 0,
true);
 		totalram_pages_inc();
 	}
 }
@@ -2141,7 +2143,7 @@ static void __init __free_pages_memory(unsigned
long start, unsigned long end)
 		while (start + (1UL << order) > end)
 			order--;
 
-		memblock_free_pages(pfn_to_page(start), start, order);
+		memblock_free_pages(pfn_to_page(start), start, order,
false);
 
 		start += (1UL << order);
 	}
diff --git a/mm/mm_init.c b/mm/mm_init.c
index 624c1f90ce050..34dc39a21b4bb 100644
--- a/mm/mm_init.c
+++ b/mm/mm_init.c
@@ -2440,9 +2440,9 @@ void *__init alloc_large_system_hash(const char
*tablename,
 }
 
 void __init memblock_free_pages(struct page *page, unsigned long pfn,
-							unsigned int
order)
+				unsigned int order, bool reserved)
 {
-	if (IS_ENABLED(CONFIG_DEFERRED_STRUCT_PAGE_INIT)) {
+	if (IS_ENABLED(CONFIG_DEFERRED_STRUCT_PAGE_INIT) && !reserved)
{
 		int nid = early_pfn_to_nid(pfn);
 
 		if (!early_page_initialised(pfn, nid))
-- 
2.43.0




^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2026-02-20  9:09 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-02-03  8:02 [PATCH] mm: Fix memblock_free_late() when using deferred struct page Benjamin Herrenschmidt
2026-02-03 18:40 ` Mike Rapoport
2026-02-03 19:53   ` Benjamin Herrenschmidt
2026-02-04  7:39     ` Mike Rapoport
2026-02-04  9:02       ` Benjamin Herrenschmidt
2026-02-06 10:33         ` Mike Rapoport
2026-02-10  1:04           ` Benjamin Herrenschmidt
2026-02-10  2:10             ` Benjamin Herrenschmidt
2026-02-10  6:17               ` Benjamin Herrenschmidt
2026-02-10  8:34                 ` Benjamin Herrenschmidt
2026-02-10 14:32                   ` Mike Rapoport
2026-02-10 23:23                     ` Benjamin Herrenschmidt
2026-02-11  5:20                       ` Mike Rapoport
2026-02-16  5:34                       ` Benjamin Herrenschmidt
2026-02-16  6:51                         ` Benjamin Herrenschmidt
2026-02-16  4:53                     ` Benjamin Herrenschmidt
2026-02-16 15:28                       ` Mike Rapoport
2026-02-16 10:36           ` Alexander Potapenko
2026-02-17  8:28 ` [PATCH v2] " Benjamin Herrenschmidt
2026-02-17 12:32   ` Mike Rapoport
2026-02-17 22:00     ` Benjamin Herrenschmidt
2026-02-17 21:47   ` Benjamin Herrenschmidt
2026-02-18  0:15     ` Benjamin Herrenschmidt
2026-02-18  8:05       ` Mike Rapoport
2026-02-19  2:48         ` Benjamin Herrenschmidt
2026-02-19 10:16           ` Mike Rapoport
2026-02-19 22:46             ` Benjamin Herrenschmidt
2026-02-20  4:57               ` Benjamin Herrenschmidt
2026-02-20  9:09                 ` Mike Rapoport
2026-02-20  9:00               ` Mike Rapoport
2026-02-20  5:12             ` Benjamin Herrenschmidt
2026-02-20  5:15             ` Benjamin Herrenschmidt
2026-02-20  5:47             ` Benjamin Herrenschmidt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox