[PATCH 02/17] mm/sparse-vmemmap: track compound page order in struct mem_section
From: Muchun Song
Date: Thu Jul 02 2026 - 05:57:17 EST
HugeTLB and DAX both rely on vmemmap optimization, but sparsemem does
not record what compound page order a section is populated with.
As a result, code that needs this information has to open-code
separate handling across users of vmemmap optimization. It also
prevents other memory management code, such as struct page
initialization, from skipping initialization of shared vmemmap pages
when needed.
Track the compound page order in struct mem_section and provide small
helpers to access it. A compound page larger than a section naturally
carries the same order across all covered sections.
This is a preparatory change for consolidating vmemmap optimization
handling and for letting later code make initialization decisions
based on the section's compound page order.
Signed-off-by: Muchun Song <songmuchun@xxxxxxxxxxxxx>
---
include/linux/mmzone.h | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 1353bcf7b712..bacd89572c5c 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -2015,6 +2015,14 @@ struct mem_section {
*/
struct page_ext *page_ext;
#endif
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+ /*
+ * The order of compound pages in this section. Typically, the section
+ * holds compound pages of this order; a larger compound page will span
+ * multiple sections.
+ */
+ unsigned int order;
+#endif
};
#ifdef CONFIG_SPARSEMEM_EXTREME
@@ -2361,10 +2369,34 @@ static inline unsigned long next_present_section_nr(unsigned long section_nr)
#endif
#else
+struct mem_section;
+
#define sparse_vmemmap_init_nid_early(_nid) do {} while (0)
#define pfn_in_present_section pfn_valid
#endif /* CONFIG_SPARSEMEM */
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+static inline void section_set_order(struct mem_section *section, unsigned int order)
+{
+ VM_WARN_ON(section->order && order && section->order != order);
+ section->order = order;
+}
+
+static inline unsigned int section_order(const struct mem_section *section)
+{
+ return section->order;
+}
+#else
+static inline void section_set_order(struct mem_section *section, unsigned int order)
+{
+}
+
+static inline unsigned int section_order(const struct mem_section *section)
+{
+ return 0;
+}
+#endif
+
/*
* Fallback case for when the architecture provides its own pfn_valid() but
* not a corresponding for_each_valid_pfn().
--
2.54.0