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: make min_order_for_split() always return an order

min_order_for_split() returns -EBUSY when the folio is truncated and
cannot be split. In commit 77008e1b2ef7 ("mm/huge_memory: do not change
split_huge_page*() target order silently"), memory_failure() does not
handle it and pass -EBUSY to try_to_split_thp_page() directly.
try_to_split_thp_page() returns -EINVAL since -EBUSY becomes 0xfffffff0 as
new_order is unsigned int in __folio_split() and this large new_order is
rejected as an invalid input. The code does not cause a bug.
soft_offline_in_use_page() also uses min_order_for_split() but it always
passes 0 as new_order for split.

Fix it by making min_order_for_split() always return an order. When the
given folio is truncated, namely folio->mapping == NULL, return 0 and let
a subsequent split function handle the situation and return -EBUSY.

Add kernel-doc to min_order_for_split() to clarify its use.

Link: https://lkml.kernel.org/r/20251126210618.1971206-4-ziy@nvidia.com
Signed-off-by: Zi Yan <ziy@nvidia.com>
Reviewed-by: Wei Yang <richard.weiyang@gmail.com>
Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>
Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Balbir Singh <balbirs@nvidia.com>
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: Miaohe Lin <linmiaohe@huawei.com>
Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
Cc: Nico Pache <npache@redhat.com>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Zi Yan and committed by
Andrew Morton
2f789106 5842bcbf

+22 -9
+3 -3
include/linux/huge_mm.h
··· 372 372 int __split_huge_page_to_list_to_order(struct page *page, struct list_head *list, 373 373 unsigned int new_order); 374 374 int folio_split_unmapped(struct folio *folio, unsigned int new_order); 375 - int min_order_for_split(struct folio *folio); 375 + unsigned int min_order_for_split(struct folio *folio); 376 376 int split_folio_to_list(struct folio *folio, struct list_head *list); 377 377 int folio_check_splittable(struct folio *folio, unsigned int new_order, 378 378 enum split_type split_type); ··· 630 630 return -EINVAL; 631 631 } 632 632 633 - static inline int min_order_for_split(struct folio *folio) 633 + static inline unsigned int min_order_for_split(struct folio *folio) 634 634 { 635 635 VM_WARN_ON_ONCE_FOLIO(1, folio); 636 - return -EINVAL; 636 + return 0; 637 637 } 638 638 639 639 static inline int split_folio_to_list(struct folio *folio, struct list_head *list)
+19 -6
mm/huge_memory.c
··· 4219 4219 SPLIT_TYPE_NON_UNIFORM); 4220 4220 } 4221 4221 4222 - int min_order_for_split(struct folio *folio) 4222 + /** 4223 + * min_order_for_split() - get the minimum order @folio can be split to 4224 + * @folio: folio to split 4225 + * 4226 + * min_order_for_split() tells the minimum order @folio can be split to. 4227 + * If a file-backed folio is truncated, 0 will be returned. Any subsequent 4228 + * split attempt should get -EBUSY from split checking code. 4229 + * 4230 + * Return: @folio's minimum order for split 4231 + */ 4232 + unsigned int min_order_for_split(struct folio *folio) 4223 4233 { 4224 4234 if (folio_test_anon(folio)) 4225 4235 return 0; 4226 4236 4227 - if (!folio->mapping) { 4228 - if (folio_test_pmd_mappable(folio)) 4229 - count_vm_event(THP_SPLIT_PAGE_FAILED); 4230 - return -EBUSY; 4231 - } 4237 + /* 4238 + * If the folio got truncated, we don't know the previous mapping and 4239 + * consequently the old min order. But it doesn't matter, as any split 4240 + * attempt will immediately fail with -EBUSY as the folio cannot get 4241 + * split until freed. 4242 + */ 4243 + if (!folio->mapping) 4244 + return 0; 4232 4245 4233 4246 return mapping_min_folio_order(folio->mapping); 4234 4247 }