Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mm/huge_memory: merge uniform_split_supported() and non_uniform_split_supported()

uniform_split_supported() and non_uniform_split_supported() share
significantly similar logic.

The only functional difference is that uniform_split_supported() includes
an additional check on the requested @new_order.

The reason for this check comes from the following two aspects:

* some file system or swap cache just supports order-0 folio
* the behavioral difference between uniform/non-uniform split

The behavioral difference between uniform split and non-uniform:

* uniform split splits folio directly to @new_order
* non-uniform split creates after-split folios with orders from
folio_order(folio) - 1 to new_order.

This means for non-uniform split or !new_order split we should check the
file system and swap cache respectively.

This commit unifies the logic and merge the two functions into a single
combined helper, removing redundant code and simplifying the split
support checking mechanism.

Link: https://lkml.kernel.org/r/20251106034155.21398-3-richard.weiyang@gmail.com
Fixes: c010d47f107f ("mm: thp: split huge page to any lower order pages")
Signed-off-by: Wei Yang <richard.weiyang@gmail.com>
Reviewed-by: Zi Yan <ziy@nvidia.com>
Cc: Zi Yan <ziy@nvidia.com>
Cc: "David Hildenbrand (Red Hat)" <david@kernel.org>
Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Barry Song <baohua@kernel.org>
Cc: Dev Jain <dev.jain@arm.com>
Cc: Lance Yang <lance.yang@linux.dev>
Cc: Liam Howlett <liam.howlett@oracle.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Nico Pache <npache@redhat.com>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Wei Yang and committed by
Andrew Morton
8a0e4bdd c467061f

+33 -46
+3 -5
include/linux/huge_mm.h
··· 374 374 unsigned int new_order, bool unmapped); 375 375 int min_order_for_split(struct folio *folio); 376 376 int split_folio_to_list(struct folio *folio, struct list_head *list); 377 - bool uniform_split_supported(struct folio *folio, unsigned int new_order, 378 - bool warns); 379 - bool non_uniform_split_supported(struct folio *folio, unsigned int new_order, 380 - bool warns); 377 + bool folio_split_supported(struct folio *folio, unsigned int new_order, 378 + enum split_type split_type, bool warns); 381 379 int folio_split(struct folio *folio, unsigned int new_order, struct page *page, 382 380 struct list_head *list); 383 381 ··· 406 408 static inline int try_folio_split_to_order(struct folio *folio, 407 409 struct page *page, unsigned int new_order) 408 410 { 409 - if (!non_uniform_split_supported(folio, new_order, /* warns= */ false)) 411 + if (!folio_split_supported(folio, new_order, SPLIT_TYPE_NON_UNIFORM, /* warns= */ false)) 410 412 return split_huge_page_to_order(&folio->page, new_order); 411 413 return folio_split(folio, new_order, page, NULL); 412 414 }
+30 -41
mm/huge_memory.c
··· 3593 3593 return 0; 3594 3594 } 3595 3595 3596 - bool non_uniform_split_supported(struct folio *folio, unsigned int new_order, 3597 - bool warns) 3596 + bool folio_split_supported(struct folio *folio, unsigned int new_order, 3597 + enum split_type split_type, bool warns) 3598 3598 { 3599 3599 if (folio_test_anon(folio)) { 3600 3600 /* order-1 is not supported for anonymous THP. */ ··· 3602 3602 "Cannot split to order-1 folio"); 3603 3603 if (new_order == 1) 3604 3604 return false; 3605 - } else if (IS_ENABLED(CONFIG_READ_ONLY_THP_FOR_FS) && 3606 - !mapping_large_folio_support(folio->mapping)) { 3607 - /* 3608 - * No split if the file system does not support large folio. 3609 - * Note that we might still have THPs in such mappings due to 3610 - * CONFIG_READ_ONLY_THP_FOR_FS. But in that case, the mapping 3611 - * does not actually support large folios properly. 3612 - */ 3613 - VM_WARN_ONCE(warns, 3614 - "Cannot split file folio to non-0 order"); 3615 - return false; 3616 - } 3617 - 3618 - /* Only swapping a whole PMD-mapped folio is supported */ 3619 - if (folio_test_swapcache(folio)) { 3620 - VM_WARN_ONCE(warns, 3621 - "Cannot split swapcache folio to non-0 order"); 3622 - return false; 3623 - } 3624 - 3625 - return true; 3626 - } 3627 - 3628 - /* See comments in non_uniform_split_supported() */ 3629 - bool uniform_split_supported(struct folio *folio, unsigned int new_order, 3630 - bool warns) 3631 - { 3632 - if (folio_test_anon(folio)) { 3633 - VM_WARN_ONCE(warns && new_order == 1, 3634 - "Cannot split to order-1 folio"); 3635 - if (new_order == 1) 3636 - return false; 3637 - } else if (new_order) { 3605 + } else if (split_type == SPLIT_TYPE_NON_UNIFORM || new_order) { 3638 3606 if (IS_ENABLED(CONFIG_READ_ONLY_THP_FOR_FS) && 3639 3607 !mapping_large_folio_support(folio->mapping)) { 3608 + /* 3609 + * We can always split a folio down to a single page 3610 + * (new_order == 0) uniformly. 3611 + * 3612 + * For any other scenario 3613 + * a) uniform split targeting a large folio 3614 + * (new_order > 0) 3615 + * b) any non-uniform split 3616 + * we must confirm that the file system supports large 3617 + * folios. 3618 + * 3619 + * Note that we might still have THPs in such 3620 + * mappings, which is created from khugepaged when 3621 + * CONFIG_READ_ONLY_THP_FOR_FS is enabled. But in that 3622 + * case, the mapping does not actually support large 3623 + * folios properly. 3624 + */ 3640 3625 VM_WARN_ONCE(warns, 3641 3626 "Cannot split file folio to non-0 order"); 3642 3627 return false; 3643 3628 } 3644 3629 } 3645 3630 3646 - if (new_order && folio_test_swapcache(folio)) { 3631 + /* 3632 + * swapcache folio could only be split to order 0 3633 + * 3634 + * non-uniform split creates after-split folios with orders from 3635 + * folio_order(folio) - 1 to new_order, making it not suitable for any 3636 + * swapcache folio split. Only uniform split to order-0 can be used 3637 + * here. 3638 + */ 3639 + if ((split_type == SPLIT_TYPE_NON_UNIFORM || new_order) && folio_test_swapcache(folio)) { 3647 3640 VM_WARN_ONCE(warns, 3648 3641 "Cannot split swapcache folio to non-0 order"); 3649 3642 return false; ··· 3704 3711 if (new_order >= old_order) 3705 3712 return -EINVAL; 3706 3713 3707 - if (split_type == SPLIT_TYPE_UNIFORM && !uniform_split_supported(folio, new_order, true)) 3708 - return -EINVAL; 3709 - 3710 - if (split_type == SPLIT_TYPE_NON_UNIFORM && 3711 - !non_uniform_split_supported(folio, new_order, true)) 3714 + if (!folio_split_supported(folio, new_order, split_type, /* warn = */ true)) 3712 3715 return -EINVAL; 3713 3716 3714 3717 is_hzp = is_huge_zero_folio(folio);