When a pgmap @align is set, all pages are mapped at a given huge page alignment and thus uses compound pages to describe them as opposed to a struct per 4K. With @align > PAGE_SIZE and when struct pages are stored in ram (!altmap) most tail pages are reused. Consequently, the amount of unique struct pages is a lot smaller that the total amount of struct pages being mapped. When struct pages are initialize in memmap_init_zone_device, make sure that only unique struct pages are initialized i.e. the first 2 4K pages per @align which means 128 struct pages, instead of 32768 for 2M @align or 262144 for a 1G @align. Keep old behaviour with altmap given that it doesn't support reusal of tail vmemmap areas. Signed-off-by: Joao Martins <joao.m.martins@xxxxxxxxxx> --- mm/page_alloc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 3a77f9e43f3a..948dfad6754b 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -6277,6 +6277,8 @@ static void __ref __init_zone_device_page(struct page *page, unsigned long pfn, } } +#define MEMMAP_NR_PAGES (2 * (PAGE_SIZE/sizeof(struct page))) + void __ref memmap_init_zone_device(struct zone *zone, unsigned long start_pfn, unsigned long nr_pages, @@ -6287,6 +6289,7 @@ void __ref memmap_init_zone_device(struct zone *zone, struct vmem_altmap *altmap = pgmap_altmap(pgmap); unsigned int pfn_align = pgmap_pfn_align(pgmap); unsigned int order_align = order_base_2(pfn_align); + unsigned long ntails = min_t(unsigned long, pfn_align, MEMMAP_NR_PAGES); unsigned long zone_idx = zone_idx(zone); unsigned long start = jiffies; int nid = pgdat->node_id; @@ -6302,6 +6305,7 @@ void __ref memmap_init_zone_device(struct zone *zone, if (altmap) { start_pfn = altmap->base_pfn + vmem_altmap_offset(altmap); nr_pages = end_pfn - start_pfn; + ntails = pfn_align; } for (pfn = start_pfn; pfn < end_pfn; pfn += pfn_align) { @@ -6315,7 +6319,7 @@ void __ref memmap_init_zone_device(struct zone *zone, __SetPageHead(page); - for (i = 1; i < pfn_align; i++) { + for (i = 1; i < ntails; i++) { __init_zone_device_page(page + i, pfn + i, zone_idx, nid, pgmap); prep_compound_tail(page, i); -- 2.17.1