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: convert "tva_flags" to "enum tva_type"

When determining which THP orders are eligible for a VMA mapping, we have
previously specified tva_flags, however it turns out it is really not
necessary to treat these as flags.

Rather, we distinguish between distinct modes.

The only case where we previously combined flags was with
TVA_ENFORCE_SYSFS, but we can avoid this by observing that this is the
default, except for MADV_COLLAPSE or an edge cases in
collapse_pte_mapped_thp() and hugepage_vma_revalidate(), and adding a mode
specifically for this case - TVA_FORCED_COLLAPSE.

We have:
* smaps handling for showing "THPeligible"
* Pagefault handling
* khugepaged handling
* Forced collapse handling: primarily MADV_COLLAPSE, but also for
an edge case in collapse_pte_mapped_thp()

Disregarding the edge cases, we only want to ignore sysfs settings only
when we are forcing a collapse through MADV_COLLAPSE, otherwise we want to
enforce it, hence this patch does the following flag to enum conversions:

* TVA_SMAPS | TVA_ENFORCE_SYSFS -> TVA_SMAPS
* TVA_IN_PF | TVA_ENFORCE_SYSFS -> TVA_PAGEFAULT
* TVA_ENFORCE_SYSFS -> TVA_KHUGEPAGED
* 0 -> TVA_FORCED_COLLAPSE

With this change, we immediately know if we are in the forced collapse
case, which will be valuable next.

Link: https://lkml.kernel.org/r/20250815135549.130506-3-usamaarif642@gmail.com
Signed-off-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Usama Arif <usamaarif642@gmail.com>
Acked-by: Usama Arif <usamaarif642@gmail.com>
Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Reviewed-by: Zi Yan <ziy@nvidia.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Barry Song <baohua@kernel.org>
Cc: Dev Jain <dev.jain@arm.com>
Cc: Jann Horn <jannh@google.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Liam Howlett <liam.howlett@oracle.com>
Cc: Mariano Pache <npache@redhat.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Rik van Riel <riel@surriel.com>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: SeongJae Park <sj@kernel.org>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Yafang <laoar.shao@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

David Hildenbrand and committed by
Andrew Morton
1f1c0610 9dc21bbd

+38 -35
+2 -2
fs/proc/task_mmu.c
··· 1369 1369 __show_smap(m, &mss, false); 1370 1370 1371 1371 seq_printf(m, "THPeligible: %8u\n", 1372 - !!thp_vma_allowable_orders(vma, vma->vm_flags, 1373 - TVA_SMAPS | TVA_ENFORCE_SYSFS, THP_ORDERS_ALL)); 1372 + !!thp_vma_allowable_orders(vma, vma->vm_flags, TVA_SMAPS, 1373 + THP_ORDERS_ALL)); 1374 1374 1375 1375 if (arch_pkeys_enabled()) 1376 1376 seq_printf(m, "ProtectionKey: %8u\n", vma_pkey(vma));
+18 -12
include/linux/huge_mm.h
··· 94 94 #define THP_ORDERS_ALL \ 95 95 (THP_ORDERS_ALL_ANON | THP_ORDERS_ALL_SPECIAL | THP_ORDERS_ALL_FILE_DEFAULT) 96 96 97 - #define TVA_SMAPS (1 << 0) /* Will be used for procfs */ 98 - #define TVA_IN_PF (1 << 1) /* Page fault handler */ 99 - #define TVA_ENFORCE_SYSFS (1 << 2) /* Obey sysfs configuration */ 97 + enum tva_type { 98 + TVA_SMAPS, /* Exposing "THPeligible:" in smaps. */ 99 + TVA_PAGEFAULT, /* Serving a page fault. */ 100 + TVA_KHUGEPAGED, /* Khugepaged collapse. */ 101 + TVA_FORCED_COLLAPSE, /* Forced collapse (e.g. MADV_COLLAPSE). */ 102 + }; 100 103 101 - #define thp_vma_allowable_order(vma, vm_flags, tva_flags, order) \ 102 - (!!thp_vma_allowable_orders(vma, vm_flags, tva_flags, BIT(order))) 104 + #define thp_vma_allowable_order(vma, vm_flags, type, order) \ 105 + (!!thp_vma_allowable_orders(vma, vm_flags, type, BIT(order))) 103 106 104 107 #define split_folio(f) split_folio_to_list(f, NULL) 105 108 ··· 267 264 268 265 unsigned long __thp_vma_allowable_orders(struct vm_area_struct *vma, 269 266 vm_flags_t vm_flags, 270 - unsigned long tva_flags, 267 + enum tva_type type, 271 268 unsigned long orders); 272 269 273 270 /** 274 271 * thp_vma_allowable_orders - determine hugepage orders that are allowed for vma 275 272 * @vma: the vm area to check 276 273 * @vm_flags: use these vm_flags instead of vma->vm_flags 277 - * @tva_flags: Which TVA flags to honour 274 + * @type: TVA type 278 275 * @orders: bitfield of all orders to consider 279 276 * 280 277 * Calculates the intersection of the requested hugepage orders and the allowed ··· 288 285 static inline 289 286 unsigned long thp_vma_allowable_orders(struct vm_area_struct *vma, 290 287 vm_flags_t vm_flags, 291 - unsigned long tva_flags, 288 + enum tva_type type, 292 289 unsigned long orders) 293 290 { 294 - /* Optimization to check if required orders are enabled early. */ 295 - if ((tva_flags & TVA_ENFORCE_SYSFS) && vma_is_anonymous(vma)) { 291 + /* 292 + * Optimization to check if required orders are enabled early. Only 293 + * forced collapse ignores sysfs configs. 294 + */ 295 + if (type != TVA_FORCED_COLLAPSE && vma_is_anonymous(vma)) { 296 296 unsigned long mask = READ_ONCE(huge_anon_orders_always); 297 297 298 298 if (vm_flags & VM_HUGEPAGE) ··· 309 303 return 0; 310 304 } 311 305 312 - return __thp_vma_allowable_orders(vma, vm_flags, tva_flags, orders); 306 + return __thp_vma_allowable_orders(vma, vm_flags, type, orders); 313 307 } 314 308 315 309 struct thpsize { ··· 553 547 554 548 static inline unsigned long thp_vma_allowable_orders(struct vm_area_struct *vma, 555 549 vm_flags_t vm_flags, 556 - unsigned long tva_flags, 550 + enum tva_type type, 557 551 unsigned long orders) 558 552 { 559 553 return 0;
+4 -4
mm/huge_memory.c
··· 99 99 100 100 unsigned long __thp_vma_allowable_orders(struct vm_area_struct *vma, 101 101 vm_flags_t vm_flags, 102 - unsigned long tva_flags, 102 + enum tva_type type, 103 103 unsigned long orders) 104 104 { 105 - bool smaps = tva_flags & TVA_SMAPS; 106 - bool in_pf = tva_flags & TVA_IN_PF; 107 - bool enforce_sysfs = tva_flags & TVA_ENFORCE_SYSFS; 105 + const bool smaps = type == TVA_SMAPS; 106 + const bool in_pf = type == TVA_PAGEFAULT; 107 + const bool enforce_sysfs = type != TVA_FORCED_COLLAPSE; 108 108 unsigned long supported_orders; 109 109 110 110 /* Check the intersection of requested and supported orders. */
+8 -9
mm/khugepaged.c
··· 474 474 { 475 475 if (!mm_flags_test(MMF_VM_HUGEPAGE, vma->vm_mm) && 476 476 hugepage_pmd_enabled()) { 477 - if (thp_vma_allowable_order(vma, vm_flags, TVA_ENFORCE_SYSFS, 478 - PMD_ORDER)) 477 + if (thp_vma_allowable_order(vma, vm_flags, TVA_KHUGEPAGED, PMD_ORDER)) 479 478 __khugepaged_enter(vma->vm_mm); 480 479 } 481 480 } ··· 920 921 struct collapse_control *cc) 921 922 { 922 923 struct vm_area_struct *vma; 923 - unsigned long tva_flags = cc->is_khugepaged ? TVA_ENFORCE_SYSFS : 0; 924 + enum tva_type type = cc->is_khugepaged ? TVA_KHUGEPAGED : 925 + TVA_FORCED_COLLAPSE; 924 926 925 927 if (unlikely(hpage_collapse_test_exit_or_disable(mm))) 926 928 return SCAN_ANY_PROCESS; ··· 932 932 933 933 if (!thp_vma_suitable_order(vma, address, PMD_ORDER)) 934 934 return SCAN_ADDRESS_RANGE; 935 - if (!thp_vma_allowable_order(vma, vma->vm_flags, tva_flags, PMD_ORDER)) 935 + if (!thp_vma_allowable_order(vma, vma->vm_flags, type, PMD_ORDER)) 936 936 return SCAN_VMA_CHECK; 937 937 /* 938 938 * Anon VMA expected, the address may be unmapped then ··· 1533 1533 * in the page cache with a single hugepage. If a mm were to fault-in 1534 1534 * this memory (mapped by a suitably aligned VMA), we'd get the hugepage 1535 1535 * and map it by a PMD, regardless of sysfs THP settings. As such, let's 1536 - * analogously elide sysfs THP settings here. 1536 + * analogously elide sysfs THP settings here and force collapse. 1537 1537 */ 1538 - if (!thp_vma_allowable_order(vma, vma->vm_flags, 0, PMD_ORDER)) 1538 + if (!thp_vma_allowable_order(vma, vma->vm_flags, TVA_FORCED_COLLAPSE, PMD_ORDER)) 1539 1539 return SCAN_VMA_CHECK; 1540 1540 1541 1541 /* Keep pmd pgtable for uffd-wp; see comment in retract_page_tables() */ ··· 2432 2432 progress++; 2433 2433 break; 2434 2434 } 2435 - if (!thp_vma_allowable_order(vma, vma->vm_flags, 2436 - TVA_ENFORCE_SYSFS, PMD_ORDER)) { 2435 + if (!thp_vma_allowable_order(vma, vma->vm_flags, TVA_KHUGEPAGED, PMD_ORDER)) { 2437 2436 skip: 2438 2437 progress++; 2439 2438 continue; ··· 2766 2767 BUG_ON(vma->vm_start > start); 2767 2768 BUG_ON(vma->vm_end < end); 2768 2769 2769 - if (!thp_vma_allowable_order(vma, vma->vm_flags, 0, PMD_ORDER)) 2770 + if (!thp_vma_allowable_order(vma, vma->vm_flags, TVA_FORCED_COLLAPSE, PMD_ORDER)) 2770 2771 return -EINVAL; 2771 2772 2772 2773 cc = kmalloc(sizeof(*cc), GFP_KERNEL);
+6 -8
mm/memory.c
··· 4515 4515 * Get a list of all the (large) orders below PMD_ORDER that are enabled 4516 4516 * and suitable for swapping THP. 4517 4517 */ 4518 - orders = thp_vma_allowable_orders(vma, vma->vm_flags, 4519 - TVA_IN_PF | TVA_ENFORCE_SYSFS, BIT(PMD_ORDER) - 1); 4518 + orders = thp_vma_allowable_orders(vma, vma->vm_flags, TVA_PAGEFAULT, 4519 + BIT(PMD_ORDER) - 1); 4520 4520 orders = thp_vma_suitable_orders(vma, vmf->address, orders); 4521 4521 orders = thp_swap_suitable_orders(swp_offset(entry), 4522 4522 vmf->address, orders); ··· 5063 5063 * for this vma. Then filter out the orders that can't be allocated over 5064 5064 * the faulting address and still be fully contained in the vma. 5065 5065 */ 5066 - orders = thp_vma_allowable_orders(vma, vma->vm_flags, 5067 - TVA_IN_PF | TVA_ENFORCE_SYSFS, BIT(PMD_ORDER) - 1); 5066 + orders = thp_vma_allowable_orders(vma, vma->vm_flags, TVA_PAGEFAULT, 5067 + BIT(PMD_ORDER) - 1); 5068 5068 orders = thp_vma_suitable_orders(vma, vmf->address, orders); 5069 5069 5070 5070 if (!orders) ··· 6254 6254 return VM_FAULT_OOM; 6255 6255 retry_pud: 6256 6256 if (pud_none(*vmf.pud) && 6257 - thp_vma_allowable_order(vma, vm_flags, 6258 - TVA_IN_PF | TVA_ENFORCE_SYSFS, PUD_ORDER)) { 6257 + thp_vma_allowable_order(vma, vm_flags, TVA_PAGEFAULT, PUD_ORDER)) { 6259 6258 ret = create_huge_pud(&vmf); 6260 6259 if (!(ret & VM_FAULT_FALLBACK)) 6261 6260 return ret; ··· 6288 6289 goto retry_pud; 6289 6290 6290 6291 if (pmd_none(*vmf.pmd) && 6291 - thp_vma_allowable_order(vma, vm_flags, 6292 - TVA_IN_PF | TVA_ENFORCE_SYSFS, PMD_ORDER)) { 6292 + thp_vma_allowable_order(vma, vm_flags, TVA_PAGEFAULT, PMD_ORDER)) { 6293 6293 ret = create_huge_pmd(&vmf); 6294 6294 if (!(ret & VM_FAULT_FALLBACK)) 6295 6295 return ret;