Re: [PATCH v2 00/15] mm: memory hot(un)plug and SPARSEMEM cleanups
From: Andrew Morton
Date: Thu Mar 26 2026 - 22:58:26 EST
On Fri, 20 Mar 2026 23:13:32 +0100 "David Hildenbrand (Arm)" <david@xxxxxxxxxx> wrote:
> Some cleanups around memory hot(un)plug and SPARSEMEM. In essence,
> we can limit CONFIG_MEMORY_HOTPLUG to CONFIG_SPARSEMEM_VMEMMAP,
> remove some dead code, and move all the hotplug bits over to
> mm/sparse-vmemmap.c.
>
> Some further/related cleanups around other unnecessary code
> (memory hole handling and complicated usemap allocation).
Sorry, for some (age-related) reason I've been sitting on v1 for nearly
a week.
Thanks, I've updated mm-unstable to this version.
Lorenzo, I've assumed that your conditional R-b on [01/15] is now
unconditional.
> v1 -> v2:
> * Added "mm/memory_hotplug: fix possible race in scan_movable_pages()"
> * Update the comment above section_deactivate()
> * Reordered the flags in sparse_init_one_section()
> * Patch description improvements
Here's how v2 altered mm.git:
mm/internal.h | 2 +-
mm/memory_hotplug.c | 11 ++++++++---
mm/sparse-vmemmap.c | 8 ++------
3 files changed, 11 insertions(+), 10 deletions(-)
--- a/mm/internal.h~b
+++ a/mm/internal.h
@@ -985,7 +985,7 @@ static inline void sparse_init_one_secti
ms->section_mem_map &= ~SECTION_MAP_MASK;
ms->section_mem_map |= coded_mem_map;
- ms->section_mem_map |= SECTION_HAS_MEM_MAP | flags;
+ ms->section_mem_map |= flags | SECTION_HAS_MEM_MAP;
ms->usage = usage;
}
--- a/mm/memory_hotplug.c~b
+++ a/mm/memory_hotplug.c
@@ -1738,6 +1738,7 @@ static int scan_movable_pages(unsigned l
unsigned long pfn;
for (pfn = start; pfn < end; pfn++) {
+ unsigned long nr_pages;
struct page *page;
struct folio *folio;
@@ -1754,9 +1755,9 @@ static int scan_movable_pages(unsigned l
if (PageOffline(page) && page_count(page))
return -EBUSY;
- if (!PageHuge(page))
- continue;
folio = page_folio(page);
+ if (!folio_test_hugetlb(folio))
+ continue;
/*
* This test is racy as we hold no reference or lock. The
* hugetlb page could have been free'ed and head is no longer
@@ -1766,7 +1767,11 @@ static int scan_movable_pages(unsigned l
*/
if (folio_test_hugetlb_migratable(folio))
goto found;
- pfn |= folio_nr_pages(folio) - 1;
+ nr_pages = folio_nr_pages(folio);
+ if (unlikely(nr_pages < 1 || nr_pages > MAX_FOLIO_NR_PAGES ||
+ !is_power_of_2(nr_pages)))
+ continue;
+ pfn |= nr_pages - 1;
}
return -ENOENT;
found:
--- a/mm/sparse-vmemmap.c~b
+++ a/mm/sparse-vmemmap.c
@@ -725,11 +725,9 @@ static int fill_subsection_map(unsigned
}
/*
- * To deactivate a memory region, there are 3 cases to handle across
- * two configurations (SPARSEMEM_VMEMMAP={y,n}):
+ * To deactivate a memory region, there are 3 cases to handle:
*
- * 1. deactivation of a partial hot-added section (only possible in
- * the SPARSEMEM_VMEMMAP=y case).
+ * 1. deactivation of a partial hot-added section:
* a) section was present at memory init.
* b) section was hot-added post memory init.
* 2. deactivation of a complete hot-added section.
@@ -737,8 +735,6 @@ static int fill_subsection_map(unsigned
*
* For 1, when subsection_map does not empty we will not be freeing the
* usage map, but still need to free the vmemmap range.
- *
- * For 2 and 3, the SPARSEMEM_VMEMMAP={y,n} cases are unified
*/
static void section_deactivate(unsigned long pfn, unsigned long nr_pages,
struct vmem_altmap *altmap)
_