On 7/22/26 17:28, Zi Yan wrote: > On Wed Jul 22, 2026 at 10:26 AM EDT, Zi Yan wrote: >> On Wed Jul 22, 2026 at 12:42 AM EDT, Matthew Brost wrote: >>> Add a lightweight structural split primitive for large (compound) folios >>> that a driver allocated with __GFP_COMP and manages entirely by itself, >>> outside of the core mm's view. >>> >>> The existing split paths - split_folio() and folio_split_unmapped() - >>> are built for folios that the mm owns: they perform a refcount freeze, >>> walk and remap the rmap, and take the anon_vma / i_mmap locks, and >>> folio_split_unmapped() further assumes an anon, pagecache-style refcount >>> model (nr_pages + 1). None of that applies to a folio that is: >>> >>> - singly referenced (the caller holds the only reference), >>> - not mapped through the rmap (folio_mapped() == 0), >>> - not in the page cache or swap cache (folio->mapping == NULL), >>> - not on any LRU or the deferred-split list. >>> >>> For such a folio the split is purely structural: because nothing else in >>> the kernel can reach it, there is no need to freeze the refcount or touch >>> any mapping. folio_split_driver_managed() therefore performs only the >> >> I do not think so. PFN scanners like memory compaction should be able to >> see them, unless you mean something else about "a driver allocated with >> __GFP_COMP". You will need to freeze it to prevent the to-be-split >> folios being touched by others. >> >> >>> compound and split-accounting teardown via __split_unmapped_folio() and >>> then hands each resulting order-@new_order folio its own reference, >>> mirroring split_page() for compound folios. The caller keeps the original >>> reference on the first resulting folio and is responsible for freeing all >>> of them individually. >>> >>> The immediate user is TTM's GPU page pool, which allocates higher-order >>> compound pages, maps them into userspace via VM_PFNMAP (never through the >>> rmap), and needs to split them into order-0 folios under memory pressure >>> so pages can be backed up to shmem and freed one at a time. >>> >>> A CONFIG_TRANSPARENT_HUGEPAGE=n stub is provided so callers can build >>> without the split machinery; it warns and returns -EINVAL. >>> >>> Cc: Maarten Lankhorst <[email protected]> >>> Cc: Maxime Ripard <[email protected]> >>> Cc: Thomas Zimmermann <[email protected]> >>> Cc: David Airlie <[email protected]> >>> Cc: Simona Vetter <[email protected]> >>> Cc: Christian Koenig <[email protected]> >>> Cc: Huang Rui <[email protected]> >>> Cc: Matthew Auld <[email protected]> >>> Cc: Matthew Brost <[email protected]> >>> Cc: Andrew Morton <[email protected]> >>> Cc: David Hildenbrand <[email protected]> >>> Cc: Lorenzo Stoakes <[email protected]> >>> Cc: Zi Yan <[email protected]> >>> Cc: Baolin Wang <[email protected]> >>> Cc: "Liam R. Howlett" <[email protected]> >>> Cc: Nico Pache <[email protected]> >>> Cc: Ryan Roberts <[email protected]> >>> Cc: Dev Jain <[email protected]> >>> Cc: Barry Song <[email protected]> >>> Cc: Lance Yang <[email protected]> >>> Cc: Tvrtko Ursulin <[email protected]> >>> Cc: Dave Airlie <[email protected]> >>> Cc: [email protected] >>> Cc: [email protected] >>> Cc: [email protected] >>> Suggested-by: Matthew Wilcox <[email protected]> >>> Signed-off-by: Matthew Brost <[email protected]> >>> Assisted-by: GitHub-Copilot:claude-opus-4.8 >>> >>> --- >>> >>> The patch is based on drm-tip rather than the core MM branches to >>> facilitate Intel CI testing and initial review. It can be rebased onto >>> the core MM branches in a subsequent revision. >>> --- >>> include/linux/huge_mm.h | 8 ++++++ >>> mm/huge_memory.c | 63 +++++++++++++++++++++++++++++++++++++++++ >>> 2 files changed, 71 insertions(+) >>> >>> diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h >>> index ad20f7f8c179..35661d82d54a 100644 >>> --- a/include/linux/huge_mm.h >>> +++ b/include/linux/huge_mm.h >>> @@ -402,6 +402,7 @@ enum split_type { >>> int __split_huge_page_to_list_to_order(struct page *page, struct list_head >>> *list, >>> unsigned int new_order); >>> int folio_split_unmapped(struct folio *folio, unsigned int new_order); >>> +int folio_split_driver_managed(struct folio *folio, unsigned int >>> new_order); >>> unsigned int min_order_for_split(struct folio *folio); >>> int split_folio_to_list(struct folio *folio, struct list_head *list); >>> int folio_check_splittable(struct folio *folio, unsigned int new_order, >>> @@ -656,6 +657,13 @@ static inline int split_folio_to_list(struct folio >>> *folio, struct list_head *lis >>> return -EINVAL; >>> } >>> >>> +static inline int folio_split_driver_managed(struct folio *folio, >>> + unsigned int new_order) >>> +{ >>> + VM_WARN_ON_ONCE_FOLIO(1, folio); >>> + return -EINVAL; >>> +} >>> + >>> static inline int folio_split(struct folio *folio, unsigned int new_order, >>> struct page *page, struct list_head *list) >>> { >>> diff --git a/mm/huge_memory.c b/mm/huge_memory.c >>> index 2bccb0a53a0a..06f9a5f35df8 100644 >>> --- a/mm/huge_memory.c >>> +++ b/mm/huge_memory.c >>> @@ -4185,6 +4185,69 @@ int folio_split_unmapped(struct folio *folio, >>> unsigned int new_order) >>> return ret; >>> } >>> >>> +/** >>> + * folio_split_driver_managed() - split an exclusively-owned, off-LRU folio >>> + * @folio: folio to split. Must be a large (compound) folio that is owned >>> + * exclusively by the caller and is invisible to the core mm. >>> + * @new_order: the order of the folios after the split. >>> + * >>> + * This is a lightweight structural split for folios that a driver >>> allocated >>> + * and manages itself (for example TTM's GPU page pool, which allocates >>> + * higher-order compound pages with __GFP_COMP and maps them into userspace >>> + * via VM_PFNMAP rather than through the rmap). Such folios are: > > Strickly speaking, these vm_insert*() compound pages are not folios, > since folios are supposed to be rmappable and they are either anonymous > memory or file-backed memory. I am working on separating them from > rmappable folios by replacing PG_private with PG_folio and marking all > pages in a folio with PG_folio in page_rmappable_folio(). > > Hopefully, we can find a better name, like refcounted_folio, later for > these non-rmappable compound pages.
They wouldn't really be folios, I guess. They would likely be a simple "refcounted" memtype that allows for compound pages. But what is the conclusion here? It sounds like "folio_split_" is the entirely wrong interface for these compound pages. -- Cheers, David
