[PATCH 14/49] mm/cma: validate hugetlb CMA range by zone at reserve time

Muchun Song
2026-04-05T12:54:57Z

During hugetlb_cma_reserve() we already have access to zone information, so we
can validate that the reserved CMA range does not span multiple zones.

Doing this check up front allows future hugetlb allocations from CMA to assume
zone-valid CMA areas, avoiding additional validity checks and potential
fallback/rollback paths, greatly simplifying the code.

The pfn_valid() check is removed from cma_validate_zones() because mem_section is
not initialized at that stage and it can trigger false warnings; keep the
sanity check in cma_activate_area() instead. This is preparatory work for the
follow-up simplification.

Signed-off-by: Muchun Song <songmuchun@bytedance.com>
---
mm/cma.c | 3 ++-
mm/hugetlb_cma.c | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/mm/cma.c b/mm/cma.c
index 15cc0ae76c8e..dd046a23f467 100644
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -125,7 +125,6 @@ bool cma_validate_zones(struct cma *cma)
* to be in the same zone. Simplify by forcing the entire
* CMA resv range to be in the same zone.
*/
- WARN_ON_ONCE(!pfn_valid(base_pfn));
if (pfn_range_intersects_zones(cma->nid, base_pfn, cmr->count)) {
set_bit(CMA_ZONES_INVALID, &cma->flags);
return false;
@@ -164,6 +163,8 @@ static void __init cma_activate_area(struct cma *cma)
bitmap_set(cmr->bitmap, 0, bitmap_count);
}

+ WARN_ON_ONCE(!pfn_valid(cmr->base_pfn));
+
for (pfn = early_pfn[r]; pfn < cmr->base_pfn + cmr->count;
pfn += pageblock_nr_pages)
init_cma_reserved_pageblock(pfn_to_page(pfn));
diff --git a/mm/hugetlb_cma.c b/mm/hugetlb_cma.c
index f83ae4998990..b068e9bf6537 100644
--- a/mm/hugetlb_cma.c
+++ b/mm/hugetlb_cma.c
@@ -233,9 +233,10 @@ void __init hugetlb_cma_reserve(void)
res = cma_declare_contiguous_multi(size, PAGE_SIZE << order,
HUGETLB_PAGE_ORDER, name,
&hugetlb_cma[nid], nid);
- if (res) {
+ if (res || !cma_validate_zones(hugetlb_cma[nid])) {
pr_warn("hugetlb_cma: reservation failed: err %d, node %d",
res, nid);
+ hugetlb_cma[nid] = NULL;
continue;
}

--
2.20.1