| /* SPDX-License-Identifier: GPL-2.0 */ |
| #ifndef __MM_COLLAPSE_H |
| #define __MM_COLLAPSE_H |
| |
| #include <linux/mm.h> |
| #include <linux/nodemask.h> |
| #include <linux/pgtable.h> |
| #include <linux/types.h> |
| |
| #define COLLAPSE_MAX_PTES_LIMIT (HPAGE_PMD_NR - 1) |
| #define COLLAPSE_MIN_MTHP_ORDER 2 |
| |
| enum scan_result { |
| SCAN_FAIL, |
| SCAN_SUCCEED, |
| SCAN_NO_PTE_TABLE, |
| SCAN_PMD_MAPPED, |
| SCAN_EXCEED_NONE_PTE, |
| SCAN_EXCEED_SWAP_PTE, |
| SCAN_EXCEED_SHARED_PTE, |
| SCAN_PTE_NON_PRESENT, |
| SCAN_PTE_UFFD, |
| SCAN_PTE_MAPPED_HUGEPAGE, |
| SCAN_LACK_REFERENCED_PAGE, |
| SCAN_PAGE_NULL, |
| SCAN_SCAN_ABORT, |
| SCAN_PAGE_COUNT, |
| SCAN_PAGE_LRU, |
| SCAN_PAGE_LOCK, |
| SCAN_PAGE_ANON, |
| SCAN_PAGE_LAZYFREE, |
| SCAN_PAGE_COMPOUND, |
| SCAN_ANY_PROCESS, |
| SCAN_VMA_NULL, |
| SCAN_VMA_CHECK, |
| SCAN_ADDRESS_RANGE, |
| SCAN_DEL_PAGE_LRU, |
| SCAN_ALLOC_HUGE_PAGE_FAIL, |
| SCAN_CGROUP_CHARGE_FAIL, |
| SCAN_TRUNCATED, |
| SCAN_PAGE_HAS_PRIVATE, |
| SCAN_STORE_FAILED, |
| SCAN_COPY_MC, |
| SCAN_PAGE_FILLED, |
| SCAN_PAGE_DIRTY_OR_WRITEBACK, |
| }; |
| |
| /* How many PTEs of a window may be missing, swapped out or shared */ |
| struct collapse_limits { |
| /* Counted over a PMD-sized window; HPAGE_PMD_NR means "no limit" */ |
| unsigned int max_ptes_none; |
| unsigned int max_ptes_swap; |
| unsigned int max_ptes_shared; |
| }; |
| |
| /* What a collapse is allowed to do, decided by the caller that asks for it */ |
| struct collapse_policy { |
| /* Limits for a PMD-sized window */ |
| struct collapse_limits pmd; |
| |
| /* |
| * Limits for a smaller window. Its max_ptes_none is either 0 or |
| * COLLAPSE_MAX_PTES_LIMIT, the latter meaning all but one PTE of the |
| * window whatever its order; any other value counts as 0. |
| */ |
| struct collapse_limits sub_pmd; |
| |
| /* Leave clean lazyfree folios to reclaim rather than collapse them */ |
| bool anon_skip_lazyfree; |
| |
| /* Refuse an anonymous range with no sign of use */ |
| bool anon_require_referenced; |
| |
| /* Map the PMD over a file collapse instead of leaving it to a fault */ |
| bool file_install_pmd; |
| |
| /* Write dirty pages back and retry once instead of refusing them */ |
| bool file_writeback_dirty; |
| |
| /* How hard to try for a destination folio */ |
| gfp_t gfp; |
| |
| /* Which VMAs are eligible, as thp_vma_allowable_orders() spells it */ |
| enum tva_type tva_type; |
| }; |
| |
| struct collapse_control { |
| struct collapse_policy policy; |
| |
| /* Num pages scanned per node */ |
| u32 node_load[MAX_NUMNODES]; |
| |
| /* Num pages scanned (see khugepaged_pages_to_scan) */ |
| unsigned int progress; |
| |
| /* nodemask for allocation fallback */ |
| nodemask_t alloc_nmask; |
| |
| /* Each bit marks a PTE the scan accepted as a collapse source */ |
| DECLARE_BITMAP(eligible_ptes, MAX_PTRS_PER_PTE); |
| |
| /* |
| * What a scan found and the run after it needs. Live only between the |
| * two, and read by nobody else. |
| * |
| * The file side takes a reference while it still has the VMA, since a |
| * file collapse works on the page cache and never sees one; the run is |
| * what gives it back. |
| */ |
| unsigned long scan_orders; |
| int scan_referenced; |
| int scan_unmapped; |
| struct file *scan_file; |
| pgoff_t scan_pgoff; |
| }; |
| |
| /* Which orders a VMA may collapse to, zero when it may not collapse at all */ |
| unsigned long collapse_possible_orders(struct vm_area_struct *vma, |
| vm_flags_t vm_flags, enum tva_type tva_flags); |
| |
| /* |
| * A caller states what it allows in cc->policy and then hands over one PTE |
| * table's worth of a VMA at a time: |
| * |
| * collapse_control_init(cc) once, before the first table |
| * collapse_scan_pmd(vma, addr, ...) per table |
| * collapse_run_pmd(mm, addr, result, cc) when a scan found work |
| * |
| * The caller holds mmap_lock for reading over the scan and passes an address |
| * within @vma, aligned to the PTE table to scan. |
| * |
| * The scan returns with that lock still held. Almost every table it is |
| * offered has nothing to collapse, so a caller walks a whole VMA under the one |
| * lock it took to get there. SCAN_SUCCEED means there is |
| * something to collapse. SCAN_PTE_MAPPED_HUGEPAGE means the page cache |
| * already holds the PMD folio and only the PTE table is left to retract. |
| * Both are work for the run, which is handed what the scan returned; anything |
| * else is why there is nothing to do. |
| * |
| * The run is called without the lock and returns without it, taking what it |
| * needs in between: what it does -- allocate, isolate, copy, flush -- is slow |
| * enough that a writer would wait behind it. The caller gives the lock up |
| * first, and with it @vma and anything derived under it, so a caller carrying |
| * on has to look up again with collapse_vma_revalidate(). The run revalidates |
| * for itself rather than trusting what the scan saw. |
| * |
| * A scan that found something has to be run: the file side takes a reference on |
| * the file while it still has the VMA to take it from, and the run is what |
| * gives it back. |
| */ |
| void collapse_control_init(struct collapse_control *cc); |
| enum scan_result collapse_scan_pmd(struct vm_area_struct *vma, |
| unsigned long addr, struct collapse_control *cc, |
| unsigned long orders); |
| enum scan_result collapse_run_pmd(struct mm_struct *mm, unsigned long addr, |
| enum scan_result result, struct collapse_control *cc); |
| enum scan_result collapse_vma_revalidate(struct mm_struct *mm, |
| unsigned long address, bool expect_anon, |
| struct vm_area_struct **vmap, struct collapse_control *cc, |
| unsigned int order); |
| |
| #endif /* __MM_COLLAPSE_H */ |