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
