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 <[email protected]>
---
 include/linux/mmzone.h | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index ae0271eaec05..6f112e6f42bb 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -2028,6 +2028,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
@@ -2224,6 +2232,17 @@ static inline bool pfn_section_first_valid(struct 
mem_section *ms, unsigned long
        *pfn = (*pfn & PAGE_SECTION_MASK) + (bit * PAGES_PER_SUBSECTION);
        return true;
 }
+
+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 int pfn_section_valid(struct mem_section *ms, unsigned long pfn)
 {
@@ -2234,6 +2253,15 @@ static inline bool pfn_section_first_valid(struct 
mem_section *ms, unsigned long
 {
        return true;
 }
+
+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
 
 void sparse_init_early_section(int nid, struct page *map, unsigned long pnum,
-- 
2.54.0


Reply via email to