Early reservations made with cma_reserve_early() currently require callers to set the pageblock migratetype and update CMA statistics. These operations maintain CMA state and should be handled by the CMA core. Move initialization of early-reserved pageblocks into cma_activate_area(), alongside the remaining pageblocks. If activation fails, restore the managed-page accounting for early-reserved pages because they remain owned by the caller and are not released by the CMA cleanup path. Signed-off-by: Muchun Song --- mm/cma.c | 16 ++++++++++------ mm/hugetlb.c | 8 +++----- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/mm/cma.c b/mm/cma.c index 9ec1d1fd5dff..46e72734ba72 100644 --- a/mm/cma.c +++ b/mm/cma.c @@ -163,6 +163,10 @@ static void __init cma_activate_area(struct cma *cma) count = early_pfn[r] - cmr->base_pfn; bitmap_count = cma_bitmap_pages_to_bits(cma, count); bitmap_set(cmr->bitmap, 0, bitmap_count); + + for (pfn = cmr->base_pfn; pfn < early_pfn[r]; + pfn += pageblock_nr_pages) + init_cma_pageblock(pfn_to_page(pfn)); } WARN_ON_ONCE(!pfn_valid(cmr->base_pfn)); @@ -191,12 +195,13 @@ static void __init cma_activate_area(struct cma *cma) /* Expose all pages to the buddy, they are useless for CMA. */ if (!test_bit(CMA_RESERVE_PAGES_ON_ERROR, &cma->flags)) { for (r = 0; r < cma->nranges; r++) { - unsigned long start_pfn; - cmr = &cma->ranges[r]; - start_pfn = r <= allocrange ? early_pfn[r] : cmr->early_pfn; + end_pfn = r <= allocrange ? early_pfn[r] : cmr->early_pfn; + for (pfn = cmr->base_pfn; pfn < end_pfn; pfn++) + adjust_managed_page_count(pfn_to_page(pfn), 1); + end_pfn = cmr->base_pfn + cmr->count; - for (pfn = start_pfn; pfn < end_pfn; pfn++) + for (; pfn < end_pfn; pfn++) free_reserved_page(pfn_to_page(pfn)); } } @@ -1110,8 +1115,7 @@ bool cma_intersects(struct cma *cma, unsigned long start, unsigned long end) * * The caller is responsible for initializing the page structures * in the area properly, since this just points to memblock-allocated - * memory. The caller should subsequently use init_cma_pageblock to - * set the migrate type and CMA stats the pageblocks that were reserved. + * memory. * * If the CMA area fails to activate later, memory obtained through * this interface is not handed to the page allocator, this is diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 290e7859b2d7..ee47a3b09df3 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -3240,9 +3240,7 @@ static void __init hugetlb_bootmem_init_migratetype(struct folio *folio, WARN_ON_ONCE(!pageblock_aligned(folio_pfn(folio))); for (i = 0; i < nr_pages; i += pageblock_nr_pages) { - if (folio_test_hugetlb_cma(folio)) - init_cma_pageblock(folio_page(folio, i)); - else + if (!folio_test_hugetlb_cma(folio)) init_pageblock_migratetype(folio_page(folio, i), MIGRATE_MOVABLE, false); } @@ -3305,8 +3303,8 @@ static void __init gather_bootmem_prealloc_node(unsigned long nid) * in order to fix confusing memory reports from free(1) and * other side-effects, like CommitLimit going negative. * - * For CMA pages, this is done in init_cma_pageblock - * (via hugetlb_bootmem_init_migratetype), so skip it here. + * For CMA pages, this is done in cma_activate_area(), so skip + * it here. */ if (hugetlb_early_cma(h)) folio_set_hugetlb_cma(folio); -- 2.54.0