All of lore.kernel.org
 help / color / mirror / Atom feed
From: Qi Zheng <qi.zheng@linux.dev>
To: Muchun Song <muchun.song@linux.dev>
Cc: osalvador@suse.de, David Hildenbrand <david@kernel.org>,
	akpm@linux-foundation.org, azpijr@gmail.com,
	linux-kernel@vger.kernel.org, linux-mm@kvack.org,
	stable@vger.kernel.org, Qi Zheng <zhengqi.arch@bytedance.com>
Subject: Re: [PATCH 2/4] mm: hugetlb: skip CMA allocations under PF_MEMALLOC_PIN
Date: Wed, 4 Nov 2026 15:47:47 +0800	[thread overview]
Message-ID: <ae47e4d2-e847-4ee5-901f-56536527eadd@linux.dev> (raw)
In-Reply-To: <2DE679F1-C87F-4222-A710-C87CDE86D333@linux.dev>

Hi Muchun,

On 11/4/26 3:07 PM, Muchun Song wrote:
> 
> 
>> On Nov 4, 2026, at 11:27, Qi Zheng <qi.zheng@linux.dev> wrote:
>>
>> Hi Muchun,
> 
> Hi,
> 
>>
>> On 11/3/26 6:56 PM, Muchun Song wrote:
>>>> On Nov 3, 2026, at 16:01, Qi Zheng <qi.zheng@linux.dev> wrote:
>>>>
>>>> From: Qi Zheng <zhengqi.arch@bytedance.com>
>>>>
>>>> With gigantic overcommit enabled, a fault during long-term pinning
>>>> can allocate a fresh HugeTLB folio from CMA despite PF_MEMALLOC_PIN.
>>>>
>>>> The folio must then be migrated before it can be pinned. However,
>>>> fresh gigantic migration targets are not supported, so pinning fails
>>>> when the HugeTLB pool has no suitable target, even if the original
>>>> fault could have allocated pinnable memory outside CMA.
>>>>
>>>> Honor PF_MEMALLOC_PIN in the HugeTLB CMA allocator so the fault can
>>>> try the non-CMA fallback, or fail when allocation is restricted to CMA.
>>> Wait... I think my Acked-by got ahead of me here. :)
>>> There seems to be a rather odd distinction that GUP is missing.
>>> The usual reason long-term GUP must migrate a page out of a
>>> MIGRATE_CMA pageblock is that the page was only borrowed from CMA by the
>>> normal page allocator.  The corresponding CMA bitmap range is still
>>> available, so a future CMA allocation relies on being able to migrate
>>> that page away.  A long-term pin would prevent that.
>>> However, a HugeTLB folio returned by
>>> hugetlb_cma_alloc_frozen_folio() is different.  It is the actual CMA
>>> allocation, not merely a movable page that happens to reside in a
>>> MIGRATE_CMA pageblock.  Its range has already been marked allocated in
>>> the hugetlb CMA bitmap.
>>> Therefore, CMA cannot allocate that range again until the HugeTLB folio
>>> is freed anyway.  Long-term pinning the folio does not seem to make the
>>> CMA area any less available than keeping the HugeTLB folio mapped for
>>> the same amount of time.
>>> folio_is_longterm_pinnable() currently only sees MIGRATE_CMA and does
>>> not distinguish these two cases.  In that light, rejecting
>>> PF_MEMALLOC_PIN in hugetlb_cma_alloc_frozen_folio() looks like working
>>> around an overly broad GUP classification.  It also means that
>>> hugetlb_cma_only users will fail the fault, while other users may consume
>>> a gigantic contiguous range outside the dedicated hugetlb CMA area even
>>> when that area has free space.
>>> Would it make more sense to fix the long-term GUP check instead, so that
>>> an explicitly CMA-allocated HugeTLB folio is considered pinnable, while
>>> ordinary pages merely borrowed from MIGRATE_CMA pageblocks remain unpinnable?
>>
>> Make sense!
>>
>> I'll replace this patch with an exception for HPG_cma folios in the
>> MIGRATE_CMA check. This also lets the HugeTLB allocator select preallocated
>> CMA folios during long-term pinning. MIGRATE_ISOLATE and ZONE_MOVABLE
>> remain restricted.
>>
>> Fresh CMA allocations under PF_MEMALLOC_PIN also need to skip ranges
>> in ZONE_MOVABLE. Returning -EBUSY here lets CMA try its remaining ranges.
>>
>> The incremental diff against this patch is below.
>>
>> diff --git a/include/linux/cma.h b/include/linux/cma.h
>> index 8555d38a97b1..7fd1b6e65b58 100644
>> --- a/include/linux/cma.h
>> +++ b/include/linux/cma.h
>> @@ -21,11 +21,13 @@
>> #define CMA_MIN_ALIGNMENT_BYTES (PAGE_SIZE * CMA_MIN_ALIGNMENT_PAGES)
>>
>> struct cma;
>> +struct folio;
>>
>> extern unsigned long totalcma_pages;
>> extern phys_addr_t cma_get_base(const struct cma *cma);
>> extern unsigned long cma_get_size(const struct cma *cma);
>> extern const char *cma_get_name(const struct cma *cma);
>> +bool cma_folio_is_pinnable(struct folio *folio);
>>
>> extern int __init cma_declare_contiguous_nid(phys_addr_t base,
>> 			phys_addr_t size, phys_addr_t limit,
>> diff --git a/include/linux/mm.h b/include/linux/mm.h
>> index cb993a1d0728..d15810be7d96 100644
>> --- a/include/linux/mm.h
>> +++ b/include/linux/mm.h
>> @@ -3,6 +3,7 @@
>> #define _LINUX_MM_H
>>
>> #include <linux/args.h>
>> +#include <linux/cma.h>
>> #include <linux/errno.h>
>> #include <linux/mmdebug.h>
>> #include <linux/gfp.h>
>> @@ -2975,14 +2976,16 @@ static inline bool is_zero_folio(const struct folio *folio)
>> 	return is_zero_page(&folio->page);
>> }
>>
>> -/* MIGRATE_CMA and ZONE_MOVABLE do not allow pin folios */
>> +/* Borrowed CMA pages and ZONE_MOVABLE folios cannot be pinned long term. */
>> #ifdef CONFIG_MIGRATION
>> static inline bool folio_is_longterm_pinnable(struct folio *folio)
>> {
>> #ifdef CONFIG_CMA
>> 	int mt = folio_migratetype(folio);
>>
>> -	if (mt == MIGRATE_CMA || mt == MIGRATE_ISOLATE)
>> +	if (mt == MIGRATE_ISOLATE)
>> +		return false;
>> +	if (mt == MIGRATE_CMA && !cma_folio_is_pinnable(folio))
>> 		return false;
> 
> Actually, we do not need cma_folio_is_pinnable(), does the following work for you?

OK, will do.

> 
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -2982,6 +2982,9 @@ static inline bool folio_is_longterm_pinnable(struct folio *folio)
>   #ifdef CONFIG_CMA
>          int mt = folio_migratetype(folio);
> 
> +       if (folio_test_hugetlb(folio) && folio_test_hugetlb_cma(folio))
> +               return true;
> +
>          if (mt == MIGRATE_CMA || mt == MIGRATE_ISOLATE)
>                  return false;
>   #endif

We should move the implementation of folio_is_longterm_pinnable() to
mm/gup.c to avoid the header dependency and build errors.

> 
>> #endif
>> /* The zero page can be "pinned" but gets special handling. */
>> diff --git a/mm/cma.c b/mm/cma.c
>> index a10ea37a261d..c2814f54f86a 100644
>> --- a/mm/cma.c
>> +++ b/mm/cma.c
>> @@ -27,6 +27,7 @@
>> #include <linux/log2.h>
>> #include <linux/cma.h>
>> #include <linux/highmem.h>
>> +#include <linux/hugetlb.h>
>> #include <linux/io.h>
>> #include <linux/kmemleak.h>
>> #include <trace/events/cma.h>
>> @@ -55,6 +56,12 @@ const char *cma_get_name(const struct cma *cma)
>> }
>> EXPORT_SYMBOL_GPL(cma_get_name);
>>
>> +bool cma_folio_is_pinnable(struct folio *folio)
>> +{
>> +	/* Explicit HugeTLB CMA allocations own their bitmap ranges. */
>> +	return folio_test_hugetlb(folio) && folio_test_hugetlb_cma(folio);
>> +}
>> +
>> static unsigned long cma_bitmap_aligned_mask(const struct cma *cma,
>> 					     unsigned int align_order)
>> {
>> @@ -792,6 +799,11 @@ static int cma_range_alloc(struct cma *cma, struct cma_memrange *cmr,
>> 	int ret = -EBUSY;
>> 	struct page *page = NULL;
>>
>> + 	/* Each range lies within one zone; try other ranges if needed. */
>> +	if ((current->flags & PF_MEMALLOC_PIN) &&
>> + 	    is_zone_movable_page(pfn_to_page(cmr->base_pfn)))
>> +		return -EBUSY;
> 
> I don't know why we need this.

I had assumed that ZONE_MOVABLE pages must always remain unpinnable.
But Documentation/admin-guide/mm/memory-hotplug.rst explicitly states:

   - Memory blocks overlapping with CMA areas cannot be offlined, this 
applies to
     memory blocks present during boot only.

So pinning explicitly CMA-allocated HugeTLB folios does not introduce
an additional offlining restriction. The ZONE_MOVABLE check I added
in cma_range_alloc() is unnecessary, and I'll drop it.

Thanks,
Qi



  reply	other threads:[~2026-11-04  7:48 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-03  8:01 [PATCH 0/4] mm: hugetlb: fix some CMA-related issues Qi Zheng
2026-11-03  8:01 ` [PATCH 1/4] x86: hugetlb: disable default CMA reservations on 32-bit kernel Qi Zheng
2026-11-03  8:41   ` Muchun Song
2026-11-03 11:40   ` Jose A. Perez de Azpillaga
2026-11-03  8:01 ` [PATCH 2/4] mm: hugetlb: skip CMA allocations under PF_MEMALLOC_PIN Qi Zheng
2026-11-03  8:44   ` Muchun Song
2026-11-03 10:56   ` Muchun Song
2026-11-03 11:59     ` Jose A. Perez de Azpillaga
2026-11-04  3:27     ` Qi Zheng
2026-11-04  6:51       ` Muchun Song
2026-11-04  7:07       ` Muchun Song
2026-11-04  7:47         ` Qi Zheng [this message]
2026-11-03  8:01 ` [PATCH 3/4] mm: hugetlb: skip CMA when direct reclaim is disallowed Qi Zheng
2026-11-03  8:47   ` sashiko-bot
2026-11-03  9:11     ` Qi Zheng
2026-11-03  8:01 ` [PATCH 4/4] mm: hugetlb: respect cpuset restrictions for surplus allocations Qi Zheng
2026-11-03 12:21   ` Jose A. Perez de Azpillaga
2026-11-04  3:39     ` Qi Zheng

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ae47e4d2-e847-4ee5-901f-56536527eadd@linux.dev \
    --to=qi.zheng@linux.dev \
    --cc=akpm@linux-foundation.org \
    --cc=azpijr@gmail.com \
    --cc=david@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=muchun.song@linux.dev \
    --cc=osalvador@suse.de \
    --cc=stable@vger.kernel.org \
    --cc=zhengqi.arch@bytedance.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.