Re: [PATCH v2 9/9] mm: hugetlb: allocate frozen pages in alloc_gigantic_folio()

Zi Yan
2025-09-09T02:03:04Z

On 2 Sep 2025, at 8:48, Kefeng Wang wrote:

> The alloc_gigantic_folio() will allocate a folio by alloc_contig_range()

s/will allocate/allocates, since you are describing an existing behavior.
It confused me when I look at the code change.

> with refcount increated and then freeze it, convert to allocate a frozen
> folio directly to remove the atomic operation about folio refcount, also
> saving atomic operation during __update_and_free_hugetlb_folio too.
>
> Rename some functions to make them more self-explanatory,
>
> folio_alloc_gigantic -> folio_alloc_frozen_gigantic
> cma_alloc/free_folio -> cma_alloc/free_frozen_folio

s/cma_alloc/cma_alloc_folio, s/cma_alloc/cma_alloc_frozen_folio.
If you do not want to type folio multiple times,

{cma_alloc,free}_folio -> {cma_alloc,free}_frozen_folio would be
less confusing.

> hugetlb_cma_alloc/free_folio -> hugetlb_cma_alloc/free_frozen_folio

ditto.

>
> Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
> ---
> include/linux/cma.h | 8 ++++----
> include/linux/gfp.h | 14 ++++++-------
> mm/cma.c | 22 +++++++++++++-------
> mm/hugetlb.c | 50 +++++++++------------------------------------
> mm/hugetlb_cma.c | 13 ++++++------
> mm/hugetlb_cma.h | 10 ++++-----
> 6 files changed, 47 insertions(+), 70 deletions(-)
>
> diff --git a/include/linux/cma.h b/include/linux/cma.h
> index e5745d2aec55..cceec7b25bae 100644
> --- a/include/linux/cma.h
> +++ b/include/linux/cma.h
> @@ -57,16 +57,16 @@ extern bool cma_intersects(struct cma *cma, unsigned long start, unsigned long e
> extern void cma_reserve_pages_on_error(struct cma *cma);
>
> #ifdef CONFIG_CMA
> -struct folio *cma_alloc_folio(struct cma *cma, int order, gfp_t gfp);
> -bool cma_free_folio(struct cma *cma, const struct folio *folio);
> +struct folio *cma_alloc_frozen_folio(struct cma *cma, int order, gfp_t gfp);
> +bool cma_free_frozen_folio(struct cma *cma, const struct folio *folio);
> bool cma_validate_zones(struct cma *cma);
> #else
> -static inline struct folio *cma_alloc_folio(struct cma *cma, int order, gfp_t gfp)
> +static inline struct folio *cma_alloc_frozen_folio(struct cma *cma, int order, gfp_t gfp)
> {
> return NULL;
> }
>
> -static inline bool cma_free_folio(struct cma *cma, const struct folio *folio)
> +static inline bool cma_free_frozen_folio(struct cma *cma, const struct folio *folio)
> {
> return false;
> }
> diff --git a/include/linux/gfp.h b/include/linux/gfp.h
> index d0047b85fe34..ceda042be704 100644
> --- a/include/linux/gfp.h
> +++ b/include/linux/gfp.h
> @@ -447,26 +447,26 @@ struct page *alloc_contig_frozen_pages_noprof(unsigned long nr_pages,
> void free_contig_range(unsigned long pfn, unsigned long nr_pages);
>
> #ifdef CONFIG_CONTIG_ALLOC
> -static inline struct folio *folio_alloc_gigantic_noprof(int order, gfp_t gfp,
> - int nid, nodemask_t *node)
> +static inline struct folio *folio_alloc_frozen_gigantic_noprof(int order,
> + gfp_t gfp, int nid, nodemask_t *node)
> {
> struct page *page;
>
> if (WARN_ON(!order || !(gfp & __GFP_COMP)))
> return NULL;
>
> - page = alloc_contig_pages_noprof(1 << order, gfp, nid, node);
> + page = alloc_contig_frozen_pages_noprof(1 << order, gfp, nid, node);
>
> return page ? page_folio(page) : NULL;
> }
> #else
> -static inline struct folio *folio_alloc_gigantic_noprof(int order, gfp_t gfp,
> - int nid, nodemask_t *node)
> +static inline struct folio *folio_alloc_frozen_gigantic_noprof(int order,
> + gfp_t gfp, int nid, nodemask_t *node)
> {
> return NULL;
> }
> #endif
> -/* This should be paired with folio_put() rather than free_contig_range(). */
> -#define folio_alloc_gigantic(...) alloc_hooks(folio_alloc_gigantic_noprof(__VA_ARGS__))
> +/* This must be paired with free_frozen_pages() rather than free_contig_range(). */
> +#define folio_alloc_frozen_gigantic(...) alloc_hooks(folio_alloc_frozen_gigantic_noprof(__VA_ARGS__))
>
> #endif /* __LINUX_GFP_H */
> diff --git a/mm/cma.c b/mm/cma.c
> index b4413e382d5d..49d53879c1d0 100644
> --- a/mm/cma.c
> +++ b/mm/cma.c
> @@ -924,20 +924,21 @@ struct page *cma_alloc(struct cma *cma, unsigned long count,
> ACR_FLAGS_CMA);
> }
>
> -struct folio *cma_alloc_folio(struct cma *cma, int order, gfp_t gfp)
> +struct folio *cma_alloc_frozen_folio(struct cma *cma, int order, gfp_t gfp)
> {
> struct page *page;
>
> if (WARN_ON(!order || !(gfp & __GFP_COMP)))
> return NULL;
>
> - page = __cma_alloc(cma, 1 << order, order, gfp, ACR_FLAGS_CMA);
> + page = __cma_alloc(cma, 1 << order, order, gfp,
> + ACR_FLAGS_CMA | ACR_FLAGS_FROZEN);
>
> return page ? page_folio(page) : NULL;
> }
>
> static bool __cma_release(struct cma *cma, const struct page *pages,
> - unsigned long count)
> + unsigned long count, bool frozen_page)
> {
> unsigned long pfn, end;
> int r;
> @@ -960,7 +961,14 @@ static bool __cma_release(struct cma *cma, const struct page *pages,
> if (r == cma->nranges)
> return false;
>
> - free_contig_range(pfn, count);
> + if (frozen_page) {
> + struct page *head_page = compound_head((struct page *)pages);

A WARN_ONCE refcount check might be helpful, since there are two
cases here.

> +
> + free_frozen_pages(head_page, compound_order(head_page));
> + } else {
> + free_contig_range(pfn, count);
> + }
> +

Best Regards,
Yan, Zi