Several struct page fields have the same initial values for every page in a zone. __init_single_page() initializes this state as part of its per-page setup, while the shared vmemmap tail path open-codes only a subset. Factor the PFN-independent state into memmap_init_page_common() and use it for both regular and shared tail struct pages. Keep section-, PFN- and instance-specific initialization in __init_single_page(). This also initializes the last cpupid and KASAN tag for shared tail struct pages consistently with regular struct pages. Signed-off-by: Muchun Song --- include/linux/mm.h | 8 -------- mm/mm_init.c | 23 ++++++++++++++++++----- mm/mm_init.h | 2 ++ mm/sparse-vmemmap.c | 7 +------ 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 77b5d450fe45..2e182498898e 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -3022,14 +3022,6 @@ static inline void set_page_node(struct page *page, unsigned long node) page->flags.f |= (node & NODES_MASK) << NODES_PGSHIFT; } -static inline void set_page_links(struct page *page, enum zone_type zone, - unsigned long node, unsigned long pfn) -{ - set_page_zone(page, zone); - set_page_node(page, node); - set_page_section_from_pfn(page, pfn); -} - /** * folio_nr_pages - The number of pages in the folio. * @folio: The folio. diff --git a/mm/mm_init.c b/mm/mm_init.c index 0129152b74d8..9677698f30d3 100644 --- a/mm/mm_init.c +++ b/mm/mm_init.c @@ -602,15 +602,28 @@ static inline void vmemmap_optimization_verify_zone(struct page *page) page_zone_id(page)); } -void __meminit __init_single_page(struct page *page, unsigned long pfn, - unsigned long zone, int nid) +/* Initialize PFN-independent fields common to pages in the same zone. */ +void __meminit memmap_init_page_common(struct page *page, + enum zone_type zone, int nid) { mm_zero_struct_page(page); - set_page_links(page, zone, nid, pfn); - init_page_count(page); - atomic_set(&page->_mapcount, -1); + set_page_zone(page, zone); + set_page_node(page, nid); page_cpupid_reset_last(page); page_kasan_tag_reset(page); + atomic_set(&page->_mapcount, -1); +#ifdef CONFIG_ZONE_DEVICE + if (zone == ZONE_DEVICE) + __SetPageReserved(page); +#endif +} + +void __meminit __init_single_page(struct page *page, unsigned long pfn, + unsigned long zone, int nid) +{ + memmap_init_page_common(page, zone, nid); + set_page_section_from_pfn(page, pfn); + init_page_count(page); INIT_LIST_HEAD(&page->lru); #ifdef WANT_PAGE_VIRTUAL diff --git a/mm/mm_init.h b/mm/mm_init.h index 0034e37dbabd..0df0644c703c 100644 --- a/mm/mm_init.h +++ b/mm/mm_init.h @@ -109,6 +109,8 @@ extern bool mirrored_kernelcore; bool memblock_has_mirror(void); void memblock_free_all(void); +void __meminit memmap_init_page_common(struct page *page, enum zone_type zone, + int nid); void __meminit __init_single_page(struct page *page, unsigned long pfn, unsigned long zone, int nid); diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c index 9b80dd7326f7..fd869617423a 100644 --- a/mm/sparse-vmemmap.c +++ b/mm/sparse-vmemmap.c @@ -212,12 +212,7 @@ struct page __ref *vmemmap_shared_tail_page(unsigned int order, struct zone *zon for (int i = 0; i < PAGE_SIZE / sizeof(struct page); i++) { page = (struct page *)addr + i; - mm_zero_struct_page(page); - atomic_set(&page->_mapcount, -1); - set_page_node(page, zone_to_nid(zone)); - set_page_zone(page, zone_idx(zone)); - if (zone_is_zone_device(zone)) - __SetPageReserved(page); + memmap_init_page_common(page, zone_idx(zone), zone_to_nid(zone)); prep_compound_tail(page, NULL, order); } -- 2.54.0