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: fix misused mapping_large_folio_support() for anon folios

When I did a large folios split test, a WARNING "[ 5059.122759][ T166]
Cannot split file folio to non-0 order" was triggered. But the test cases
are only for anonmous folios. while mapping_large_folio_support() is only
reasonable for page cache folios.

In split_huge_page_to_list_to_order(), the folio passed to
mapping_large_folio_support() maybe anonmous folio. The folio_test_anon()
check is missing. So the split of the anonmous THP is failed. This is
also the same for shmem_mapping(). We'd better add a check for both. But
the shmem_mapping() in __split_huge_page() is not involved, as for
anonmous folios, the end parameter is set to -1, so (head[i].index >= end)
is always false. shmem_mapping() is not called.

Also add a VM_WARN_ON_ONCE() in mapping_large_folio_support() for anon
mapping, So we can detect the wrong use more easily.

THP folios maybe exist in the pagecache even the file system doesn't
support large folio, it is because when CONFIG_TRANSPARENT_HUGEPAGE is
enabled, khugepaged will try to collapse read-only file-backed pages to
THP. But the mapping does not actually support multi order large folios
properly.

Using /sys/kernel/debug/split_huge_pages to verify this, with this patch,
large anon THP is successfully split and the warning is ceased.

Link: https://lkml.kernel.org/r/202406071740485174hcFl7jRxncsHDtI-Pz-o@zte.com.cn
Fixes: c010d47f107f ("mm: thp: split huge page to any lower order pages")
Reviewed-by: Barry Song <baohua@kernel.org>
Reviewed-by: Zi Yan <ziy@nvidia.com>
Acked-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Ran Xiaokai <ran.xiaokai@zte.com.cn>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: xu xin <xu.xin16@zte.com.cn>
Cc: Yang Yang <yang.yang29@zte.com.cn>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Ran Xiaokai and committed by
Andrew Morton
6a50c9b5 a273559e

+21 -11
+4
include/linux/pagemap.h
··· 381 381 */ 382 382 static inline bool mapping_large_folio_support(struct address_space *mapping) 383 383 { 384 + /* AS_LARGE_FOLIO_SUPPORT is only reasonable for pagecache folios */ 385 + VM_WARN_ONCE((unsigned long)mapping & PAGE_MAPPING_ANON, 386 + "Anonymous mapping always supports large folio"); 387 + 384 388 return IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && 385 389 test_bit(AS_LARGE_FOLIO_SUPPORT, &mapping->flags); 386 390 }
+17 -11
mm/huge_memory.c
··· 3009 3009 if (new_order >= folio_order(folio)) 3010 3010 return -EINVAL; 3011 3011 3012 - /* Cannot split anonymous THP to order-1 */ 3013 - if (new_order == 1 && folio_test_anon(folio)) { 3014 - VM_WARN_ONCE(1, "Cannot split to order-1 folio"); 3015 - return -EINVAL; 3016 - } 3017 - 3018 - if (new_order) { 3019 - /* Only swapping a whole PMD-mapped folio is supported */ 3020 - if (folio_test_swapcache(folio)) 3012 + if (folio_test_anon(folio)) { 3013 + /* order-1 is not supported for anonymous THP. */ 3014 + if (new_order == 1) { 3015 + VM_WARN_ONCE(1, "Cannot split to order-1 folio"); 3021 3016 return -EINVAL; 3017 + } 3018 + } else if (new_order) { 3022 3019 /* Split shmem folio to non-zero order not supported */ 3023 3020 if (shmem_mapping(folio->mapping)) { 3024 3021 VM_WARN_ONCE(1, 3025 3022 "Cannot split shmem folio to non-0 order"); 3026 3023 return -EINVAL; 3027 3024 } 3028 - /* No split if the file system does not support large folio */ 3029 - if (!mapping_large_folio_support(folio->mapping)) { 3025 + /* 3026 + * No split if the file system does not support large folio. 3027 + * Note that we might still have THPs in such mappings due to 3028 + * CONFIG_READ_ONLY_THP_FOR_FS. But in that case, the mapping 3029 + * does not actually support large folios properly. 3030 + */ 3031 + if (IS_ENABLED(CONFIG_READ_ONLY_THP_FOR_FS) && 3032 + !mapping_large_folio_support(folio->mapping)) { 3030 3033 VM_WARN_ONCE(1, 3031 3034 "Cannot split file folio to non-0 order"); 3032 3035 return -EINVAL; 3033 3036 } 3034 3037 } 3035 3038 3039 + /* Only swapping a whole PMD-mapped folio is supported */ 3040 + if (folio_test_swapcache(folio) && new_order) 3041 + return -EINVAL; 3036 3042 3037 3043 is_hzp = is_huge_zero_folio(folio); 3038 3044 if (is_hzp) {