* [PATCH v3 1/3] x86: hugetlb: disable default CMA reservations on 32-bit kernel [not found] <cover.1794046188.git.zhengqi.arch@bytedance.com> @ 2026-11-07 10:30 ` Qi Zheng 2026-11-07 10:30 ` [PATCH v3 2/3] mm: gup: allow long-term pins of CMA-allocated HugeTLB folios Qi Zheng 2026-11-07 10:30 ` [PATCH v3 3/3] mm: hugetlb: fix GFP mask propagation to CMA Qi Zheng 2 siblings, 0 replies; 13+ messages in thread From: Qi Zheng @ 2026-11-07 10:30 UTC (permalink / raw) To: muchun.song, osalvador, david, akpm, azpijr, lance.yang Cc: linux-kernel, linux-mm, Qi Zheng, stable From: Qi Zheng <zhengqi.arch@bytedance.com> A 32-bit x86 kernel can run on a 64-bit-capable CPU advertising GBPAGES. arch_hugetlb_cma_order() checks only this feature and returns a nonzero order, although gigantic HugeTLB support on x86 requires CONFIG_X86_64. Specifying hugetlb_cma= can therefore reserve a CMA area that cannot serve the intended gigantic HugeTLB allocations. On non-PAE kernels, the folded PUD_SHIFT yields a 4 MiB order, which is equal to MAX_PAGE_ORDER. With CONFIG_DEBUG_VM enabled, this triggers the VM_WARN_ON(order <= MAX_PAGE_ORDER) check in hugetlb_cma_reserve(), warning that hugetlb_cma is attempting to reserve a non-gigantic order. Require CONFIG_X86_64 as well as GBPAGES when selecting the default CMA order to avoid these ineffective reservations. Fixes: cf11e85fc08c ("mm: hugetlb: optionally allocate gigantic hugepages using cma") Cc: stable@vger.kernel.org Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com> Acked-by: Muchun Song <muchun.song@linux.dev> Reviewed-by: Jose A. Perez de Azpillaga <azpijr@gmail.com> Acked-by: Oscar Salvador <osalvador@suse.de> --- arch/x86/mm/hugetlbpage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c index 3b26621c91286..70726a99ede7b 100644 --- a/arch/x86/mm/hugetlbpage.c +++ b/arch/x86/mm/hugetlbpage.c @@ -45,7 +45,7 @@ arch_initcall(gigantic_pages_init); unsigned int __init arch_hugetlb_cma_order(void) { - if (boot_cpu_has(X86_FEATURE_GBPAGES)) + if (IS_ENABLED(CONFIG_X86_64) && boot_cpu_has(X86_FEATURE_GBPAGES)) return PUD_SHIFT - PAGE_SHIFT; return 0; -- 2.54.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 2/3] mm: gup: allow long-term pins of CMA-allocated HugeTLB folios [not found] <cover.1794046188.git.zhengqi.arch@bytedance.com> 2026-11-07 10:30 ` [PATCH v3 1/3] x86: hugetlb: disable default CMA reservations on 32-bit kernel Qi Zheng @ 2026-11-07 10:30 ` Qi Zheng 2026-11-07 17:58 ` David Hildenbrand (Arm) 2026-11-07 10:30 ` [PATCH v3 3/3] mm: hugetlb: fix GFP mask propagation to CMA Qi Zheng 2 siblings, 1 reply; 13+ messages in thread From: Qi Zheng @ 2026-11-07 10:30 UTC (permalink / raw) To: muchun.song, osalvador, david, akpm, azpijr, lance.yang Cc: linux-kernel, linux-mm, Qi Zheng, stable From: Qi Zheng <zhengqi.arch@bytedance.com> Long-term pinning treats explicitly CMA-allocated HugeTLB folios as unpinnable, causing unnecessary migration or pinning failures. These folios already own their CMA bitmap ranges, and memory blocks overlapping CMA areas cannot be offlined. Allow HugeTLB folios with HPG_cma to be pinned directly, including in ZONE_MOVABLE. Fixes: cf11e85fc08c ("mm: hugetlb: optionally allocate gigantic hugepages using cma") Cc: stable@vger.kernel.org Suggested-by: Muchun Song <muchun.song@linux.dev> Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com> Acked-by: Muchun Song <muchun.song@linux.dev> Reviewed-by: Oscar Salvador <osalvador@suse.de> Reviewed-by: Jose A. Perez de Azpillaga <azpijr@gmail.com> --- include/linux/mm.h | 29 +---------------------------- mm/gup.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 2d0b8a4c9974f..75dd40265d3f4 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2975,35 +2975,8 @@ 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 */ #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) - return false; -#endif - /* The zero page can be "pinned" but gets special handling. */ - if (is_zero_folio(folio)) - return true; - - /* Coherent device memory must always allow eviction. */ - if (folio_is_device_coherent(folio)) - return false; - - /* - * Filesystems can only tolerate transient delays to truncate and - * hole-punch operations - */ - if (folio_is_fsdax(folio)) - return false; - - /* Otherwise, non-movable zone folios can be pinned. */ - return !folio_is_zone_movable(folio); - -} +bool folio_is_longterm_pinnable(struct folio *folio); #else static inline bool folio_is_longterm_pinnable(struct folio *folio) { diff --git a/mm/gup.c b/mm/gup.c index 2b405cce2ca5c..f41701c603500 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -2216,6 +2216,37 @@ struct page *get_dump_page(unsigned long addr, int *locked) #ifdef CONFIG_MIGRATION +bool folio_is_longterm_pinnable(struct folio *folio) +{ +#ifdef CONFIG_CMA + int mt = folio_migratetype(folio); + + /* These HugeTLB folios own the CMA memory, so they can be long-term pinned. */ + if (folio_test_hugetlb(folio) && folio_test_hugetlb_cma(folio)) + return true; + + if (mt == MIGRATE_CMA || mt == MIGRATE_ISOLATE) + return false; +#endif + /* The zero page can be "pinned" but gets special handling. */ + if (is_zero_folio(folio)) + return true; + + /* Coherent device memory must always allow eviction. */ + if (folio_is_device_coherent(folio)) + return false; + + /* + * Filesystems can only tolerate transient delays to truncate and + * hole-punch operations + */ + if (folio_is_fsdax(folio)) + return false; + + /* Otherwise, non-movable zone folios can be pinned. */ + return !folio_is_zone_movable(folio); +} + /* * An array of either pages or folios ("pofs"). Although it may seem tempting to * avoid this complication, by simply interpreting a list of folios as a list of -- 2.54.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v3 2/3] mm: gup: allow long-term pins of CMA-allocated HugeTLB folios 2026-11-07 10:30 ` [PATCH v3 2/3] mm: gup: allow long-term pins of CMA-allocated HugeTLB folios Qi Zheng @ 2026-11-07 17:58 ` David Hildenbrand (Arm) 2026-11-09 3:10 ` Qi Zheng 0 siblings, 1 reply; 13+ messages in thread From: David Hildenbrand (Arm) @ 2026-11-07 17:58 UTC (permalink / raw) To: Qi Zheng, muchun.song, osalvador, akpm, azpijr, lance.yang Cc: linux-kernel, linux-mm, Qi Zheng, stable On 11/7/26 11:30, Qi Zheng wrote: > From: Qi Zheng <zhengqi.arch@bytedance.com> > > Long-term pinning treats explicitly CMA-allocated HugeTLB folios as > unpinnable, causing unnecessary migration or pinning failures. > > These folios already own their CMA bitmap ranges, and memory blocks > overlapping CMA areas cannot be offlined. Allow HugeTLB folios with > HPG_cma to be pinned directly, including in ZONE_MOVABLE. > > Fixes: cf11e85fc08c ("mm: hugetlb: optionally allocate gigantic hugepages using cma") > Cc: stable@vger.kernel.org > Suggested-by: Muchun Song <muchun.song@linux.dev> > Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com> > Acked-by: Muchun Song <muchun.song@linux.dev> > Reviewed-by: Oscar Salvador <osalvador@suse.de> > Reviewed-by: Jose A. Perez de Azpillaga <azpijr@gmail.com> > --- > include/linux/mm.h | 29 +---------------------------- > mm/gup.c | 31 +++++++++++++++++++++++++++++++ > 2 files changed, 32 insertions(+), 28 deletions(-) > > diff --git a/include/linux/mm.h b/include/linux/mm.h > index 2d0b8a4c9974f..75dd40265d3f4 100644 > --- a/include/linux/mm.h > +++ b/include/linux/mm.h > @@ -2975,35 +2975,8 @@ 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 */ > #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) > - return false; > -#endif > - /* The zero page can be "pinned" but gets special handling. */ > - if (is_zero_folio(folio)) > - return true; > - > - /* Coherent device memory must always allow eviction. */ > - if (folio_is_device_coherent(folio)) > - return false; > - > - /* > - * Filesystems can only tolerate transient delays to truncate and > - * hole-punch operations > - */ > - if (folio_is_fsdax(folio)) > - return false; > - > - /* Otherwise, non-movable zone folios can be pinned. */ > - return !folio_is_zone_movable(folio); > - > -} Moving code while adding new stuff to it, please don't. Move code first, then modify it. I don't want to play "find the difference between two pictures" on a Saturday evening. > +bool folio_is_longterm_pinnable(struct folio *folio); > #else > static inline bool folio_is_longterm_pinnable(struct folio *folio) > { > diff --git a/mm/gup.c b/mm/gup.c > index 2b405cce2ca5c..f41701c603500 100644 > --- a/mm/gup.c > +++ b/mm/gup.c > @@ -2216,6 +2216,37 @@ struct page *get_dump_page(unsigned long addr, int *locked) > > #ifdef CONFIG_MIGRATION > > +bool folio_is_longterm_pinnable(struct folio *folio) > +{ > +#ifdef CONFIG_CMA > + int mt = folio_migratetype(folio); > + > + /* These HugeTLB folios own the CMA memory, so they can be long-term pinned. */ > + if (folio_test_hugetlb(folio) && folio_test_hugetlb_cma(folio)) > + return true; More hugetlb hackery ... don't like that, sorry. I think this just goes down to a problem we discussed a while ago that is independent of hugetlb: we'd need some way to identify that the the page was actually allocated by the CMA owner, and it's not just some other movable allcoation that ended up there. For something generic non-hugetlb thing, can't we call into CMA to ask whether the current chunk is marked allocated? If that's too hard, we could add a temporary hugetlb hack. But we all hate hugetlb hacks. :) -- Cheers, David ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 2/3] mm: gup: allow long-term pins of CMA-allocated HugeTLB folios 2026-11-07 17:58 ` David Hildenbrand (Arm) @ 2026-11-09 3:10 ` Qi Zheng 2026-11-11 7:43 ` David Hildenbrand (Arm) 0 siblings, 1 reply; 13+ messages in thread From: Qi Zheng @ 2026-11-09 3:10 UTC (permalink / raw) To: David Hildenbrand (Arm), muchun.song, osalvador, akpm, azpijr, lance.yang, Qi Zheng Cc: linux-kernel, linux-mm, stable On 11/8/26 1:58 AM, David Hildenbrand (Arm) wrote: > On 11/7/26 11:30, Qi Zheng wrote: >> From: Qi Zheng <zhengqi.arch@bytedance.com> >> >> Long-term pinning treats explicitly CMA-allocated HugeTLB folios as >> unpinnable, causing unnecessary migration or pinning failures. >> >> These folios already own their CMA bitmap ranges, and memory blocks >> overlapping CMA areas cannot be offlined. Allow HugeTLB folios with >> HPG_cma to be pinned directly, including in ZONE_MOVABLE. >> >> Fixes: cf11e85fc08c ("mm: hugetlb: optionally allocate gigantic hugepages using cma") >> Cc: stable@vger.kernel.org >> Suggested-by: Muchun Song <muchun.song@linux.dev> >> Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com> >> Acked-by: Muchun Song <muchun.song@linux.dev> >> Reviewed-by: Oscar Salvador <osalvador@suse.de> >> Reviewed-by: Jose A. Perez de Azpillaga <azpijr@gmail.com> >> --- >> include/linux/mm.h | 29 +---------------------------- >> mm/gup.c | 31 +++++++++++++++++++++++++++++++ >> 2 files changed, 32 insertions(+), 28 deletions(-) >> >> diff --git a/include/linux/mm.h b/include/linux/mm.h >> index 2d0b8a4c9974f..75dd40265d3f4 100644 >> --- a/include/linux/mm.h >> +++ b/include/linux/mm.h >> @@ -2975,35 +2975,8 @@ 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 */ >> #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) >> - return false; >> -#endif >> - /* The zero page can be "pinned" but gets special handling. */ >> - if (is_zero_folio(folio)) >> - return true; >> - >> - /* Coherent device memory must always allow eviction. */ >> - if (folio_is_device_coherent(folio)) >> - return false; >> - >> - /* >> - * Filesystems can only tolerate transient delays to truncate and >> - * hole-punch operations >> - */ >> - if (folio_is_fsdax(folio)) >> - return false; >> - >> - /* Otherwise, non-movable zone folios can be pinned. */ >> - return !folio_is_zone_movable(folio); >> - >> -} > > Moving code while adding new stuff to it, please don't. > > Move code first, then modify it. > > I don't want to play "find the difference between two pictures" on a Saturday > evening. ;), got it. I moved the code to resolve a build dependency. > >> +bool folio_is_longterm_pinnable(struct folio *folio); >> #else >> static inline bool folio_is_longterm_pinnable(struct folio *folio) >> { >> diff --git a/mm/gup.c b/mm/gup.c >> index 2b405cce2ca5c..f41701c603500 100644 >> --- a/mm/gup.c >> +++ b/mm/gup.c >> @@ -2216,6 +2216,37 @@ struct page *get_dump_page(unsigned long addr, int *locked) >> >> #ifdef CONFIG_MIGRATION >> >> +bool folio_is_longterm_pinnable(struct folio *folio) >> +{ >> +#ifdef CONFIG_CMA >> + int mt = folio_migratetype(folio); >> + >> + /* These HugeTLB folios own the CMA memory, so they can be long-term pinned. */ >> + if (folio_test_hugetlb(folio) && folio_test_hugetlb_cma(folio)) >> + return true; > More hugetlb hackery ... don't like that, sorry. Agree. > > I think this just goes down to a problem we discussed a while ago that is > independent of hugetlb: we'd need some way to identify that the the page was > actually allocated by the CMA owner, and it's not just some other movable > allcoation that ended up there. > > For something generic non-hugetlb thing, can't we call into CMA to ask whether > the current chunk is marked allocated? The existing bitmap is set before allocation completes, so the range may still contain borrowed movable pages. A set bit alone cannot establish ownership. A generic query may need separate ownership tracking, such as an owned_bitmap recording successfully allocated pages. Its updates and lookups would also need to handle concurrency with fast GUP. > > If that's too hard, we could add a temporary hugetlb hack. For this fix, I'd prefer to keep the current check. > > But we all hate hugetlb hacks. :) +1. > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 2/3] mm: gup: allow long-term pins of CMA-allocated HugeTLB folios 2026-11-09 3:10 ` Qi Zheng @ 2026-11-11 7:43 ` David Hildenbrand (Arm) 2026-11-11 10:26 ` Qi Zheng 0 siblings, 1 reply; 13+ messages in thread From: David Hildenbrand (Arm) @ 2026-11-11 7:43 UTC (permalink / raw) To: Qi Zheng, muchun.song, osalvador, akpm, azpijr, lance.yang, Qi Zheng Cc: linux-kernel, linux-mm, stable On 11/9/26 04:10, Qi Zheng wrote: > > > On 11/8/26 1:58 AM, David Hildenbrand (Arm) wrote: >> On 11/7/26 11:30, Qi Zheng wrote: >>> From: Qi Zheng <zhengqi.arch@bytedance.com> >>> >>> Long-term pinning treats explicitly CMA-allocated HugeTLB folios as >>> unpinnable, causing unnecessary migration or pinning failures. >>> >>> These folios already own their CMA bitmap ranges, and memory blocks >>> overlapping CMA areas cannot be offlined. Allow HugeTLB folios with >>> HPG_cma to be pinned directly, including in ZONE_MOVABLE. >>> >>> Fixes: cf11e85fc08c ("mm: hugetlb: optionally allocate gigantic hugepages using cma") >>> Cc: stable@vger.kernel.org >>> Suggested-by: Muchun Song <muchun.song@linux.dev> >>> Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com> >>> Acked-by: Muchun Song <muchun.song@linux.dev> >>> Reviewed-by: Oscar Salvador <osalvador@suse.de> >>> Reviewed-by: Jose A. Perez de Azpillaga <azpijr@gmail.com> >>> --- >>> include/linux/mm.h | 29 +---------------------------- >>> mm/gup.c | 31 +++++++++++++++++++++++++++++++ >>> 2 files changed, 32 insertions(+), 28 deletions(-) >>> >>> diff --git a/include/linux/mm.h b/include/linux/mm.h >>> index 2d0b8a4c9974f..75dd40265d3f4 100644 >>> --- a/include/linux/mm.h >>> +++ b/include/linux/mm.h >>> @@ -2975,35 +2975,8 @@ 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 */ >>> #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) >>> - return false; >>> -#endif >>> - /* The zero page can be "pinned" but gets special handling. */ >>> - if (is_zero_folio(folio)) >>> - return true; >>> - >>> - /* Coherent device memory must always allow eviction. */ >>> - if (folio_is_device_coherent(folio)) >>> - return false; >>> - >>> - /* >>> - * Filesystems can only tolerate transient delays to truncate and >>> - * hole-punch operations >>> - */ >>> - if (folio_is_fsdax(folio)) >>> - return false; >>> - >>> - /* Otherwise, non-movable zone folios can be pinned. */ >>> - return !folio_is_zone_movable(folio); >>> - >>> -} >> >> Moving code while adding new stuff to it, please don't. >> >> Move code first, then modify it. >> >> I don't want to play "find the difference between two pictures" on a Saturday >> evening. > You resent your series way too fast. Now we have discussions in to threads, congratulations ;) > ;), got it. > > I moved the code to resolve a build dependency. > Why can't that be resolved differently? What is the dependency? >> >>> +bool folio_is_longterm_pinnable(struct folio *folio); >>> #else >>> static inline bool folio_is_longterm_pinnable(struct folio *folio) >>> { >>> diff --git a/mm/gup.c b/mm/gup.c >>> index 2b405cce2ca5c..f41701c603500 100644 >>> --- a/mm/gup.c >>> +++ b/mm/gup.c >>> @@ -2216,6 +2216,37 @@ struct page *get_dump_page(unsigned long addr, int *locked) >>> >>> #ifdef CONFIG_MIGRATION >>> >>> +bool folio_is_longterm_pinnable(struct folio *folio) >>> +{ >>> +#ifdef CONFIG_CMA >>> + int mt = folio_migratetype(folio); >>> + >>> + /* These HugeTLB folios own the CMA memory, so they can be long-term pinned. */ >>> + if (folio_test_hugetlb(folio) && folio_test_hugetlb_cma(folio)) >>> + return true; >> More hugetlb hackery ... don't like that, sorry. > > Agree. > >> >> I think this just goes down to a problem we discussed a while ago that is >> independent of hugetlb: we'd need some way to identify that the the page was >> actually allocated by the CMA owner, and it's not just some other movable >> allcoation that ended up there. >> >> For something generic non-hugetlb thing, can't we call into CMA to ask whether >> the current chunk is marked allocated? > > The existing bitmap is set before allocation completes, so the range > may still contain borrowed movable pages. A set bit alone cannot > establish ownership. > > A generic query may need separate ownership tracking, such as an > owned_bitmap recording successfully allocated pages. Its updates and > lookups would also need to handle concurrency with fast GUP. Or simply two bitmaps? "trying allocation - allocated" -- Cheers, David ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 2/3] mm: gup: allow long-term pins of CMA-allocated HugeTLB folios 2026-11-11 7:43 ` David Hildenbrand (Arm) @ 2026-11-11 10:26 ` Qi Zheng 2026-11-11 22:26 ` Frank van der Linden 2026-11-12 8:40 ` David Hildenbrand (Arm) 0 siblings, 2 replies; 13+ messages in thread From: Qi Zheng @ 2026-11-11 10:26 UTC (permalink / raw) To: David Hildenbrand (Arm), muchun.song, osalvador, akpm, azpijr, lance.yang, Qi Zheng Cc: linux-kernel, linux-mm, stable Hi David, On 11/11/26 3:43 PM, David Hildenbrand (Arm) wrote: > On 11/9/26 04:10, Qi Zheng wrote: >> >> >> On 11/8/26 1:58 AM, David Hildenbrand (Arm) wrote: >>> On 11/7/26 11:30, Qi Zheng wrote: >>>> From: Qi Zheng <zhengqi.arch@bytedance.com> >>>> >>>> Long-term pinning treats explicitly CMA-allocated HugeTLB folios as >>>> unpinnable, causing unnecessary migration or pinning failures. >>>> >>>> These folios already own their CMA bitmap ranges, and memory blocks >>>> overlapping CMA areas cannot be offlined. Allow HugeTLB folios with >>>> HPG_cma to be pinned directly, including in ZONE_MOVABLE. >>>> >>>> Fixes: cf11e85fc08c ("mm: hugetlb: optionally allocate gigantic hugepages using cma") >>>> Cc: stable@vger.kernel.org >>>> Suggested-by: Muchun Song <muchun.song@linux.dev> >>>> Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com> >>>> Acked-by: Muchun Song <muchun.song@linux.dev> >>>> Reviewed-by: Oscar Salvador <osalvador@suse.de> >>>> Reviewed-by: Jose A. Perez de Azpillaga <azpijr@gmail.com> >>>> --- >>>> include/linux/mm.h | 29 +---------------------------- >>>> mm/gup.c | 31 +++++++++++++++++++++++++++++++ >>>> 2 files changed, 32 insertions(+), 28 deletions(-) >>>> >>>> diff --git a/include/linux/mm.h b/include/linux/mm.h >>>> index 2d0b8a4c9974f..75dd40265d3f4 100644 >>>> --- a/include/linux/mm.h >>>> +++ b/include/linux/mm.h >>>> @@ -2975,35 +2975,8 @@ 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 */ >>>> #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) >>>> - return false; >>>> -#endif >>>> - /* The zero page can be "pinned" but gets special handling. */ >>>> - if (is_zero_folio(folio)) >>>> - return true; >>>> - >>>> - /* Coherent device memory must always allow eviction. */ >>>> - if (folio_is_device_coherent(folio)) >>>> - return false; >>>> - >>>> - /* >>>> - * Filesystems can only tolerate transient delays to truncate and >>>> - * hole-punch operations >>>> - */ >>>> - if (folio_is_fsdax(folio)) >>>> - return false; >>>> - >>>> - /* Otherwise, non-movable zone folios can be pinned. */ >>>> - return !folio_is_zone_movable(folio); >>>> - >>>> -} >>> >>> Moving code while adding new stuff to it, please don't. >>> >>> Move code first, then modify it. >>> >>> I don't want to play "find the difference between two pictures" on a Saturday >>> evening. >> > > You resent your series way too fast. Got it. > > Now we have discussions in to threads, congratulations ;) > >> ;), got it. >> >> I moved the code to resolve a build dependency. >> > > Why can't that be resolved differently? What is the dependency? The dependency is that the new check wants to use `folio_test_hugetlb_cma()`, which is a HugeTLB-specific inline helper from `include/linux/hugetlb.h`. `folio_is_longterm_pinnable()` currently lives in `include/linux/mm.h`, while `include/linux/hugetlb.h` already includes `linux/mm.h`. So I can't simply use `folio_test_hugetlb_cma()` from `mm.h` > >>> >>>> +bool folio_is_longterm_pinnable(struct folio *folio); >>>> #else >>>> static inline bool folio_is_longterm_pinnable(struct folio *folio) >>>> { >>>> diff --git a/mm/gup.c b/mm/gup.c >>>> index 2b405cce2ca5c..f41701c603500 100644 >>>> --- a/mm/gup.c >>>> +++ b/mm/gup.c >>>> @@ -2216,6 +2216,37 @@ struct page *get_dump_page(unsigned long addr, int *locked) >>>> >>>> #ifdef CONFIG_MIGRATION >>>> >>>> +bool folio_is_longterm_pinnable(struct folio *folio) >>>> +{ >>>> +#ifdef CONFIG_CMA >>>> + int mt = folio_migratetype(folio); >>>> + >>>> + /* These HugeTLB folios own the CMA memory, so they can be long-term pinned. */ >>>> + if (folio_test_hugetlb(folio) && folio_test_hugetlb_cma(folio)) >>>> + return true; >>> More hugetlb hackery ... don't like that, sorry. >> >> Agree. >> >>> >>> I think this just goes down to a problem we discussed a while ago that is >>> independent of hugetlb: we'd need some way to identify that the the page was >>> actually allocated by the CMA owner, and it's not just some other movable >>> allcoation that ended up there. >>> >>> For something generic non-hugetlb thing, can't we call into CMA to ask whether >>> the current chunk is marked allocated? >> >> The existing bitmap is set before allocation completes, so the range >> may still contain borrowed movable pages. A set bit alone cannot >> establish ownership. The more accurate code path is as follows. Assuming the 2M buddy allocation is successful, page P is borrowed from the 1G CMA area. Now, proceed to request a new 1G huge page: only_alloc_fresh_hugetlb_folio --> alloc_gigantic_frozen_folio --> hugetlb_cma_alloc_frozen_folio --> cma_range_alloc /* set bitmap!! */ --> bitmap_set(cmr->bitmap, bitmap_no, bitmap_count); <time A> /* may fail */ alloc_contig_frozen_range /* set HPG_cma!! */ folio_set_hugetlb_cma(folio); At time A, for page P, a bitmap was set, but HPG_cma was not set. If a concurrent FOLL_LONGTERM pin uses the bitmap alone to determine ownership, it could incorrectly allow P to remain pinned. If alloc_contig_frozen_range() fails, cma_range_alloc() clears the bitmap bits, while the long-term pin on P remains. HPG_cma is set only after explicit CMA allocation succeeds. It records the folio's own CMA ownership, whereas a set bitmap bit can represent another allocation's in-flight reservation. Therefore, the bitmap alone cannot replace HPG_cma in this check. >> >> A generic query may need separate ownership tracking, such as an >> owned_bitmap recording successfully allocated pages. Its updates and >> lookups would also need to handle concurrency with fast GUP. > > Or simply two bitmaps? "trying allocation - allocated" As a fix, perhaps this is a bit too complex? :( Alternatively, we could adjust the timing for setting the bitmap, though this might introduce new concurrency issues. Thanks, Qi ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 2/3] mm: gup: allow long-term pins of CMA-allocated HugeTLB folios 2026-11-11 10:26 ` Qi Zheng @ 2026-11-11 22:26 ` Frank van der Linden 2026-11-12 3:27 ` Qi Zheng 2026-11-12 8:36 ` David Hildenbrand (Arm) 2026-11-12 8:40 ` David Hildenbrand (Arm) 1 sibling, 2 replies; 13+ messages in thread From: Frank van der Linden @ 2026-11-11 22:26 UTC (permalink / raw) To: Qi Zheng Cc: David Hildenbrand (Arm), muchun.song, osalvador, akpm, azpijr, lance.yang, Qi Zheng, linux-kernel, linux-mm, stable On Wed, Nov 11, 2026 at 2:27 AM Qi Zheng <zhengqi.arch@bytedance.com> wrote: > > Hi David, > > On 11/11/26 3:43 PM, David Hildenbrand (Arm) wrote: > > On 11/9/26 04:10, Qi Zheng wrote: > >> > >> > >> On 11/8/26 1:58 AM, David Hildenbrand (Arm) wrote: > >>> On 11/7/26 11:30, Qi Zheng wrote: > >>>> From: Qi Zheng <zhengqi.arch@bytedance.com> > >>>> > >>>> Long-term pinning treats explicitly CMA-allocated HugeTLB folios as > >>>> unpinnable, causing unnecessary migration or pinning failures. > >>>> > >>>> These folios already own their CMA bitmap ranges, and memory blocks > >>>> overlapping CMA areas cannot be offlined. Allow HugeTLB folios with > >>>> HPG_cma to be pinned directly, including in ZONE_MOVABLE. > >>>> > >>>> Fixes: cf11e85fc08c ("mm: hugetlb: optionally allocate gigantic hugepages using cma") > >>>> Cc: stable@vger.kernel.org > >>>> Suggested-by: Muchun Song <muchun.song@linux.dev> > >>>> Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com> > >>>> Acked-by: Muchun Song <muchun.song@linux.dev> > >>>> Reviewed-by: Oscar Salvador <osalvador@suse.de> > >>>> Reviewed-by: Jose A. Perez de Azpillaga <azpijr@gmail.com> > >>>> --- > >>>> include/linux/mm.h | 29 +---------------------------- > >>>> mm/gup.c | 31 +++++++++++++++++++++++++++++++ > >>>> 2 files changed, 32 insertions(+), 28 deletions(-) > >>>> > >>>> diff --git a/include/linux/mm.h b/include/linux/mm.h > >>>> index 2d0b8a4c9974f..75dd40265d3f4 100644 > >>>> --- a/include/linux/mm.h > >>>> +++ b/include/linux/mm.h > >>>> @@ -2975,35 +2975,8 @@ 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 */ > >>>> #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) > >>>> - return false; > >>>> -#endif > >>>> - /* The zero page can be "pinned" but gets special handling. */ > >>>> - if (is_zero_folio(folio)) > >>>> - return true; > >>>> - > >>>> - /* Coherent device memory must always allow eviction. */ > >>>> - if (folio_is_device_coherent(folio)) > >>>> - return false; > >>>> - > >>>> - /* > >>>> - * Filesystems can only tolerate transient delays to truncate and > >>>> - * hole-punch operations > >>>> - */ > >>>> - if (folio_is_fsdax(folio)) > >>>> - return false; > >>>> - > >>>> - /* Otherwise, non-movable zone folios can be pinned. */ > >>>> - return !folio_is_zone_movable(folio); > >>>> - > >>>> -} > >>> > >>> Moving code while adding new stuff to it, please don't. > >>> > >>> Move code first, then modify it. > >>> > >>> I don't want to play "find the difference between two pictures" on a Saturday > >>> evening. > >> > > > > You resent your series way too fast. > > Got it. > > > > > Now we have discussions in to threads, congratulations ;) > > > >> ;), got it. > >> > >> I moved the code to resolve a build dependency. > >> > > > > Why can't that be resolved differently? What is the dependency? > > The dependency is that the new check wants to use > `folio_test_hugetlb_cma()`, which is a HugeTLB-specific inline helper > from `include/linux/hugetlb.h`. > > `folio_is_longterm_pinnable()` currently lives in `include/linux/mm.h`, > while `include/linux/hugetlb.h` already includes `linux/mm.h`. So I > can't simply use `folio_test_hugetlb_cma()` from `mm.h` > > > > >>> > >>>> +bool folio_is_longterm_pinnable(struct folio *folio); > >>>> #else > >>>> static inline bool folio_is_longterm_pinnable(struct folio *folio) > >>>> { > >>>> diff --git a/mm/gup.c b/mm/gup.c > >>>> index 2b405cce2ca5c..f41701c603500 100644 > >>>> --- a/mm/gup.c > >>>> +++ b/mm/gup.c > >>>> @@ -2216,6 +2216,37 @@ struct page *get_dump_page(unsigned long addr, int *locked) > >>>> > >>>> #ifdef CONFIG_MIGRATION > >>>> > >>>> +bool folio_is_longterm_pinnable(struct folio *folio) > >>>> +{ > >>>> +#ifdef CONFIG_CMA > >>>> + int mt = folio_migratetype(folio); > >>>> + > >>>> + /* These HugeTLB folios own the CMA memory, so they can be long-term pinned. */ > >>>> + if (folio_test_hugetlb(folio) && folio_test_hugetlb_cma(folio)) > >>>> + return true; > >>> More hugetlb hackery ... don't like that, sorry. > >> > >> Agree. > >> > >>> > >>> I think this just goes down to a problem we discussed a while ago that is > >>> independent of hugetlb: we'd need some way to identify that the the page was > >>> actually allocated by the CMA owner, and it's not just some other movable > >>> allcoation that ended up there. > >>> > >>> For something generic non-hugetlb thing, can't we call into CMA to ask whether > >>> the current chunk is marked allocated? > >> > >> The existing bitmap is set before allocation completes, so the range > >> may still contain borrowed movable pages. A set bit alone cannot > >> establish ownership. > > The more accurate code path is as follows. > > Assuming the 2M buddy allocation is successful, page P is borrowed from > the 1G CMA area. > > Now, proceed to request a new 1G huge page: > > only_alloc_fresh_hugetlb_folio > --> alloc_gigantic_frozen_folio > --> hugetlb_cma_alloc_frozen_folio > --> cma_range_alloc > /* set bitmap!! */ > --> bitmap_set(cmr->bitmap, bitmap_no, bitmap_count); > > <time A> > > /* may fail */ > alloc_contig_frozen_range > > /* set HPG_cma!! */ > folio_set_hugetlb_cma(folio); > > At time A, for page P, a bitmap was set, but HPG_cma was not set. > > If a concurrent FOLL_LONGTERM pin uses the bitmap alone to determine > ownership, it could incorrectly allow P to remain pinned. If > alloc_contig_frozen_range() fails, cma_range_alloc() clears the bitmap > bits, while the long-term pin on P remains. > > HPG_cma is set only after explicit CMA allocation succeeds. It records > the folio's own CMA ownership, whereas a set bitmap bit can represent > another allocation's in-flight reservation. Therefore, the bitmap > alone cannot replace HPG_cma in this check. > > >> > >> A generic query may need separate ownership tracking, such as an > >> owned_bitmap recording successfully allocated pages. Its updates and > >> lookups would also need to handle concurrency with fast GUP. > > > > Or simply two bitmaps? "trying allocation - allocated" > > As a fix, perhaps this is a bit too complex? :( > > Alternatively, we could adjust the timing for setting the bitmap, though > this might introduce new concurrency issues. > > Thanks, > Qi Yeah, ideally there would be a way to identify folios allocated through cma_alloc. But that would probably require.. dare I say.. a page flag. Trying to check bitmaps does seem too complex. And, since we've had a local change that does exactly the same thing for a few years (which I apparently forgot to send along with other hugetlb_cma changes), I can confirm that this looks good to me and works. So, Reviewed-by: Frank van der Linden <fvdl@google.com> ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 2/3] mm: gup: allow long-term pins of CMA-allocated HugeTLB folios 2026-11-11 22:26 ` Frank van der Linden @ 2026-11-12 3:27 ` Qi Zheng 2026-11-12 8:36 ` David Hildenbrand (Arm) 1 sibling, 0 replies; 13+ messages in thread From: Qi Zheng @ 2026-11-12 3:27 UTC (permalink / raw) To: Frank van der Linden Cc: David Hildenbrand (Arm), muchun.song, osalvador, akpm, azpijr, lance.yang, linux-kernel, linux-mm, stable, Qi Zheng On 11/12/26 6:26 AM, Frank van der Linden wrote: > On Wed, Nov 11, 2026 at 2:27 AM Qi Zheng <zhengqi.arch@bytedance.com> wrote: >> >> Hi David, >> >> On 11/11/26 3:43 PM, David Hildenbrand (Arm) wrote: >>> On 11/9/26 04:10, Qi Zheng wrote: >>>> >>>> >>>> On 11/8/26 1:58 AM, David Hildenbrand (Arm) wrote: >>>>> On 11/7/26 11:30, Qi Zheng wrote: >>>>>> From: Qi Zheng <zhengqi.arch@bytedance.com> >>>>>> >>>>>> Long-term pinning treats explicitly CMA-allocated HugeTLB folios as >>>>>> unpinnable, causing unnecessary migration or pinning failures. >>>>>> >>>>>> These folios already own their CMA bitmap ranges, and memory blocks >>>>>> overlapping CMA areas cannot be offlined. Allow HugeTLB folios with >>>>>> HPG_cma to be pinned directly, including in ZONE_MOVABLE. >>>>>> >>>>>> Fixes: cf11e85fc08c ("mm: hugetlb: optionally allocate gigantic hugepages using cma") >>>>>> Cc: stable@vger.kernel.org >>>>>> Suggested-by: Muchun Song <muchun.song@linux.dev> >>>>>> Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com> >>>>>> Acked-by: Muchun Song <muchun.song@linux.dev> >>>>>> Reviewed-by: Oscar Salvador <osalvador@suse.de> >>>>>> Reviewed-by: Jose A. Perez de Azpillaga <azpijr@gmail.com> >>>>>> --- >>>>>> include/linux/mm.h | 29 +---------------------------- >>>>>> mm/gup.c | 31 +++++++++++++++++++++++++++++++ >>>>>> 2 files changed, 32 insertions(+), 28 deletions(-) >>>>>> >>>>>> diff --git a/include/linux/mm.h b/include/linux/mm.h >>>>>> index 2d0b8a4c9974f..75dd40265d3f4 100644 >>>>>> --- a/include/linux/mm.h >>>>>> +++ b/include/linux/mm.h >>>>>> @@ -2975,35 +2975,8 @@ 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 */ >>>>>> #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) >>>>>> - return false; >>>>>> -#endif >>>>>> - /* The zero page can be "pinned" but gets special handling. */ >>>>>> - if (is_zero_folio(folio)) >>>>>> - return true; >>>>>> - >>>>>> - /* Coherent device memory must always allow eviction. */ >>>>>> - if (folio_is_device_coherent(folio)) >>>>>> - return false; >>>>>> - >>>>>> - /* >>>>>> - * Filesystems can only tolerate transient delays to truncate and >>>>>> - * hole-punch operations >>>>>> - */ >>>>>> - if (folio_is_fsdax(folio)) >>>>>> - return false; >>>>>> - >>>>>> - /* Otherwise, non-movable zone folios can be pinned. */ >>>>>> - return !folio_is_zone_movable(folio); >>>>>> - >>>>>> -} >>>>> >>>>> Moving code while adding new stuff to it, please don't. >>>>> >>>>> Move code first, then modify it. >>>>> >>>>> I don't want to play "find the difference between two pictures" on a Saturday >>>>> evening. >>>> >>> >>> You resent your series way too fast. >> >> Got it. >> >>> >>> Now we have discussions in to threads, congratulations ;) >>> >>>> ;), got it. >>>> >>>> I moved the code to resolve a build dependency. >>>> >>> >>> Why can't that be resolved differently? What is the dependency? >> >> The dependency is that the new check wants to use >> `folio_test_hugetlb_cma()`, which is a HugeTLB-specific inline helper >> from `include/linux/hugetlb.h`. >> >> `folio_is_longterm_pinnable()` currently lives in `include/linux/mm.h`, >> while `include/linux/hugetlb.h` already includes `linux/mm.h`. So I >> can't simply use `folio_test_hugetlb_cma()` from `mm.h` >> >>> >>>>> >>>>>> +bool folio_is_longterm_pinnable(struct folio *folio); >>>>>> #else >>>>>> static inline bool folio_is_longterm_pinnable(struct folio *folio) >>>>>> { >>>>>> diff --git a/mm/gup.c b/mm/gup.c >>>>>> index 2b405cce2ca5c..f41701c603500 100644 >>>>>> --- a/mm/gup.c >>>>>> +++ b/mm/gup.c >>>>>> @@ -2216,6 +2216,37 @@ struct page *get_dump_page(unsigned long addr, int *locked) >>>>>> >>>>>> #ifdef CONFIG_MIGRATION >>>>>> >>>>>> +bool folio_is_longterm_pinnable(struct folio *folio) >>>>>> +{ >>>>>> +#ifdef CONFIG_CMA >>>>>> + int mt = folio_migratetype(folio); >>>>>> + >>>>>> + /* These HugeTLB folios own the CMA memory, so they can be long-term pinned. */ >>>>>> + if (folio_test_hugetlb(folio) && folio_test_hugetlb_cma(folio)) >>>>>> + return true; >>>>> More hugetlb hackery ... don't like that, sorry. >>>> >>>> Agree. >>>> >>>>> >>>>> I think this just goes down to a problem we discussed a while ago that is >>>>> independent of hugetlb: we'd need some way to identify that the the page was >>>>> actually allocated by the CMA owner, and it's not just some other movable >>>>> allcoation that ended up there. >>>>> >>>>> For something generic non-hugetlb thing, can't we call into CMA to ask whether >>>>> the current chunk is marked allocated? >>>> >>>> The existing bitmap is set before allocation completes, so the range >>>> may still contain borrowed movable pages. A set bit alone cannot >>>> establish ownership. >> >> The more accurate code path is as follows. >> >> Assuming the 2M buddy allocation is successful, page P is borrowed from >> the 1G CMA area. >> >> Now, proceed to request a new 1G huge page: >> >> only_alloc_fresh_hugetlb_folio >> --> alloc_gigantic_frozen_folio >> --> hugetlb_cma_alloc_frozen_folio >> --> cma_range_alloc >> /* set bitmap!! */ >> --> bitmap_set(cmr->bitmap, bitmap_no, bitmap_count); >> >> <time A> >> >> /* may fail */ >> alloc_contig_frozen_range >> >> /* set HPG_cma!! */ >> folio_set_hugetlb_cma(folio); >> >> At time A, for page P, a bitmap was set, but HPG_cma was not set. >> >> If a concurrent FOLL_LONGTERM pin uses the bitmap alone to determine >> ownership, it could incorrectly allow P to remain pinned. If >> alloc_contig_frozen_range() fails, cma_range_alloc() clears the bitmap >> bits, while the long-term pin on P remains. >> >> HPG_cma is set only after explicit CMA allocation succeeds. It records >> the folio's own CMA ownership, whereas a set bitmap bit can represent >> another allocation's in-flight reservation. Therefore, the bitmap >> alone cannot replace HPG_cma in this check. >> >>>> >>>> A generic query may need separate ownership tracking, such as an >>>> owned_bitmap recording successfully allocated pages. Its updates and >>>> lookups would also need to handle concurrency with fast GUP. >>> >>> Or simply two bitmaps? "trying allocation - allocated" >> >> As a fix, perhaps this is a bit too complex? :( >> >> Alternatively, we could adjust the timing for setting the bitmap, though >> this might introduce new concurrency issues. >> >> Thanks, >> Qi > > Yeah, ideally there would be a way to identify folios allocated > through cma_alloc. But that would probably require.. dare I say.. a > page flag. Trying to check bitmaps does seem too complex. Agree. > > And, since we've had a local change that does exactly the same thing > for a few years (which I apparently forgot to send along with other > hugetlb_cma changes), I can confirm that this looks good to me and > works. So, > > Reviewed-by: Frank van der Linden <fvdl@google.com> Thanks for your review and confirmation! ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 2/3] mm: gup: allow long-term pins of CMA-allocated HugeTLB folios 2026-11-11 22:26 ` Frank van der Linden 2026-11-12 3:27 ` Qi Zheng @ 2026-11-12 8:36 ` David Hildenbrand (Arm) 1 sibling, 0 replies; 13+ messages in thread From: David Hildenbrand (Arm) @ 2026-11-12 8:36 UTC (permalink / raw) To: Frank van der Linden, Qi Zheng Cc: muchun.song, osalvador, akpm, azpijr, lance.yang, Qi Zheng, linux-kernel, linux-mm, stable On 11/11/26 23:26, Frank van der Linden wrote: > On Wed, Nov 11, 2026 at 2:27 AM Qi Zheng <zhengqi.arch@bytedance.com> wrote: >> >> Hi David, >> >> On 11/11/26 3:43 PM, David Hildenbrand (Arm) wrote: >>> >>> You resent your series way too fast. >> >> Got it. >> >>> >>> Now we have discussions in to threads, congratulations ;) >>> >>> >>> Why can't that be resolved differently? What is the dependency? >> >> The dependency is that the new check wants to use >> `folio_test_hugetlb_cma()`, which is a HugeTLB-specific inline helper >> from `include/linux/hugetlb.h`. >> >> `folio_is_longterm_pinnable()` currently lives in `include/linux/mm.h`, >> while `include/linux/hugetlb.h` already includes `linux/mm.h`. So I >> can't simply use `folio_test_hugetlb_cma()` from `mm.h` >> >>> >> >> The more accurate code path is as follows. >> >> Assuming the 2M buddy allocation is successful, page P is borrowed from >> the 1G CMA area. >> >> Now, proceed to request a new 1G huge page: >> >> only_alloc_fresh_hugetlb_folio >> --> alloc_gigantic_frozen_folio >> --> hugetlb_cma_alloc_frozen_folio >> --> cma_range_alloc >> /* set bitmap!! */ >> --> bitmap_set(cmr->bitmap, bitmap_no, bitmap_count); >> >> <time A> >> >> /* may fail */ >> alloc_contig_frozen_range >> >> /* set HPG_cma!! */ >> folio_set_hugetlb_cma(folio); >> >> At time A, for page P, a bitmap was set, but HPG_cma was not set. >> >> If a concurrent FOLL_LONGTERM pin uses the bitmap alone to determine >> ownership, it could incorrectly allow P to remain pinned. If >> alloc_contig_frozen_range() fails, cma_range_alloc() clears the bitmap >> bits, while the long-term pin on P remains. >> >> HPG_cma is set only after explicit CMA allocation succeeds. It records >> the folio's own CMA ownership, whereas a set bitmap bit can represent >> another allocation's in-flight reservation. Therefore, the bitmap >> alone cannot replace HPG_cma in this check. >> >>> >>> Or simply two bitmaps? "trying allocation - allocated" >> >> As a fix, perhaps this is a bit too complex? :( >> >> Alternatively, we could adjust the timing for setting the bitmap, though >> this might introduce new concurrency issues. >> >> Thanks, >> Qi > > Yeah, ideally there would be a way to identify folios allocated > through cma_alloc. But that would probably require.. dare I say.. a > page flag. Trying to check bitmaps does seem too complex. Why? You know it's a CMA region. And CMA regions are limited and static. Bitmap check is cheap. Pageflag likely won't happen ... In general, please, it's ok to send some hugetlb hacks (that make me angry) as a quick fix, but please do think about a proper way of handling that. -- Cheers, David ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 2/3] mm: gup: allow long-term pins of CMA-allocated HugeTLB folios 2026-11-11 10:26 ` Qi Zheng 2026-11-11 22:26 ` Frank van der Linden @ 2026-11-12 8:40 ` David Hildenbrand (Arm) 1 sibling, 0 replies; 13+ messages in thread From: David Hildenbrand (Arm) @ 2026-11-12 8:40 UTC (permalink / raw) To: Qi Zheng, muchun.song, osalvador, akpm, azpijr, lance.yang, Qi Zheng Cc: linux-kernel, linux-mm, stable On 11/11/26 11:26, Qi Zheng wrote: > Hi David, > > On 11/11/26 3:43 PM, David Hildenbrand (Arm) wrote: >> On 11/9/26 04:10, Qi Zheng wrote: >>> >>> >>> >> >> You resent your series way too fast. > > Got it. > >> >> Now we have discussions in to threads, congratulations ;) >> >>> ;), got it. >>> >>> I moved the code to resolve a build dependency. >>> >> >> Why can't that be resolved differently? What is the dependency? > > The dependency is that the new check wants to use > `folio_test_hugetlb_cma()`, which is a HugeTLB-specific inline helper > from `include/linux/hugetlb.h`. > > `folio_is_longterm_pinnable()` currently lives in `include/linux/mm.h`, > while `include/linux/hugetlb.h` already includes `linux/mm.h`. So I > can't simply use `folio_test_hugetlb_cma()` from `mm.h` It's all so hacky. :) core-mm shouldn't have to worry about hugetlb internals like folio_test_hugetlb_cma(). >>> >>> A generic query may need separate ownership tracking, such as an >>> owned_bitmap recording successfully allocated pages. Its updates and >>> lookups would also need to handle concurrency with fast GUP. >> >> Or simply two bitmaps? "trying allocation - allocated" > > As a fix, perhaps this is a bit too complex? :( > > Alternatively, we could adjust the timing for setting the bitmap, though > this might introduce new concurrency issues. I think we had that order reversed in the past. Likely a second bitmap would allow us to fix it fairly easily. -- Cheers, David ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v3 3/3] mm: hugetlb: fix GFP mask propagation to CMA [not found] <cover.1794046188.git.zhengqi.arch@bytedance.com> 2026-11-07 10:30 ` [PATCH v3 1/3] x86: hugetlb: disable default CMA reservations on 32-bit kernel Qi Zheng 2026-11-07 10:30 ` [PATCH v3 2/3] mm: gup: allow long-term pins of CMA-allocated HugeTLB folios Qi Zheng @ 2026-11-07 10:30 ` Qi Zheng 2026-11-07 17:02 ` Oscar Salvador (SUSE) 2 siblings, 1 reply; 13+ messages in thread From: Qi Zheng @ 2026-11-07 10:30 UTC (permalink / raw) To: muchun.song, osalvador, david, akpm, azpijr, lance.yang Cc: linux-kernel, linux-mm, Qi Zheng, stable From: Qi Zheng <zhengqi.arch@bytedance.com> cma_alloc_frozen_compound() uses GFP_KERNEL, allowing direct reclaim during the first MPOL_PREFERRED_MANY allocation attempt even though the caller clears __GFP_DIRECT_RECLAIM. Pass the caller's GFP mask through the helper so CMA respects its reclaim constraints when trying the preferred nodes. Fixes: 9bda131c6093 ("mm: cma: add cma_alloc_frozen{_compound}()") Cc: stable@vger.kernel.org Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com> Acked-by: Muchun Song <muchun.song@linux.dev> Reviewed-by: Jose A. Perez de Azpillaga <azpijr@gmail.com> --- include/linux/cma.h | 2 +- mm/cma.c | 5 +++-- mm/hugetlb_cma.c | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/linux/cma.h b/include/linux/cma.h index 8555d38a97b1a..4539ea5f2c4e8 100644 --- a/include/linux/cma.h +++ b/include/linux/cma.h @@ -53,7 +53,7 @@ extern bool cma_release(struct cma *cma, const struct page *pages, unsigned long struct page *cma_alloc_frozen(struct cma *cma, unsigned long count, unsigned int align, bool no_warn); -struct page *cma_alloc_frozen_compound(struct cma *cma, unsigned int order); +struct page *cma_alloc_frozen_compound(struct cma *cma, unsigned int order, gfp_t gfp); bool cma_release_frozen(struct cma *cma, const struct page *pages, unsigned long count); diff --git a/mm/cma.c b/mm/cma.c index 9ec1d1fd5dff5..45017ed876f76 100644 --- a/mm/cma.c +++ b/mm/cma.c @@ -933,9 +933,10 @@ struct page *cma_alloc_frozen(struct cma *cma, unsigned long count, return __cma_alloc_frozen(cma, count, align, gfp); } -struct page *cma_alloc_frozen_compound(struct cma *cma, unsigned int order) +struct page *cma_alloc_frozen_compound(struct cma *cma, unsigned int order, gfp_t gfp) { - gfp_t gfp = GFP_KERNEL | __GFP_COMP | __GFP_NOWARN; + if (WARN_ON_ONCE(!(gfp & __GFP_COMP))) + return NULL; return __cma_alloc_frozen(cma, 1 << order, order, gfp); } diff --git a/mm/hugetlb_cma.c b/mm/hugetlb_cma.c index 80b2407e9f077..307e5736ecdbe 100644 --- a/mm/hugetlb_cma.c +++ b/mm/hugetlb_cma.c @@ -69,14 +69,14 @@ struct folio *hugetlb_cma_alloc_frozen_folio(int order, gfp_t gfp_mask, } if (hugetlb_cma[nid] && node_isset(nid, *nmask)) - page = cma_alloc_frozen_compound(hugetlb_cma[nid], order); + page = cma_alloc_frozen_compound(hugetlb_cma[nid], order, gfp_mask); if (!page && !(gfp_mask & __GFP_THISNODE)) { for_each_node_mask(node, *nmask) { if (node == nid || !hugetlb_cma[node]) continue; - page = cma_alloc_frozen_compound(hugetlb_cma[node], order); + page = cma_alloc_frozen_compound(hugetlb_cma[node], order, gfp_mask); if (page) break; } -- 2.54.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v3 3/3] mm: hugetlb: fix GFP mask propagation to CMA 2026-11-07 10:30 ` [PATCH v3 3/3] mm: hugetlb: fix GFP mask propagation to CMA Qi Zheng @ 2026-11-07 17:02 ` Oscar Salvador (SUSE) 2026-11-09 3:10 ` Qi Zheng 0 siblings, 1 reply; 13+ messages in thread From: Oscar Salvador (SUSE) @ 2026-11-07 17:02 UTC (permalink / raw) To: Qi Zheng Cc: muchun.song, osalvador, david, akpm, azpijr, lance.yang, linux-kernel, linux-mm, Qi Zheng, stable On Sat, Nov 07, 2026 at 06:30:47PM +0800, Qi Zheng wrote: > From: Qi Zheng <zhengqi.arch@bytedance.com> > > cma_alloc_frozen_compound() uses GFP_KERNEL, allowing direct reclaim > during the first MPOL_PREFERRED_MANY allocation attempt even though > the caller clears __GFP_DIRECT_RECLAIM. > > Pass the caller's GFP mask through the helper so CMA respects its > reclaim constraints when trying the preferred nodes. > > Fixes: 9bda131c6093 ("mm: cma: add cma_alloc_frozen{_compound}()") > Cc: stable@vger.kernel.org > Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com> > Acked-by: Muchun Song <muchun.song@linux.dev> > Reviewed-by: Jose A. Perez de Azpillaga <azpijr@gmail.com> Reviewed-by: Oscar Salvador (SUSE) <osalvador@kernel.org> A comment below: > --- a/mm/cma.c > +++ b/mm/cma.c > @@ -933,9 +933,10 @@ struct page *cma_alloc_frozen(struct cma *cma, unsigned long count, > return __cma_alloc_frozen(cma, count, align, gfp); > } > > -struct page *cma_alloc_frozen_compound(struct cma *cma, unsigned int order) > +struct page *cma_alloc_frozen_compound(struct cma *cma, unsigned int order, gfp_t gfp) > { > - gfp_t gfp = GFP_KERNEL | __GFP_COMP | __GFP_NOWARN; > + if (WARN_ON_ONCE(!(gfp & __GFP_COMP))) > + return NULL; I think this needs a comment explaining why we are checking for __GFP_COMP, because it might not be obvious to the casual reader. Something like: "The only caller of cma_alloc_frozen_compound() is hugetlb, and hugetlb constructs its gfp mask via htlb_alloc_mask(), which already sets __GFP_COMP. Check here for usecases bypassing htlb_alloc_mask()." Maybe in the future we do have some other users of this function which are outside of the hugetlb realm, but if we are propagating the gfp mask down the chain to this point, we do have to check that those users are also setting __GFP_COMP. -- Oscar Salvador SUSE Labs ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 3/3] mm: hugetlb: fix GFP mask propagation to CMA 2026-11-07 17:02 ` Oscar Salvador (SUSE) @ 2026-11-09 3:10 ` Qi Zheng 0 siblings, 0 replies; 13+ messages in thread From: Qi Zheng @ 2026-11-09 3:10 UTC (permalink / raw) To: Oscar Salvador (SUSE) Cc: muchun.song, osalvador, david, akpm, azpijr, lance.yang, linux-kernel, linux-mm, stable, Qi Zheng On 11/8/26 1:02 AM, Oscar Salvador (SUSE) wrote: > On Sat, Nov 07, 2026 at 06:30:47PM +0800, Qi Zheng wrote: >> From: Qi Zheng <zhengqi.arch@bytedance.com> >> >> cma_alloc_frozen_compound() uses GFP_KERNEL, allowing direct reclaim >> during the first MPOL_PREFERRED_MANY allocation attempt even though >> the caller clears __GFP_DIRECT_RECLAIM. >> >> Pass the caller's GFP mask through the helper so CMA respects its >> reclaim constraints when trying the preferred nodes. >> >> Fixes: 9bda131c6093 ("mm: cma: add cma_alloc_frozen{_compound}()") >> Cc: stable@vger.kernel.org >> Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com> >> Acked-by: Muchun Song <muchun.song@linux.dev> >> Reviewed-by: Jose A. Perez de Azpillaga <azpijr@gmail.com> > > Reviewed-by: Oscar Salvador (SUSE) <osalvador@kernel.org> > > A comment below: > >> --- a/mm/cma.c >> +++ b/mm/cma.c >> @@ -933,9 +933,10 @@ struct page *cma_alloc_frozen(struct cma *cma, unsigned long count, >> return __cma_alloc_frozen(cma, count, align, gfp); >> } >> >> -struct page *cma_alloc_frozen_compound(struct cma *cma, unsigned int order) >> +struct page *cma_alloc_frozen_compound(struct cma *cma, unsigned int order, gfp_t gfp) >> { >> - gfp_t gfp = GFP_KERNEL | __GFP_COMP | __GFP_NOWARN; >> + if (WARN_ON_ONCE(!(gfp & __GFP_COMP))) >> + return NULL; > > I think this needs a comment explaining why we are checking for __GFP_COMP, > because it might not be obvious to the casual reader. > Something like: > > "The only caller of cma_alloc_frozen_compound() is hugetlb, and hugetlb > constructs its gfp mask via htlb_alloc_mask(), which already sets > __GFP_COMP. Check here for usecases bypassing htlb_alloc_mask()." OK, will add this comment. Thanks, Qi > > > Maybe in the future we do have some other users of this function which are outside > of the hugetlb realm, but if we are propagating the gfp mask down the chain to this > point, we do have to check that those users are also setting __GFP_COMP. > > > ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-11-12 8:41 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <cover.1794046188.git.zhengqi.arch@bytedance.com>
2026-11-07 10:30 ` [PATCH v3 1/3] x86: hugetlb: disable default CMA reservations on 32-bit kernel Qi Zheng
2026-11-07 10:30 ` [PATCH v3 2/3] mm: gup: allow long-term pins of CMA-allocated HugeTLB folios Qi Zheng
2026-11-07 17:58 ` David Hildenbrand (Arm)
2026-11-09 3:10 ` Qi Zheng
2026-11-11 7:43 ` David Hildenbrand (Arm)
2026-11-11 10:26 ` Qi Zheng
2026-11-11 22:26 ` Frank van der Linden
2026-11-12 3:27 ` Qi Zheng
2026-11-12 8:36 ` David Hildenbrand (Arm)
2026-11-12 8:40 ` David Hildenbrand (Arm)
2026-11-07 10:30 ` [PATCH v3 3/3] mm: hugetlb: fix GFP mask propagation to CMA Qi Zheng
2026-11-07 17:02 ` Oscar Salvador (SUSE)
2026-11-09 3:10 ` Qi Zheng
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox