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 11:27:59 +0800 [thread overview]
Message-ID: <8b7f6573-ed12-494f-9210-d6f6dbf01567@linux.dev> (raw)
In-Reply-To: <4EC5E593-7537-4659-879C-95ECC2224D2F@linux.dev>
Hi Muchun,
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;
#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;
+
mask = cma_bitmap_aligned_mask(cma, align);
offset = cma_bitmap_aligned_offset(cma, cmr, align);
bitmap_maxno = cma_bitmap_maxno(cma, cmr);
diff --git a/mm/hugetlb_cma.c b/mm/hugetlb_cma.c
index dde1c866406f..95fd2d190f0d 100644
--- a/mm/hugetlb_cma.c
+++ b/mm/hugetlb_cma.c
@@ -62,9 +62,6 @@ struct folio *hugetlb_cma_alloc_frozen_folio(int
order, gfp_t gfp_mask,
if (!hugetlb_cma_size)
return NULL;
- if (current->flags & PF_MEMALLOC_PIN)
- return NULL;
-
retry_cpuset:
if (!nodemask) {
cpuset_mems_cookie = read_mems_allowed_begin();
Thanks,
Qi
>
> Thanks,
> Muchun
>
>>
>> Fixes: eb02f14c4a2b ("mm/hugetlb: allow overcommitting gigantic hugepages")
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
>> ---
>> mm/hugetlb_cma.c | 3 +++
>> 1 file changed, 3 insertions(+)
>>
>> diff --git a/mm/hugetlb_cma.c b/mm/hugetlb_cma.c
>> index 95fd2d190f0d2..dde1c866406fb 100644
>> --- a/mm/hugetlb_cma.c
>> +++ b/mm/hugetlb_cma.c
>> @@ -62,6 +62,9 @@ struct folio *hugetlb_cma_alloc_frozen_folio(int order, gfp_t gfp_mask,
>> if (!hugetlb_cma_size)
>> return NULL;
>>
>> + if (current->flags & PF_MEMALLOC_PIN)
>> + return NULL;
>> +
>> retry_cpuset:
>> if (!nodemask) {
>> cpuset_mems_cookie = read_mems_allowed_begin();
>> --
>> 2.54.0
>>
>
next prev parent reply other threads:[~2026-11-04 3:28 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 [this message]
2026-11-04 6:51 ` Muchun Song
2026-11-04 7:07 ` Muchun Song
2026-11-04 7:47 ` Qi Zheng
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=8b7f6573-ed12-494f-9210-d6f6dbf01567@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.