Pull folio updates from Matthew Wilcox: - Rewrite how munlock works to massively reduce the contention on i_mmap_rwsem (Hugh Dickins): https://lore.kernel.org/linux-mm/8e4356d-9622-a7f0-b2c-f116b5f2efea@google.com/ - Sort out the page refcount mess for ZONE_DEVICE pages (Christoph Hellwig): https://lore.kernel.org/linux-mm/20220210072828.2930359-1-hch@lst.de/ - Convert GUP to use folios and make pincount available for order-1 pages. (Matthew Wilcox) - Convert a few more truncation functions to use folios (Matthew Wilcox) - Convert page_vma_mapped_walk to use PFNs instead of pages (Matthew Wilcox) - Convert rmap_walk to use folios (Matthew Wilcox) - Convert most of shrink_page_list() to use a folio (Matthew Wilcox) - Add support for creating large folios in readahead (Matthew Wilcox) * tag 'folio-5.18c' of git://git.infradead.org/users/willy/pagecache: (114 commits) mm/damon: minor cleanup for damon_pa_young selftests/vm/transhuge-stress: Support file-backed PMD folios mm/filemap: Support VM_HUGEPAGE for file mappings mm/readahead: Switch to page_cache_ra_order mm/readahead: Align file mappings for non-DAX mm/readahead: Add large folio readahead mm: Support arbitrary THP sizes mm: Make large folios depend on THP mm: Fix READ_ONLY_THP warning mm/filemap: Allow large folios to be added to the page cache mm: Turn can_split_huge_page() into can_split_folio() mm/vmscan: Convert pageout() to take a folio mm/vmscan: Turn page_check_references() into folio_check_references() mm/vmscan: Account large folios correctly mm/vmscan: Optimise shrink_page_list for non-PMD-sized folios mm/vmscan: Free non-shmem folios without splitting them mm/rmap: Constify the rmap_walk_control argument mm/rmap: Convert rmap_walk() to take a folio mm: Turn page_anon_vma() into folio_anon_vma() mm/rmap: Turn page_lock_anon_vma_read() into folio_lock_anon_vma_read() ...
Unified · Split
| @@ -55,18 +55,18 @@ flags the caller provides. The caller is required to pass in a non-null struct · 54 unmodified lines | ||
| 55 | 55 | pages* array, and the function then pins pages by incrementing each by a special |
| 56 | 56 | value: GUP_PIN_COUNTING_BIAS. |
| 57 | 57 | |
| 58 | −For huge pages (and in fact, any compound page of more than 2 pages), the | |
| 59 | −GUP_PIN_COUNTING_BIAS scheme is not used. Instead, an exact form of pin counting | |
| 60 | −is achieved, by using the 3rd struct page in the compound page. A new struct | |
| 61 | −page field, hpage_pinned_refcount, has been added in order to support this. | |
| 58 | +For compound pages, the GUP_PIN_COUNTING_BIAS scheme is not used. Instead, | |
| 59 | +an exact form of pin counting is achieved, by using the 2nd struct page | |
| 60 | +in the compound page. A new struct page field, compound_pincount, has | |
| 61 | +been added in order to support this. | |
| 62 | 62 | |
| 63 | 63 | This approach for compound pages avoids the counting upper limit problems that |
| 64 | 64 | are discussed below. Those limitations would have been aggravated severely by |
| 65 | 65 | huge pages, because each tail page adds a refcount to the head page. And in |
| 66 | −fact, testing revealed that, without a separate hpage_pinned_refcount field, | |
| 66 | +fact, testing revealed that, without a separate compound_pincount field, | |
| 67 | 67 | page overflows were seen in some huge page stress tests. |
| 68 | 68 | |
| 69 | −This also means that huge pages and compound pages (of order > 1) do not suffer | |
| 69 | +This also means that huge pages and compound pages do not suffer | |
| 70 | 70 | from the false positives problem that is mentioned below.:: |
| 71 | 71 | |
| 72 | 72 | Function |
| @@ -264,9 +264,9 @@ place.) · 191 unmodified lines | ||
| 264 | 264 | Other diagnostics |
| 265 | 265 | ================= |
| 266 | 266 | |
| 267 | −dump_page() has been enhanced slightly, to handle these new counting fields, and | |
| 268 | −to better report on compound pages in general. Specifically, for compound pages | |
| 269 | −with order > 1, the exact (hpage_pinned_refcount) pincount is reported. | |
| 267 | +dump_page() has been enhanced slightly, to handle these new counting | |
| 268 | +fields, and to better report on compound pages in general. Specifically, | |
| 269 | +for compound pages, the exact (compound_pincount) pincount is reported. | |
| 270 | 270 | |
| 271 | 271 | References |
| 272 | 272 | ========== |
| @@ -233,6 +233,7 @@ pmd_page_vaddr(pmd_t pmd) · 232 unmodified lines | ||
| 233 | 233 | return ((pmd_val(pmd) & _PFN_MASK) >> (32-PAGE_SHIFT)) + PAGE_OFFSET; |
| 234 | 234 | } |
| 235 | 235 | |
| 236 | +#define pmd_pfn(pmd) (pmd_val(pmd) >> 32) | |
| 236 | 237 | #define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> 32)) |
| 237 | 238 | #define pud_page(pud) (pfn_to_page(pud_val(pud) >> 32)) |
| 238 | 239 | |
| @@ -31,7 +31,6 @@ static inline pmd_t pte_pmd(pte_t pte) · 30 unmodified lines | ||
| 31 | 31 | |
| 32 | 32 | #define pmd_write(pmd) pte_write(pmd_pte(pmd)) |
| 33 | 33 | #define pmd_young(pmd) pte_young(pmd_pte(pmd)) |
| 34 | −#define pmd_pfn(pmd) pte_pfn(pmd_pte(pmd)) | |
| 35 | 34 | #define pmd_dirty(pmd) pte_dirty(pmd_pte(pmd)) |
| 36 | 35 | |
| 37 | 36 | #define mk_pmd(page, prot) pte_pmd(mk_pte(page, prot)) |
| @@ -161,6 +161,7 @@ · 160 unmodified lines | ||
| 161 | 161 | #define pmd_present(x) (pmd_val(x)) |
| 162 | 162 | #define pmd_clear(xp) do { pmd_val(*(xp)) = 0; } while (0) |
| 163 | 163 | #define pmd_page_vaddr(pmd) (pmd_val(pmd) & PAGE_MASK) |
| 164 | +#define pmd_pfn(pmd) ((pmd_val(pmd) & PAGE_MASK) >> PAGE_SHIFT) | |
| 164 | 165 | #define pmd_page(pmd) virt_to_page(pmd_page_vaddr(pmd)) |
| 165 | 166 | #define set_pmd(pmdp, pmd) (*(pmdp) = pmd) |
| 166 | 167 | #define pmd_pgtable(pmd) ((pgtable_t) pmd_page_vaddr(pmd)) |
| @@ -208,6 +208,8 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) · 207 unmodified lines | ||
| 208 | 208 | } |
| 209 | 209 | #define pmd_offset pmd_offset |
| 210 | 210 | |
| 211 | +#define pmd_pfn(pmd) (__phys_to_pfn(pmd_val(pmd) & PHYS_MASK)) | |
| 212 | + | |
| 211 | 213 | #define pmd_large(pmd) (pmd_val(pmd) & 2) |
| 212 | 214 | #define pmd_leaf(pmd) (pmd_val(pmd) & 2) |
| 213 | 215 | #define pmd_bad(pmd) (pmd_val(pmd) & 2) |
| @@ -17,6 +17,7 @@ · 16 unmodified lines | ||
| 17 | 17 | #include <linux/mman.h> |
| 18 | 18 | #include <linux/nodemask.h> |
| 19 | 19 | #include <linux/memblock.h> |
| 20 | +#include <linux/memremap.h> | |
| 20 | 21 | #include <linux/memory.h> |
| 21 | 22 | #include <linux/fs.h> |
| 22 | 23 | #include <linux/io.h> |
| @@ -30,6 +30,7 @@ · 29 unmodified lines | ||
| 30 | 30 | #define pgd_ERROR(e) \ |
| 31 | 31 | pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) |
| 32 | 32 | |
| 33 | +#define pmd_pfn(pmd) (pmd_phys(pmd) >> PAGE_SHIFT) | |
| 33 | 34 | #define pmd_page(pmd) (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT)) |
| 34 | 35 | #define pte_clear(mm, addr, ptep) set_pte((ptep), \ |
| 35 | 36 | (((unsigned int) addr >= PAGE_OFFSET) ? __pte(_PAGE_GLOBAL) : __pte(0))) |
| @@ -235,6 +235,11 @@ static inline int pmd_bad(pmd_t pmd) · 234 unmodified lines | ||
| 235 | 235 | return 0; |
| 236 | 236 | } |
| 237 | 237 | |
| 238 | +/* | |
| 239 | + * pmd_pfn - converts a PMD entry to a page frame number | |
| 240 | + */ | |
| 241 | +#define pmd_pfn(pmd) (pmd_val(pmd) >> PAGE_SHIFT) | |
| 242 | + | |
| 238 | 243 | /* |
| 239 | 244 | * pmd_page - converts a PMD entry to a page pointer |
| 240 | 245 | */ |
| @@ -267,6 +267,7 @@ ia64_phys_addr_valid (unsigned long addr) · 266 unmodified lines | ||
| 267 | 267 | #define pmd_present(pmd) (pmd_val(pmd) != 0UL) |
| 268 | 268 | #define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0UL) |
| 269 | 269 | #define pmd_page_vaddr(pmd) ((unsigned long) __va(pmd_val(pmd) & _PFN_MASK)) |
| 270 | +#define pmd_pfn(pmd) ((pmd_val(pmd) & _PFN_MASK) >> PAGE_SHIFT) | |
| 270 | 271 | #define pmd_page(pmd) virt_to_page((pmd_val(pmd) + PAGE_OFFSET)) |
| 271 | 272 | |
| 272 | 273 | #define pud_none(pud) (!pud_val(pud)) |
| @@ -322,6 +322,7 @@ extern pgd_t kernel_pg_dir[PTRS_PER_PGD]; · 321 unmodified lines | ||
| 322 | 322 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) |
| 323 | 323 | #define __swp_entry_to_pte(x) (__pte((x).val)) |
| 324 | 324 | |
| 325 | +#define pmd_pfn(pmd) (pmd_val(pmd) >> PAGE_SHIFT) | |
| 325 | 326 | #define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)) |
| 326 | 327 | |
| 327 | 328 | #define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) |
| @@ -147,6 +147,7 @@ static inline void pud_set(pud_t *pudp, pmd_t *pmdp) · 146 unmodified lines | ||
| 147 | 147 | #define pmd_present(pmd) (pmd_val(pmd) & _PAGE_TABLE) |
| 148 | 148 | #define pmd_clear(pmdp) ({ pmd_val(*pmdp) = 0; }) |
| 149 | 149 | |
| 150 | +#define pmd_pfn(pmd) ((pmd_val(pmd) & _TABLE_MASK) >> PAGE_SHIFT) | |
| 150 | 151 | /* |
| 151 | 152 | * m68k does not have huge pages (020/030 actually could), but generic code |
| 152 | 153 | * expects pmd_page() to exists, only to then DCE it all. Provide a dummy to |
| @@ -130,6 +130,7 @@ static inline void pte_clear (struct mm_struct *mm, unsigned long addr, pte_t *p · 129 unmodified lines | ||
| 130 | 130 | ({ pte_t __pte; pte_val(__pte) = pfn | pgprot_val(pgprot); __pte; }) |
| 131 | 131 | |
| 132 | 132 | #define pte_page(pte) virt_to_page(__pte_page(pte)) |
| 133 | +#define pmd_pfn(pmd) (pmd_val(pmd) >> PAGE_SHIFT) | |
| 133 | 134 | #define pmd_page(pmd) virt_to_page(pmd_page_vaddr(pmd)) |
| 134 | 135 | |
| 135 | 136 | |
| @@ -399,6 +399,9 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd) · 398 unmodified lines | ||
| 399 | 399 | return ((unsigned long) (pmd_val(pmd) & PAGE_MASK)); |
| 400 | 400 | } |
| 401 | 401 | |
| 402 | +/* returns pfn of the pmd entry*/ | |
| 403 | +#define pmd_pfn(pmd) (__pa(pmd_val(pmd)) >> PAGE_SHIFT) | |
| 404 | + | |
| 402 | 405 | /* returns struct *page of the pmd entry*/ |
| 403 | 406 | #define pmd_page(pmd) (pfn_to_page(__pa(pmd_val(pmd)) >> PAGE_SHIFT)) |
| 404 | 407 | |
| @@ -86,6 +86,11 @@ extern void paging_init(void); · 85 unmodified lines | ||
| 86 | 86 | */ |
| 87 | 87 | #define pmd_phys(pmd) virt_to_phys((void *)pmd_val(pmd)) |
| 88 | 88 | |
| 89 | +static inline unsigned long pmd_pfn(pmd_t pmd) | |
| 90 | +{ | |
| 91 | + return pmd_val(pmd) >> _PFN_SHIFT; | |
| 92 | +} | |
| 93 | + | |
| 89 | 94 | #ifndef CONFIG_MIPS_HUGE_TLB_SUPPORT |
| 90 | 95 | #define pmd_page(pmd) (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT)) |
| 91 | 96 | #endif /* CONFIG_MIPS_HUGE_TLB_SUPPORT */ |
| @@ -422,11 +427,6 @@ static inline int pmd_write(pmd_t pmd) · 330 unmodified lines | ||
| 422 | 427 | return !!(pmd_val(pmd) & _PAGE_WRITE); |
| 423 | 428 | } |
| 424 | 429 | |
| 425 | −static inline unsigned long pmd_pfn(pmd_t pmd) | |
| 426 | −{ | |
| 427 | − return pmd_val(pmd) >> _PFN_SHIFT; | |
| 428 | −} | |
| 429 | − | |
| 430 | 430 | static inline struct page *pmd_page(pmd_t pmd) |
| 431 | 431 | { |
| 432 | 432 | if (pmd_val(pmd) & _PAGE_HUGE) |
| @@ -308,6 +308,7 @@ static inline pmd_t __mk_pmd(pte_t * ptep, unsigned long prot) · 307 unmodified lines | ||
| 308 | 308 | return pmd; |
| 309 | 309 | } |
| 310 | 310 | |
| 311 | +#define pmd_pfn(pmd) (pmd_val(pmd) >> PAGE_SHIFT) | |
| 311 | 312 | #define pmd_page(pmd) virt_to_page(__va(pmd_val(pmd))) |
| 312 | 313 | |
| 313 | 314 | /* |
| @@ -235,6 +235,7 @@ static inline void pte_clear(struct mm_struct *mm, · 234 unmodified lines | ||
| 235 | 235 | * and a page entry and page directory to the page they refer to. |
| 236 | 236 | */ |
| 237 | 237 | #define pmd_phys(pmd) virt_to_phys((void *)pmd_val(pmd)) |
| 238 | +#define pmd_pfn(pmd) (pmd_phys(pmd) >> PAGE_SHIFT) | |
| 238 | 239 | #define pmd_page(pmd) (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT)) |
| 239 | 240 | |
| 240 | 241 | static inline unsigned long pmd_page_vaddr(pmd_t pmd) |
| @@ -361,6 +361,7 @@ static inline void pmd_set(pmd_t *pmdp, pte_t *ptep) · 360 unmodified lines | ||
| 361 | 361 | pmd_val(*pmdp) = _KERNPG_TABLE | (unsigned long) ptep; |
| 362 | 362 | } |
| 363 | 363 | |
| 364 | +#define pmd_pfn(pmd) (pmd_val(pmd) >> PAGE_SHIFT) | |
| 364 | 365 | #define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)) |
| 365 | 366 | |
| 366 | 367 | static inline unsigned long pmd_page_vaddr(pmd_t pmd) |
| @@ -408,6 +408,7 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd) · 407 unmodified lines | ||
| 408 | 408 | return ((unsigned long) __va(pmd_address(pmd))); |
| 409 | 409 | } |
| 410 | 410 | |
| 411 | +#define pmd_pfn(pmd) (pmd_address(pmd) >> PAGE_SHIFT) | |
| 411 | 412 | #define __pmd_page(pmd) ((unsigned long) __va(pmd_address(pmd))) |
| 412 | 413 | #define pmd_page(pmd) virt_to_page((void *)__pmd_page(pmd)) |
| 413 | 414 | |
| @@ -372,8 +372,8 @@ static inline void __ptep_set_access_flags(struct vm_area_struct *vma, · 371 unmodified lines | ||
| 372 | 372 | #define __HAVE_ARCH_PTE_SAME |
| 373 | 373 | #define pte_same(A,B) (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HASHPTE) == 0) |
| 374 | 374 | |
| 375 | −#define pmd_page(pmd) \ | |
| 376 | − pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT) | |
| 375 | +#define pmd_pfn(pmd) (pmd_val(pmd) >> PAGE_SHIFT) | |
| 376 | +#define pmd_page(pmd) pfn_to_page(pmd_pfn(pmd)) | |
| 377 | 377 | |
| 378 | 378 | /* |
| 379 | 379 | * Encode and decode a swap entry. |
| @@ -21,7 +21,6 @@ extern void destroy_context(struct mm_struct *mm); · 20 unmodified lines | ||
| 21 | 21 | #ifdef CONFIG_SPAPR_TCE_IOMMU |
| 22 | 22 | struct mm_iommu_table_group_mem_t; |
| 23 | 23 | |
| 24 | −extern int isolate_lru_page(struct page *page); /* from internal.h */ | |
| 25 | 24 | extern bool mm_iommu_preregistered(struct mm_struct *mm); |
| 26 | 25 | extern long mm_iommu_new(struct mm_struct *mm, |
| 27 | 26 | unsigned long ua, unsigned long entries, |
| @@ -349,15 +349,14 @@ static inline int pte_young(pte_t pte) · 348 unmodified lines | ||
| 349 | 349 | * of the pte page. -- paulus |
| 350 | 350 | */ |
| 351 | 351 | #ifndef CONFIG_BOOKE |
| 352 | −#define pmd_page(pmd) \ | |
| 353 | − pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT) | |
| 352 | +#define pmd_pfn(pmd) (pmd_val(pmd) >> PAGE_SHIFT) | |
| 354 | 353 | #else |
| 355 | 354 | #define pmd_page_vaddr(pmd) \ |
| 356 | 355 | ((unsigned long)(pmd_val(pmd) & ~(PTE_TABLE_SIZE - 1))) |
| 357 | −#define pmd_page(pmd) \ | |
| 358 | − pfn_to_page((__pa(pmd_val(pmd)) >> PAGE_SHIFT)) | |
| 356 | +#define pmd_pfn(pmd) (__pa(pmd_val(pmd)) >> PAGE_SHIFT) | |
| 359 | 357 | #endif |
| 360 | 358 | |
| 359 | +#define pmd_page(pmd) pfn_to_page(pmd_pfn(pmd)) | |
| 361 | 360 | /* |
| 362 | 361 | * Encode and decode a swap entry. |
| 363 | 362 | * Note that the bits we use in a PTE for representing a swap entry |
| @@ -142,6 +142,7 @@ static inline pte_t pmd_pte(pmd_t pmd) · 141 unmodified lines | ||
| 142 | 142 | #define pmd_present(pmd) (!pmd_none(pmd)) |
| 143 | 143 | #define pmd_page_vaddr(pmd) (pmd_val(pmd) & ~PMD_MASKED_BITS) |
| 144 | 144 | extern struct page *pmd_page(pmd_t pmd); |
| 145 | +#define pmd_pfn(pmd) (page_to_pfn(pmd_page(pmd))) | |
| 145 | 146 | |
| 146 | 147 | static inline void pud_set(pud_t *pudp, unsigned long val) |
| 147 | 148 | { |
| @@ -91,6 +91,7 @@ · 90 unmodified lines | ||
| 91 | 91 | #include <linux/kvm_host.h> |
| 92 | 92 | #include <linux/ksm.h> |
| 93 | 93 | #include <linux/of.h> |
| 94 | +#include <linux/memremap.h> | |
| 94 | 95 | #include <asm/ultravisor.h> |
| 95 | 96 | #include <asm/mman.h> |
| 96 | 97 | #include <asm/kvm_ppc.h> |
| @@ -712,7 +713,6 @@ static struct page *kvmppc_uvmem_get_page(unsigned long gpa, struct kvm *kvm) · 615 unmodified lines | ||
| 712 | 713 | |
| 713 | 714 | dpage = pfn_to_page(uvmem_pfn); |
| 714 | 715 | dpage->zone_device_data = pvt; |
| 715 | − get_page(dpage); | |
| 716 | 716 | lock_page(dpage); |
| 717 | 717 | return dpage; |
| 718 | 718 | out_clear: |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | #include <linux/sched.h> |
| 7 | 7 | #include <linux/mm_types.h> |
| 8 | 8 | #include <linux/memblock.h> |
| 9 | +#include <linux/memremap.h> | |
| 9 | 10 | #include <linux/debugfs.h> |
| 10 | 11 | #include <misc/cxl-base.h> |
| 11 | 12 | |
| @@ -406,6 +406,7 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd) · 405 unmodified lines | ||
| 406 | 406 | return (unsigned long)pmd_val(pmd); |
| 407 | 407 | } |
| 408 | 408 | |
| 409 | +#define pmd_pfn(pmd) (__pa(pmd_val(pmd)) >> PAGE_SHIFT) | |
| 409 | 410 | #define pmd_page(pmd) (virt_to_page(pmd_val(pmd))) |
| 410 | 411 | |
| 411 | 412 | #ifdef CONFIG_X2TLB |
| @@ -127,11 +127,16 @@ static inline int srmmu_device_memory(unsigned long x) · 126 unmodified lines | ||
| 127 | 127 | return ((x & 0xF0000000) != 0); |
| 128 | 128 | } |
| 129 | 129 | |
| 130 | +static inline unsigned long pmd_pfn(pmd_t pmd) | |
| 131 | +{ | |
| 132 | + return (pmd_val(pmd) & SRMMU_PTD_PMASK) >> (PAGE_SHIFT-4); | |
| 133 | +} | |
| 134 | + | |
| 130 | 135 | static inline struct page *pmd_page(pmd_t pmd) |
| 131 | 136 | { |
| 132 | 137 | if (srmmu_device_memory(pmd_val(pmd))) |
| 133 | 138 | BUG(); |
| 134 | − return pfn_to_page((pmd_val(pmd) & SRMMU_PTD_PMASK) >> (PAGE_SHIFT-4)); | |
| 139 | + return pfn_to_page(pmd_pfn(pmd)); | |
| 135 | 140 | } |
| 136 | 141 | |
| 137 | 142 | static inline unsigned long __pmd_page(pmd_t pmd) |
| @@ -109,6 +109,7 @@ extern unsigned long end_iomem; · 108 unmodified lines | ||
| 109 | 109 | #define p4d_newpage(x) (p4d_val(x) & _PAGE_NEWPAGE) |
| 110 | 110 | #define p4d_mkuptodate(x) (p4d_val(x) &= ~_PAGE_NEWPAGE) |
| 111 | 111 | |
| 112 | +#define pmd_pfn(pmd) (pmd_val(pmd) >> PAGE_SHIFT) | |
| 112 | 113 | #define pmd_page(pmd) phys_to_page(pmd_val(pmd) & PAGE_MASK) |
| 113 | 114 | |
| 114 | 115 | #define pte_page(x) pfn_to_page(pte_pfn(x)) |
| @@ -241,6 +241,7 @@ static inline void paging_init(void) { } · 240 unmodified lines | ||
| 241 | 241 | * The pmd contains the kernel virtual address of the pte page. |
| 242 | 242 | */ |
| 243 | 243 | #define pmd_page_vaddr(pmd) ((unsigned long)(pmd_val(pmd) & PAGE_MASK)) |
| 244 | +#define pmd_pfn(pmd) (__pa(pmd_val(pmd)) >> PAGE_SHIFT) | |
| 244 | 245 | #define pmd_page(pmd) virt_to_page(pmd_val(pmd)) |
| 245 | 246 | |
| 246 | 247 | /* |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | |
| 11 | 11 | #include <linux/module.h> |
| 12 | 12 | #include <linux/kthread.h> |
| 13 | +#include <linux/pagemap.h> | |
| 13 | 14 | #include <xen/events.h> |
| 14 | 15 | #include <xen/grant_table.h> |
| 15 | 16 | #include "common.h" |
| @@ -24,6 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | #include <linux/hmm.h> |
| 25 | 25 | #include <linux/dma-direction.h> |
| 26 | 26 | #include <linux/dma-mapping.h> |
| 27 | +#include <linux/migrate.h> | |
| 27 | 28 | #include "amdgpu_sync.h" |
| 28 | 29 | #include "amdgpu_object.h" |
| 29 | 30 | #include "amdgpu_vm.h" |
| @@ -224,7 +225,6 @@ svm_migrate_get_vram_page(struct svm_range *prange, unsigned long pfn) · 194 unmodified lines | ||
| 224 | 225 | page = pfn_to_page(pfn); |
| 225 | 226 | svm_range_bo_ref(prange->svm_bo); |
| 226 | 227 | page->zone_device_data = prange->svm_bo; |
| 227 | − get_page(page); | |
| 228 | 228 | lock_page(page); |
| 229 | 229 | } |
| 230 | 230 | |
| @@ -25,6 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | |
| 26 | 26 | #include <linux/hashtable.h> |
| 27 | 27 | #include <linux/mmu_notifier.h> |
| 28 | +#include <linux/memremap.h> | |
| 28 | 29 | #include <linux/mutex.h> |
| 29 | 30 | #include <linux/types.h> |
| 30 | 31 | #include <linux/atomic.h> |
| @@ -27,11 +27,11 @@ · 26 unmodified lines | ||
| 27 | 27 | /* |
| 28 | 28 | * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> |
| 29 | 29 | */ |
| 30 | − | |
| 31 | 30 | #include <linux/dma-buf-map.h> |
| 32 | 31 | #include <linux/export.h> |
| 33 | 32 | #include <linux/highmem.h> |
| 34 | 33 | #include <linux/cc_platform.h> |
| 34 | +#include <linux/ioport.h> | |
| 35 | 35 | #include <xen/xen.h> |
| 36 | 36 | |
| 37 | 37 | #include <drm/drm_cache.h> |
| @@ -39,6 +39,8 @@ · 38 unmodified lines | ||
| 39 | 39 | |
| 40 | 40 | #include <linux/sched/mm.h> |
| 41 | 41 | #include <linux/hmm.h> |
| 42 | +#include <linux/memremap.h> | |
| 43 | +#include <linux/migrate.h> | |
| 42 | 44 | |
| 43 | 45 | /* |
| 44 | 46 | * FIXME: this is ugly right now we are using TTM to allocate vram and we pin |
| @@ -324,7 +326,6 @@ nouveau_dmem_page_alloc_locked(struct nouveau_drm *drm) · 279 unmodified lines | ||
| 324 | 326 | return NULL; |
| 325 | 327 | } |
| 326 | 328 | |
| 327 | − get_page(page); | |
| 328 | 329 | lock_page(page); |
| 329 | 330 | return page; |
| 330 | 331 | } |
| @@ -35,6 +35,7 @@ · 34 unmodified lines | ||
| 35 | 35 | #include <linux/sched/mm.h> |
| 36 | 36 | #include <linux/sort.h> |
| 37 | 37 | #include <linux/hmm.h> |
| 38 | +#include <linux/memremap.h> | |
| 38 | 39 | #include <linux/rmap.h> |
| 39 | 40 | |
| 40 | 41 | struct nouveau_svm { |
| @@ -2,6 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | /* |
| 3 | 3 | * Copyright (c) 2016 HGST, a Western Digital Company. |
| 4 | 4 | */ |
| 5 | +#include <linux/memremap.h> | |
| 5 | 6 | #include <linux/moduleparam.h> |
| 6 | 7 | #include <linux/slab.h> |
| 7 | 8 | #include <linux/pci-p2pdma.h> |
| @@ -3,6 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | #define __NVDIMM_PMEM_H__ |
| 4 | 4 | #include <linux/page-flags.h> |
| 5 | 5 | #include <linux/badblocks.h> |
| 6 | +#include <linux/memremap.h> | |
| 6 | 7 | #include <linux/types.h> |
| 7 | 8 | #include <linux/pfn_t.h> |
| 8 | 9 | #include <linux/fs.h> |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <linux/init.h> |
| 16 | 16 | #include <linux/interrupt.h> |
| 17 | 17 | #include <linux/io.h> |
| 18 | +#include <linux/memremap.h> | |
| 18 | 19 | #include <linux/mm.h> |
| 19 | 20 | #include <linux/module.h> |
| 20 | 21 | #include <linux/mutex.h> |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
| 7 | 7 | #include <linux/blkdev.h> |
| 8 | 8 | #include <linux/blk-integrity.h> |
| 9 | +#include <linux/memremap.h> | |
| 9 | 10 | #include <linux/module.h> |
| 10 | 11 | #include "nvmet.h" |
| 11 | 12 | |
| @@ -179,6 +179,7 @@ · 178 unmodified lines | ||
| 179 | 179 | #include <linux/kthread.h> |
| 180 | 180 | #include <linux/sched/signal.h> |
| 181 | 181 | #include <linux/limits.h> |
| 182 | +#include <linux/pagemap.h> | |
| 182 | 183 | #include <linux/rwsem.h> |
| 183 | 184 | #include <linux/slab.h> |
| 184 | 185 | #include <linux/spinlock.h> |
| @@ -48,7 +48,7 @@ config FS_DAX · 47 unmodified lines | ||
| 48 | 48 | bool "File system based Direct Access (DAX) support" |
| 49 | 49 | depends on MMU |
| 50 | 50 | depends on !(ARM || MIPS || SPARC) |
| 51 | − select DEV_PAGEMAP_OPS if (ZONE_DEVICE && !FS_DAX_LIMITED) | |
| 51 | + depends on ZONE_DEVICE || FS_DAX_LIMITED | |
| 52 | 52 | select FS_IOMAP |
| 53 | 53 | select DAX |
| 54 | 54 | help |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/time.h> |
| 15 | 15 | #include <linux/file.h> |
| 16 | 16 | #include <linux/fs.h> |
| 17 | +#include <linux/pagemap.h> | |
| 17 | 18 | #include <linux/stat.h> |
| 18 | 19 | #include <linux/cred.h> |
| 19 | 20 | #include <linux/errno.h> |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | #include <linux/dax.h> |
| 9 | 9 | #include <linux/pci.h> |
| 10 | 10 | #include <linux/pfn_t.h> |
| 11 | +#include <linux/memremap.h> | |
| 11 | 12 | #include <linux/module.h> |
| 12 | 13 | #include <linux/virtio.h> |
| 13 | 14 | #include <linux/virtio_fs.h> |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <linux/fs.h> |
| 8 | 8 | #include <linux/iomap.h> |
| 9 | 9 | #include <linux/fiemap.h> |
| 10 | +#include <linux/pagemap.h> | |
| 10 | 11 | |
| 11 | 12 | static int iomap_to_fiemap(struct fiemap_extent_info *fi, |
| 12 | 13 | const struct iomap *iomap, u32 flags) |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <linux/hash.h> |
| 8 | 8 | #include <linux/slab.h> |
| 9 | 9 | #include <linux/file.h> |
| 10 | +#include <linux/pagemap.h> | |
| 10 | 11 | #include <linux/sched.h> |
| 11 | 12 | #include <linux/list_lru.h> |
| 12 | 13 | #include <linux/fsnotify_backend.h> |
| @@ -26,6 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | #include <linux/xattr.h> |
| 27 | 27 | #include <linux/jhash.h> |
| 28 | 28 | #include <linux/ima.h> |
| 29 | +#include <linux/pagemap.h> | |
| 29 | 30 | #include <linux/slab.h> |
| 30 | 31 | #include <linux/uaccess.h> |
| 31 | 32 | #include <linux/exportfs.h> |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | #include <linux/proc_fs.h> |
| 11 | 11 | #include <linux/seq_file.h> |
| 12 | 12 | #include <linux/hugetlb.h> |
| 13 | +#include <linux/memremap.h> | |
| 13 | 14 | #include <linux/memcontrol.h> |
| 14 | 15 | #include <linux/mmu_notifier.h> |
| 15 | 16 | #include <linux/page_idle.h> |
| @@ -46,45 +46,45 @@ · 45 unmodified lines | ||
| 46 | 46 | static bool page_cache_pipe_buf_try_steal(struct pipe_inode_info *pipe, |
| 47 | 47 | struct pipe_buffer *buf) |
| 48 | 48 | { |
| 49 | − struct page *page = buf->page; | |
| 49 | + struct folio *folio = page_folio(buf->page); | |
| 50 | 50 | struct address_space *mapping; |
| 51 | 51 | |
| 52 | − lock_page(page); | |
| 52 | + folio_lock(folio); | |
| 53 | 53 | |
| 54 | − mapping = page_mapping(page); | |
| 54 | + mapping = folio_mapping(folio); | |
| 55 | 55 | if (mapping) { |
| 56 | − WARN_ON(!PageUptodate(page)); | |
| 56 | + WARN_ON(!folio_test_uptodate(folio)); | |
| 57 | 57 | |
| 58 | 58 | /* |
| 59 | 59 | * At least for ext2 with nobh option, we need to wait on |
| 60 | − * writeback completing on this page, since we'll remove it | |
| 60 | + * writeback completing on this folio, since we'll remove it | |
| 61 | 61 | * from the pagecache. Otherwise truncate wont wait on the |
| 62 | − * page, allowing the disk blocks to be reused by someone else | |
| 62 | + * folio, allowing the disk blocks to be reused by someone else | |
| 63 | 63 | * before we actually wrote our data to them. fs corruption |
| 64 | 64 | * ensues. |
| 65 | 65 | */ |
| 66 | − wait_on_page_writeback(page); | |
| 66 | + folio_wait_writeback(folio); | |
| 67 | 67 | |
| 68 | − if (page_has_private(page) && | |
| 69 | − !try_to_release_page(page, GFP_KERNEL)) | |
| 68 | + if (folio_has_private(folio) && | |
| 69 | + !filemap_release_folio(folio, GFP_KERNEL)) | |
| 70 | 70 | goto out_unlock; |
| 71 | 71 | |
| 72 | 72 | /* |
| 73 | 73 | * If we succeeded in removing the mapping, set LRU flag |
| 74 | 74 | * and return good. |
| 75 | 75 | */ |
| 76 | − if (remove_mapping(mapping, page)) { | |
| 76 | + if (remove_mapping(mapping, folio)) { | |
| 77 | 77 | buf->flags |= PIPE_BUF_FLAG_LRU; |
| 78 | 78 | return true; |
| 79 | 79 | } |
| 80 | 80 | } |
| 81 | 81 | |
| 82 | 82 | /* |
| 83 | − * Raced with truncate or failed to remove page from current | |
| 83 | + * Raced with truncate or failed to remove folio from current | |
| 84 | 84 | * address space, unlock and return failure. |
| 85 | 85 | */ |
| 86 | 86 | out_unlock: |
| 87 | − unlock_page(page); | |
| 87 | + folio_unlock(folio); | |
| 88 | 88 | return false; |
| 89 | 89 | } |
| 90 | 90 | |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #include <linux/namei.h> |
| 10 | 10 | #include <linux/nls.h> |
| 11 | 11 | #include <linux/sizes.h> |
| 12 | +#include <linux/pagemap.h> | |
| 12 | 13 | #include <linux/vfs.h> |
| 13 | 14 | #include "vfsmod.h" |
| 14 | 15 | |
| @@ -2753,54 +2753,6 @@ extern void init_special_inode(struct inode *, umode_t, dev_t); · 2752 unmodified lines | ||
| 2753 | 2753 | extern void make_bad_inode(struct inode *); |
| 2754 | 2754 | extern bool is_bad_inode(struct inode *); |
| 2755 | 2755 | |
| 2756 | −unsigned long invalidate_mapping_pages(struct address_space *mapping, | |
| 2757 | − pgoff_t start, pgoff_t end); | |
| 2758 | − | |
| 2759 | −void invalidate_mapping_pagevec(struct address_space *mapping, | |
| 2760 | − pgoff_t start, pgoff_t end, | |
| 2761 | − unsigned long *nr_pagevec); | |
| 2762 | − | |
| 2763 | −static inline void invalidate_remote_inode(struct inode *inode) | |
| 2764 | −{ | |
| 2765 | − if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | |
| 2766 | − S_ISLNK(inode->i_mode)) | |
| 2767 | − invalidate_mapping_pages(inode->i_mapping, 0, -1); | |
| 2768 | −} | |
| 2769 | −extern int invalidate_inode_pages2(struct address_space *mapping); | |
| 2770 | −extern int invalidate_inode_pages2_range(struct address_space *mapping, | |
| 2771 | − pgoff_t start, pgoff_t end); | |
| 2772 | −extern int write_inode_now(struct inode *, int); | |
| 2773 | −extern int filemap_fdatawrite(struct address_space *); | |
| 2774 | −extern int filemap_flush(struct address_space *); | |
| 2775 | −extern int filemap_fdatawait_keep_errors(struct address_space *mapping); | |
| 2776 | −extern int filemap_fdatawait_range(struct address_space *, loff_t lstart, | |
| 2777 | − loff_t lend); | |
| 2778 | −extern int filemap_fdatawait_range_keep_errors(struct address_space *mapping, | |
| 2779 | − loff_t start_byte, loff_t end_byte); | |
| 2780 | − | |
| 2781 | −static inline int filemap_fdatawait(struct address_space *mapping) | |
| 2782 | −{ | |
| 2783 | − return filemap_fdatawait_range(mapping, 0, LLONG_MAX); | |
| 2784 | −} | |
| 2785 | − | |
| 2786 | −extern bool filemap_range_has_page(struct address_space *, loff_t lstart, | |
| 2787 | − loff_t lend); | |
| 2788 | −extern int filemap_write_and_wait_range(struct address_space *mapping, | |
| 2789 | − loff_t lstart, loff_t lend); | |
| 2790 | −extern int __filemap_fdatawrite_range(struct address_space *mapping, | |
| 2791 | − loff_t start, loff_t end, int sync_mode); | |
| 2792 | −extern int filemap_fdatawrite_range(struct address_space *mapping, | |
| 2793 | − loff_t start, loff_t end); | |
| 2794 | −extern int filemap_check_errors(struct address_space *mapping); | |
| 2795 | −extern void __filemap_set_wb_err(struct address_space *mapping, int err); | |
| 2796 | −int filemap_fdatawrite_wbc(struct address_space *mapping, | |
| 2797 | − struct writeback_control *wbc); | |
| 2798 | − | |
| 2799 | −static inline int filemap_write_and_wait(struct address_space *mapping) | |
| 2800 | −{ | |
| 2801 | − return filemap_write_and_wait_range(mapping, 0, LLONG_MAX); | |
| 2802 | −} | |
| 2803 | − | |
| 2804 | 2756 | extern int __must_check file_fdatawait_range(struct file *file, loff_t lstart, |
| 2805 | 2757 | loff_t lend); |
| 2806 | 2758 | extern int __must_check file_check_and_advance_wb_err(struct file *file); |
| @@ -2812,67 +2764,6 @@ static inline int file_write_and_wait(struct file *file) · 5 unmodified lines | ||
| 2812 | 2764 | return file_write_and_wait_range(file, 0, LLONG_MAX); |
| 2813 | 2765 | } |
| 2814 | 2766 | |
| 2815 | −/** | |
| 2816 | − * filemap_set_wb_err - set a writeback error on an address_space | |
| 2817 | − * @mapping: mapping in which to set writeback error | |
| 2818 | − * @err: error to be set in mapping | |
| 2819 | − * | |
| 2820 | − * When writeback fails in some way, we must record that error so that | |
| 2821 | − * userspace can be informed when fsync and the like are called. We endeavor | |
| 2822 | − * to report errors on any file that was open at the time of the error. Some | |
| 2823 | − * internal callers also need to know when writeback errors have occurred. | |
| 2824 | − * | |
| 2825 | − * When a writeback error occurs, most filesystems will want to call | |
| 2826 | − * filemap_set_wb_err to record the error in the mapping so that it will be | |
| 2827 | − * automatically reported whenever fsync is called on the file. | |
| 2828 | − */ | |
| 2829 | −static inline void filemap_set_wb_err(struct address_space *mapping, int err) | |
| 2830 | −{ | |
| 2831 | − /* Fastpath for common case of no error */ | |
| 2832 | − if (unlikely(err)) | |
| 2833 | − __filemap_set_wb_err(mapping, err); | |
| 2834 | −} | |
| 2835 | − | |
| 2836 | −/** | |
| 2837 | − * filemap_check_wb_err - has an error occurred since the mark was sampled? | |
| 2838 | − * @mapping: mapping to check for writeback errors | |
| 2839 | − * @since: previously-sampled errseq_t | |
| 2840 | − * | |
| 2841 | − * Grab the errseq_t value from the mapping, and see if it has changed "since" | |
| 2842 | − * the given value was sampled. | |
| 2843 | − * | |
| 2844 | − * If it has then report the latest error set, otherwise return 0. | |
| 2845 | − */ | |
| 2846 | −static inline int filemap_check_wb_err(struct address_space *mapping, | |
| 2847 | − errseq_t since) | |
| 2848 | −{ | |
| 2849 | − return errseq_check(&mapping->wb_err, since); | |
| 2850 | −} | |
| 2851 | − | |
| 2852 | −/** | |
| 2853 | − * filemap_sample_wb_err - sample the current errseq_t to test for later errors | |
| 2854 | − * @mapping: mapping to be sampled | |
| 2855 | − * | |
| 2856 | − * Writeback errors are always reported relative to a particular sample point | |
| 2857 | − * in the past. This function provides those sample points. | |
| 2858 | − */ | |
| 2859 | −static inline errseq_t filemap_sample_wb_err(struct address_space *mapping) | |
| 2860 | −{ | |
| 2861 | − return errseq_sample(&mapping->wb_err); | |
| 2862 | −} | |
| 2863 | − | |
| 2864 | −/** | |
| 2865 | − * file_sample_sb_err - sample the current errseq_t to test for later errors | |
| 2866 | − * @file: file pointer to be sampled | |
| 2867 | − * | |
| 2868 | − * Grab the most current superblock-level errseq_t value for the given | |
| 2869 | − * struct file. | |
| 2870 | − */ | |
| 2871 | −static inline errseq_t file_sample_sb_err(struct file *file) | |
| 2872 | −{ | |
| 2873 | − return errseq_sample(&file->f_path.dentry->d_sb->s_wb_err); | |
| 2874 | −} | |
| 2875 | − | |
| 2876 | 2767 | extern int vfs_fsync_range(struct file *file, loff_t start, loff_t end, |
| 2877 | 2768 | int datasync); |
| 2878 | 2769 | extern int vfs_fsync(struct file *file, int datasync); |
| @@ -3627,15 +3518,4 @@ extern int vfs_fadvise(struct file *file, loff_t offset, loff_t len, · 748 unmodified lines | ||
| 3627 | 3518 | extern int generic_fadvise(struct file *file, loff_t offset, loff_t len, |
| 3628 | 3519 | int advice); |
| 3629 | 3520 | |
| 3630 | −/* | |
| 3631 | − * Flush file data before changing attributes. Caller must hold any locks | |
| 3632 | − * required to prevent further writes to this file until we're done setting | |
| 3633 | − * flags. | |
| 3634 | − */ | |
| 3635 | −static inline int inode_drain_writes(struct inode *inode) | |
| 3636 | −{ | |
| 3637 | − inode_dio_wait(inode); | |
| 3638 | − return filemap_write_and_wait(inode->i_mapping); | |
| 3639 | −} | |
| 3640 | − | |
| 3641 | 3521 | #endif /* _LINUX_FS_H */ |
| @@ -9,14 +9,9 @@ · 8 unmodified lines | ||
| 9 | 9 | #ifndef LINUX_HMM_H |
| 10 | 10 | #define LINUX_HMM_H |
| 11 | 11 | |
| 12 | −#include <linux/kconfig.h> | |
| 13 | −#include <linux/pgtable.h> | |
| 12 | +#include <linux/mm.h> | |
| 14 | 13 | |
| 15 | −#include <linux/device.h> | |
| 16 | −#include <linux/migrate.h> | |
| 17 | −#include <linux/memremap.h> | |
| 18 | −#include <linux/completion.h> | |
| 19 | −#include <linux/mmu_notifier.h> | |
| 14 | +struct mmu_interval_notifier; | |
| 20 | 15 | |
| 21 | 16 | /* |
| 22 | 17 | * On output: |
| @@ -185,7 +185,7 @@ void prep_transhuge_page(struct page *page); · 184 unmodified lines | ||
| 185 | 185 | void free_transhuge_page(struct page *page); |
| 186 | 186 | bool is_transparent_hugepage(struct page *page); |
| 187 | 187 | |
| 188 | −bool can_split_huge_page(struct page *page, int *pextra_pins); | |
| 188 | +bool can_split_folio(struct folio *folio, int *pextra_pins); | |
| 189 | 189 | int split_huge_page_to_list(struct page *page, struct list_head *list); |
| 190 | 190 | static inline int split_huge_page(struct page *page) |
| 191 | 191 | { |
| @@ -194,7 +194,7 @@ static inline int split_huge_page(struct page *page) · 2 unmodified lines | ||
| 194 | 194 | void deferred_split_huge_page(struct page *page); |
| 195 | 195 | |
| 196 | 196 | void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, |
| 197 | − unsigned long address, bool freeze, struct page *page); | |
| 197 | + unsigned long address, bool freeze, struct folio *folio); | |
| 198 | 198 | |
| 199 | 199 | #define split_huge_pmd(__vma, __pmd, __address) \ |
| 200 | 200 | do { \ |
| @@ -207,7 +207,7 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, · 6 unmodified lines | ||
| 207 | 207 | |
| 208 | 208 | |
| 209 | 209 | void split_huge_pmd_address(struct vm_area_struct *vma, unsigned long address, |
| 210 | − bool freeze, struct page *page); | |
| 210 | + bool freeze, struct folio *folio); | |
| 211 | 211 | |
| 212 | 212 | void __split_huge_pud(struct vm_area_struct *vma, pud_t *pud, |
| 213 | 213 | unsigned long address); |
| @@ -250,30 +250,6 @@ static inline spinlock_t *pud_trans_huge_lock(pud_t *pud, · 36 unmodified lines | ||
| 250 | 250 | return NULL; |
| 251 | 251 | } |
| 252 | 252 | |
| 253 | −/** | |
| 254 | − * thp_order - Order of a transparent huge page. | |
| 255 | − * @page: Head page of a transparent huge page. | |
| 256 | − */ | |
| 257 | −static inline unsigned int thp_order(struct page *page) | |
| 258 | −{ | |
| 259 | − VM_BUG_ON_PGFLAGS(PageTail(page), page); | |
| 260 | − if (PageHead(page)) | |
| 261 | − return HPAGE_PMD_ORDER; | |
| 262 | − return 0; | |
| 263 | −} | |
| 264 | − | |
| 265 | −/** | |
| 266 | − * thp_nr_pages - The number of regular pages in this huge page. | |
| 267 | − * @page: The head page of a huge page. | |
| 268 | − */ | |
| 269 | −static inline int thp_nr_pages(struct page *page) | |
| 270 | −{ | |
| 271 | − VM_BUG_ON_PGFLAGS(PageTail(page), page); | |
| 272 | − if (PageHead(page)) | |
| 273 | − return HPAGE_PMD_NR; | |
| 274 | − return 1; | |
| 275 | −} | |
| 276 | − | |
| 277 | 253 | /** |
| 278 | 254 | * folio_test_pmd_mappable - Can we map this folio with a PMD? |
| 279 | 255 | * @folio: The folio to test |
| @@ -336,18 +312,6 @@ static inline struct list_head *page_deferred_list(struct page *page) · 56 unmodified lines | ||
| 336 | 312 | #define HPAGE_PUD_MASK ({ BUILD_BUG(); 0; }) |
| 337 | 313 | #define HPAGE_PUD_SIZE ({ BUILD_BUG(); 0; }) |
| 338 | 314 | |
| 339 | −static inline unsigned int thp_order(struct page *page) | |
| 340 | −{ | |
| 341 | − VM_BUG_ON_PGFLAGS(PageTail(page), page); | |
| 342 | − return 0; | |
| 343 | −} | |
| 344 | − | |
| 345 | −static inline int thp_nr_pages(struct page *page) | |
| 346 | −{ | |
| 347 | − VM_BUG_ON_PGFLAGS(PageTail(page), page); | |
| 348 | − return 1; | |
| 349 | −} | |
| 350 | − | |
| 351 | 315 | static inline bool folio_test_pmd_mappable(struct folio *folio) |
| 352 | 316 | { |
| 353 | 317 | return false; |
| @@ -387,7 +351,7 @@ static inline bool is_transparent_hugepage(struct page *page) · 33 unmodified lines | ||
| 387 | 351 | #define thp_get_unmapped_area NULL |
| 388 | 352 | |
| 389 | 353 | static inline bool |
| 390 | −can_split_huge_page(struct page *page, int *pextra_pins) | |
| 354 | +can_split_folio(struct folio *folio, int *pextra_pins) | |
| 391 | 355 | { |
| 392 | 356 | BUILD_BUG(); |
| 393 | 357 | return false; |
| @@ -406,9 +370,9 @@ static inline void deferred_split_huge_page(struct page *page) {} · 12 unmodified lines | ||
| 406 | 370 | do { } while (0) |
| 407 | 371 | |
| 408 | 372 | static inline void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, |
| 409 | − unsigned long address, bool freeze, struct page *page) {} | |
| 373 | + unsigned long address, bool freeze, struct folio *folio) {} | |
| 410 | 374 | static inline void split_huge_pmd_address(struct vm_area_struct *vma, |
| 411 | − unsigned long address, bool freeze, struct page *page) {} | |
| 375 | + unsigned long address, bool freeze, struct folio *folio) {} | |
| 412 | 376 | |
| 413 | 377 | #define split_huge_pud(__vma, __pmd, __address) \ |
| 414 | 378 | do { } while (0) |
| @@ -483,15 +447,10 @@ static inline bool thp_migration_supported(void) · 68 unmodified lines | ||
| 483 | 447 | } |
| 484 | 448 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ |
| 485 | 449 | |
| 486 | −/** | |
| 487 | − * thp_size - Size of a transparent huge page. | |
| 488 | − * @page: Head page of a transparent huge page. | |
| 489 | − * | |
| 490 | − * Return: Number of bytes in this page. | |
| 491 | − */ | |
| 492 | −static inline unsigned long thp_size(struct page *page) | |
| 450 | +static inline int split_folio_to_list(struct folio *folio, | |
| 451 | + struct list_head *list) | |
| 493 | 452 | { |
| 494 | − return PAGE_SIZE << thp_order(page); | |
| 453 | + return split_huge_page_to_list(&folio->page, list); | |
| 495 | 454 | } |
| 496 | 455 | |
| 497 | 456 | #endif /* _LINUX_HUGE_MM_H */ |
| @@ -970,6 +970,11 @@ static inline struct hstate *page_hstate(struct page *page) · 969 unmodified lines | ||
| 970 | 970 | return NULL; |
| 971 | 971 | } |
| 972 | 972 | |
| 973 | +static inline struct hstate *size_to_hstate(unsigned long size) | |
| 974 | +{ | |
| 975 | + return NULL; | |
| 976 | +} | |
| 977 | + | |
| 973 | 978 | static inline unsigned long huge_page_size(struct hstate *h) |
| 974 | 979 | { |
| 975 | 980 | return PAGE_SIZE; |
| @@ -51,7 +51,7 @@ static inline void ksm_exit(struct mm_struct *mm) · 50 unmodified lines | ||
| 51 | 51 | struct page *ksm_might_need_to_copy(struct page *page, |
| 52 | 52 | struct vm_area_struct *vma, unsigned long address); |
| 53 | 53 | |
| 54 | −void rmap_walk_ksm(struct page *page, struct rmap_walk_control *rwc); | |
| 54 | +void rmap_walk_ksm(struct folio *folio, const struct rmap_walk_control *rwc); | |
| 55 | 55 | void folio_migrate_ksm(struct folio *newfolio, struct folio *folio); |
| 56 | 56 | |
| 57 | 57 | #else /* !CONFIG_KSM */ |
| @@ -78,8 +78,8 @@ static inline struct page *ksm_might_need_to_copy(struct page *page, · 20 unmodified lines | ||
| 78 | 78 | return page; |
| 79 | 79 | } |
| 80 | 80 | |
| 81 | −static inline void rmap_walk_ksm(struct page *page, | |
| 82 | − struct rmap_walk_control *rwc) | |
| 81 | +static inline void rmap_walk_ksm(struct folio *folio, | |
| 82 | + const struct rmap_walk_control *rwc) | |
| 83 | 83 | { |
| 84 | 84 | } |
| 85 | 85 | |
| @@ -1,6 +1,8 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | 2 | #ifndef _LINUX_MEMREMAP_H_ |
| 3 | 3 | #define _LINUX_MEMREMAP_H_ |
| 4 | + | |
| 5 | +#include <linux/mm.h> | |
| 4 | 6 | #include <linux/range.h> |
| 5 | 7 | #include <linux/ioport.h> |
| 6 | 8 | #include <linux/percpu-refcount.h> |
| @@ -66,9 +68,9 @@ enum memory_type { · 59 unmodified lines | ||
| 66 | 68 | |
| 67 | 69 | struct dev_pagemap_ops { |
| 68 | 70 | /* |
| 69 | − * Called once the page refcount reaches 1. (ZONE_DEVICE pages never | |
| 70 | − * reach 0 refcount unless there is a refcount bug. This allows the | |
| 71 | − * device driver to implement its own memory management.) | |
| 71 | + * Called once the page refcount reaches 0. The reference count will be | |
| 72 | + * reset to one by the core code after the method is called to prepare | |
| 73 | + * for handing out the page again. | |
| 72 | 74 | */ |
| 73 | 75 | void (*page_free)(struct page *page); |
| 74 | 76 | |
| @@ -129,6 +131,25 @@ static inline unsigned long pgmap_vmemmap_nr(struct dev_pagemap *pgmap) · 54 unmodified lines | ||
| 129 | 131 | return 1 << pgmap->vmemmap_shift; |
| 130 | 132 | } |
| 131 | 133 | |
| 134 | +static inline bool is_device_private_page(const struct page *page) | |
| 135 | +{ | |
| 136 | + return IS_ENABLED(CONFIG_DEVICE_PRIVATE) && | |
| 137 | + is_zone_device_page(page) && | |
| 138 | + page->pgmap->type == MEMORY_DEVICE_PRIVATE; | |
| 139 | +} | |
| 140 | + | |
| 141 | +static inline bool folio_is_device_private(const struct folio *folio) | |
| 142 | +{ | |
| 143 | + return is_device_private_page(&folio->page); | |
| 144 | +} | |
| 145 | + | |
| 146 | +static inline bool is_pci_p2pdma_page(const struct page *page) | |
| 147 | +{ | |
| 148 | + return IS_ENABLED(CONFIG_PCI_P2PDMA) && | |
| 149 | + is_zone_device_page(page) && | |
| 150 | + page->pgmap->type == MEMORY_DEVICE_PCI_P2PDMA; | |
| 151 | +} | |
| 152 | + | |
| 132 | 153 | #ifdef CONFIG_ZONE_DEVICE |
| 133 | 154 | void *memremap_pages(struct dev_pagemap *pgmap, int nid); |
| 134 | 155 | void memunmap_pages(struct dev_pagemap *pgmap); |
| @@ -3,9 +3,6 @@ · 2 unmodified lines | ||
| 3 | 3 | #define _LINUX_MM_H |
| 4 | 4 | |
| 5 | 5 | #include <linux/errno.h> |
| 6 | − | |
| 7 | −#ifdef __KERNEL__ | |
| 8 | − | |
| 9 | 6 | #include <linux/mmdebug.h> |
| 10 | 7 | #include <linux/gfp.h> |
| 11 | 8 | #include <linux/bug.h> |
| @@ -26,7 +23,6 @@ · 14 unmodified lines | ||
| 26 | 23 | #include <linux/err.h> |
| 27 | 24 | #include <linux/page-flags.h> |
| 28 | 25 | #include <linux/page_ref.h> |
| 29 | −#include <linux/memremap.h> | |
| 30 | 26 | #include <linux/overflow.h> |
| 31 | 27 | #include <linux/sizes.h> |
| 32 | 28 | #include <linux/sched.h> |
| @@ -216,8 +212,10 @@ int overcommit_policy_handler(struct ctl_table *, int, void *, size_t *, · 183 unmodified lines | ||
| 216 | 212 | |
| 217 | 213 | #if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP) |
| 218 | 214 | #define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n)) |
| 215 | +#define folio_page_idx(folio, p) (page_to_pfn(p) - folio_pfn(folio)) | |
| 219 | 216 | #else |
| 220 | 217 | #define nth_page(page,n) ((page) + (n)) |
| 218 | +#define folio_page_idx(folio, p) ((p) - &(folio)->page) | |
| 221 | 219 | #endif |
| 222 | 220 | |
| 223 | 221 | /* to align the pointer to the (next) page boundary */ |
| @@ -227,6 +225,10 @@ int overcommit_policy_handler(struct ctl_table *, int, void *, size_t *, · 3 unmodified lines | ||
| 227 | 225 | #define PAGE_ALIGNED(addr) IS_ALIGNED((unsigned long)(addr), PAGE_SIZE) |
| 228 | 226 | |
| 229 | 227 | #define lru_to_page(head) (list_entry((head)->prev, struct page, lru)) |
| 228 | +static inline struct folio *lru_to_folio(struct list_head *head) | |
| 229 | +{ | |
| 230 | + return list_entry((head)->prev, struct folio, lru); | |
| 231 | +} | |
| 230 | 232 | |
| 231 | 233 | void setup_initial_init_mm(void *start_code, void *end_code, |
| 232 | 234 | void *end_data, void *brk); |
| @@ -775,21 +777,26 @@ static inline int is_vmalloc_or_module_addr(const void *x) · 542 unmodified lines | ||
| 775 | 777 | } |
| 776 | 778 | #endif |
| 777 | 779 | |
| 778 | −static inline int head_compound_mapcount(struct page *head) | |
| 780 | +/* | |
| 781 | + * How many times the entire folio is mapped as a single unit (eg by a | |
| 782 | + * PMD or PUD entry). This is probably not what you want, except for | |
| 783 | + * debugging purposes; look at folio_mapcount() or page_mapcount() | |
| 784 | + * instead. | |
| 785 | + */ | |
| 786 | +static inline int folio_entire_mapcount(struct folio *folio) | |
| 779 | 787 | { |
| 780 | − return atomic_read(compound_mapcount_ptr(head)) + 1; | |
| 788 | + VM_BUG_ON_FOLIO(!folio_test_large(folio), folio); | |
| 789 | + return atomic_read(folio_mapcount_ptr(folio)) + 1; | |
| 781 | 790 | } |
| 782 | 791 | |
| 783 | 792 | /* |
| 784 | 793 | * Mapcount of compound page as a whole, does not include mapped sub-pages. |
| 785 | 794 | * |
| 786 | − * Must be called only for compound pages or any their tail sub-pages. | |
| 795 | + * Must be called only for compound pages. | |
| 787 | 796 | */ |
| 788 | 797 | static inline int compound_mapcount(struct page *page) |
| 789 | 798 | { |
| 790 | − VM_BUG_ON_PAGE(!PageCompound(page), page); | |
| 791 | − page = compound_head(page); | |
| 792 | − return head_compound_mapcount(page); | |
| 799 | + return folio_entire_mapcount(page_folio(page)); | |
| 793 | 800 | } |
| 794 | 801 | |
| 795 | 802 | /* |
| @@ -819,8 +826,14 @@ static inline int page_mapcount(struct page *page) · 23 unmodified lines | ||
| 819 | 826 | return atomic_read(&page->_mapcount) + 1; |
| 820 | 827 | } |
| 821 | 828 | |
| 829 | +int folio_mapcount(struct folio *folio); | |
| 830 | + | |
| 822 | 831 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
| 823 | −int total_mapcount(struct page *page); | |
| 832 | +static inline int total_mapcount(struct page *page) | |
| 833 | +{ | |
| 834 | + return folio_mapcount(page_folio(page)); | |
| 835 | +} | |
| 836 | + | |
| 824 | 837 | int page_trans_huge_mapcount(struct page *page); |
| 825 | 838 | #else |
| 826 | 839 | static inline int total_mapcount(struct page *page) |
| @@ -890,33 +903,17 @@ static inline void destroy_compound_page(struct page *page) · 63 unmodified lines | ||
| 890 | 903 | compound_page_dtors[page[1].compound_dtor](page); |
| 891 | 904 | } |
| 892 | 905 | |
| 893 | −static inline bool hpage_pincount_available(struct page *page) | |
| 894 | −{ | |
| 895 | − /* | |
| 896 | − * Can the page->hpage_pinned_refcount field be used? That field is in | |
| 897 | − * the 3rd page of the compound page, so the smallest (2-page) compound | |
| 898 | − * pages cannot support it. | |
| 899 | − */ | |
| 900 | − page = compound_head(page); | |
| 901 | − return PageCompound(page) && compound_order(page) > 1; | |
| 902 | −} | |
| 903 | − | |
| 904 | 906 | static inline int head_compound_pincount(struct page *head) |
| 905 | 907 | { |
| 906 | 908 | return atomic_read(compound_pincount_ptr(head)); |
| 907 | 909 | } |
| 908 | 910 | |
| 909 | −static inline int compound_pincount(struct page *page) | |
| 910 | −{ | |
| 911 | − VM_BUG_ON_PAGE(!hpage_pincount_available(page), page); | |
| 912 | − page = compound_head(page); | |
| 913 | − return head_compound_pincount(page); | |
| 914 | −} | |
| 915 | − | |
| 916 | 911 | static inline void set_compound_order(struct page *page, unsigned int order) |
| 917 | 912 | { |
| 918 | 913 | page[1].compound_order = order; |
| 914 | +#ifdef CONFIG_64BIT | |
| 919 | 915 | page[1].compound_nr = 1U << order; |
| 916 | +#endif | |
| 920 | 917 | } |
| 921 | 918 | |
| 922 | 919 | /* Returns the number of pages in this potentially compound page. */ |
| @@ -924,7 +921,11 @@ static inline unsigned long compound_nr(struct page *page) · 1 unmodified line | ||
| 924 | 921 | { |
| 925 | 922 | if (!PageHead(page)) |
| 926 | 923 | return 1; |
| 924 | +#ifdef CONFIG_64BIT | |
| 927 | 925 | return page[1].compound_nr; |
| 926 | +#else | |
| 927 | + return 1UL << compound_order(page); | |
| 928 | +#endif | |
| 928 | 929 | } |
| 929 | 930 | |
| 930 | 931 | /* Returns the number of bytes in this potentially compound page. */ |
| @@ -939,6 +940,37 @@ static inline unsigned int page_shift(struct page *page) · 8 unmodified lines | ||
| 939 | 940 | return PAGE_SHIFT + compound_order(page); |
| 940 | 941 | } |
| 941 | 942 | |
| 943 | +/** | |
| 944 | + * thp_order - Order of a transparent huge page. | |
| 945 | + * @page: Head page of a transparent huge page. | |
| 946 | + */ | |
| 947 | +static inline unsigned int thp_order(struct page *page) | |
| 948 | +{ | |
| 949 | + VM_BUG_ON_PGFLAGS(PageTail(page), page); | |
| 950 | + return compound_order(page); | |
| 951 | +} | |
| 952 | + | |
| 953 | +/** | |
| 954 | + * thp_nr_pages - The number of regular pages in this huge page. | |
| 955 | + * @page: The head page of a huge page. | |
| 956 | + */ | |
| 957 | +static inline int thp_nr_pages(struct page *page) | |
| 958 | +{ | |
| 959 | + VM_BUG_ON_PGFLAGS(PageTail(page), page); | |
| 960 | + return compound_nr(page); | |
| 961 | +} | |
| 962 | + | |
| 963 | +/** | |
| 964 | + * thp_size - Size of a transparent huge page. | |
| 965 | + * @page: Head page of a transparent huge page. | |
| 966 | + * | |
| 967 | + * Return: Number of bytes in this page. | |
| 968 | + */ | |
| 969 | +static inline unsigned long thp_size(struct page *page) | |
| 970 | +{ | |
| 971 | + return PAGE_SIZE << thp_order(page); | |
| 972 | +} | |
| 973 | + | |
| 942 | 974 | void free_compound_page(struct page *page); |
| 943 | 975 | |
| 944 | 976 | #ifdef CONFIG_MMU |
| @@ -1090,59 +1122,35 @@ static inline bool is_zone_device_page(const struct page *page) · 145 unmodified lines | ||
| 1090 | 1122 | } |
| 1091 | 1123 | #endif |
| 1092 | 1124 | |
| 1125 | +static inline bool folio_is_zone_device(const struct folio *folio) | |
| 1126 | +{ | |
| 1127 | + return is_zone_device_page(&folio->page); | |
| 1128 | +} | |
| 1129 | + | |
| 1093 | 1130 | static inline bool is_zone_movable_page(const struct page *page) |
| 1094 | 1131 | { |
| 1095 | 1132 | return page_zonenum(page) == ZONE_MOVABLE; |
| 1096 | 1133 | } |
| 1097 | 1134 | |
| 1098 | −#ifdef CONFIG_DEV_PAGEMAP_OPS | |
| 1099 | −void free_devmap_managed_page(struct page *page); | |
| 1135 | +#if defined(CONFIG_ZONE_DEVICE) && defined(CONFIG_FS_DAX) | |
| 1100 | 1136 | DECLARE_STATIC_KEY_FALSE(devmap_managed_key); |
| 1101 | 1137 | |
| 1102 | −static inline bool page_is_devmap_managed(struct page *page) | |
| 1138 | +bool __put_devmap_managed_page(struct page *page); | |
| 1139 | +static inline bool put_devmap_managed_page(struct page *page) | |
| 1103 | 1140 | { |
| 1104 | 1141 | if (!static_branch_unlikely(&devmap_managed_key)) |
| 1105 | 1142 | return false; |
| 1106 | 1143 | if (!is_zone_device_page(page)) |
| 1107 | 1144 | return false; |
| 1108 | − switch (page->pgmap->type) { | |
| 1109 | − case MEMORY_DEVICE_PRIVATE: | |
| 1110 | − case MEMORY_DEVICE_FS_DAX: | |
| 1111 | − return true; | |
| 1112 | − default: | |
| 1113 | − break; | |
| 1114 | − } | |
| 1115 | − return false; | |
| 1145 | + return __put_devmap_managed_page(page); | |
| 1116 | 1146 | } |
| 1117 | 1147 | |
| 1118 | −void put_devmap_managed_page(struct page *page); | |
| 1119 | − | |
| 1120 | −#else /* CONFIG_DEV_PAGEMAP_OPS */ | |
| 1121 | −static inline bool page_is_devmap_managed(struct page *page) | |
| 1148 | +#else /* CONFIG_ZONE_DEVICE && CONFIG_FS_DAX */ | |
| 1149 | +static inline bool put_devmap_managed_page(struct page *page) | |
| 1122 | 1150 | { |
| 1123 | 1151 | return false; |
| 1124 | 1152 | } |
| 1125 | − | |
| 1126 | −static inline void put_devmap_managed_page(struct page *page) | |
| 1127 | −{ | |
| 1128 | −} | |
| 1129 | −#endif /* CONFIG_DEV_PAGEMAP_OPS */ | |
| 1130 | − | |
| 1131 | −static inline bool is_device_private_page(const struct page *page) | |
| 1132 | −{ | |
| 1133 | − return IS_ENABLED(CONFIG_DEV_PAGEMAP_OPS) && | |
| 1134 | − IS_ENABLED(CONFIG_DEVICE_PRIVATE) && | |
| 1135 | − is_zone_device_page(page) && | |
| 1136 | − page->pgmap->type == MEMORY_DEVICE_PRIVATE; | |
| 1137 | −} | |
| 1138 | − | |
| 1139 | −static inline bool is_pci_p2pdma_page(const struct page *page) | |
| 1140 | −{ | |
| 1141 | − return IS_ENABLED(CONFIG_DEV_PAGEMAP_OPS) && | |
| 1142 | − IS_ENABLED(CONFIG_PCI_P2PDMA) && | |
| 1143 | − is_zone_device_page(page) && | |
| 1144 | − page->pgmap->type == MEMORY_DEVICE_PCI_P2PDMA; | |
| 1145 | −} | |
| 1153 | +#endif /* CONFIG_ZONE_DEVICE && CONFIG_FS_DAX */ | |
| 1146 | 1154 | |
| 1147 | 1155 | /* 127: arbitrary random number, small enough to assemble well */ |
| 1148 | 1156 | #define folio_ref_zero_or_close_to_overflow(folio) \ |
| @@ -1168,9 +1176,6 @@ static inline void get_page(struct page *page) · 19 unmodified lines | ||
| 1168 | 1176 | } |
| 1169 | 1177 | |
| 1170 | 1178 | bool __must_check try_grab_page(struct page *page, unsigned int flags); |
| 1171 | −struct page *try_grab_compound_head(struct page *page, int refs, | |
| 1172 | − unsigned int flags); | |
| 1173 | − | |
| 1174 | 1179 | |
| 1175 | 1180 | static inline __must_check bool try_get_page(struct page *page) |
| 1176 | 1181 | { |
| @@ -1225,16 +1230,11 @@ static inline void put_page(struct page *page) · 48 unmodified lines | ||
| 1225 | 1230 | struct folio *folio = page_folio(page); |
| 1226 | 1231 | |
| 1227 | 1232 | /* |
| 1228 | − * For devmap managed pages we need to catch refcount transition from | |
| 1229 | − * 2 to 1, when refcount reach one it means the page is free and we | |
| 1230 | − * need to inform the device driver through callback. See | |
| 1231 | − * include/linux/memremap.h and HMM for details. | |
| 1233 | + * For some devmap managed pages we need to catch refcount transition | |
| 1234 | + * from 2 to 1: | |
| 1232 | 1235 | */ |
| 1233 | − if (page_is_devmap_managed(&folio->page)) { | |
| 1234 | − put_devmap_managed_page(&folio->page); | |
| 1236 | + if (put_devmap_managed_page(&folio->page)) | |
| 1235 | 1237 | return; |
| 1236 | − } | |
| 1237 | − | |
| 1238 | 1238 | folio_put(folio); |
| 1239 | 1239 | } |
| 1240 | 1240 | |
| @@ -1264,10 +1264,9 @@ static inline void put_page(struct page *page) · 23 unmodified lines | ||
| 1264 | 1264 | * applications that don't have huge page reference counts, this won't be an |
| 1265 | 1265 | * issue. |
| 1266 | 1266 | * |
| 1267 | − * Locking: the lockless algorithm described in page_cache_get_speculative() | |
| 1268 | − * and page_cache_gup_pin_speculative() provides safe operation for | |
| 1269 | − * get_user_pages and page_mkclean and other calls that race to set up page | |
| 1270 | − * table entries. | |
| 1267 | + * Locking: the lockless algorithm described in folio_try_get_rcu() | |
| 1268 | + * provides safe operation for get_user_pages(), page_mkclean() and | |
| 1269 | + * other calls that race to set up page table entries. | |
| 1271 | 1270 | */ |
| 1272 | 1271 | #define GUP_PIN_COUNTING_BIAS (1U << 10) |
| 1273 | 1272 | |
| @@ -1278,70 +1277,11 @@ void unpin_user_page_range_dirty_lock(struct page *page, unsigned long npages, · 4 unmodified lines | ||
| 1278 | 1277 | bool make_dirty); |
| 1279 | 1278 | void unpin_user_pages(struct page **pages, unsigned long npages); |
| 1280 | 1279 | |
| 1281 | −/** | |
| 1282 | − * page_maybe_dma_pinned - Report if a page is pinned for DMA. | |
| 1283 | − * @page: The page. | |
| 1284 | − * | |
| 1285 | − * This function checks if a page has been pinned via a call to | |
| 1286 | − * a function in the pin_user_pages() family. | |
| 1287 | − * | |
| 1288 | − * For non-huge pages, the return value is partially fuzzy: false is not fuzzy, | |
| 1289 | − * because it means "definitely not pinned for DMA", but true means "probably | |
| 1290 | − * pinned for DMA, but possibly a false positive due to having at least | |
| 1291 | − * GUP_PIN_COUNTING_BIAS worth of normal page references". | |
| 1292 | − * | |
| 1293 | − * False positives are OK, because: a) it's unlikely for a page to get that many | |
| 1294 | − * refcounts, and b) all the callers of this routine are expected to be able to | |
| 1295 | − * deal gracefully with a false positive. | |
| 1296 | − * | |
| 1297 | − * For huge pages, the result will be exactly correct. That's because we have | |
| 1298 | − * more tracking data available: the 3rd struct page in the compound page is | |
| 1299 | − * used to track the pincount (instead using of the GUP_PIN_COUNTING_BIAS | |
| 1300 | − * scheme). | |
| 1301 | − * | |
| 1302 | − * For more information, please see Documentation/core-api/pin_user_pages.rst. | |
| 1303 | − * | |
| 1304 | − * Return: True, if it is likely that the page has been "dma-pinned". | |
| 1305 | − * False, if the page is definitely not dma-pinned. | |
| 1306 | − */ | |
| 1307 | −static inline bool page_maybe_dma_pinned(struct page *page) | |
| 1308 | −{ | |
| 1309 | − if (hpage_pincount_available(page)) | |
| 1310 | − return compound_pincount(page) > 0; | |
| 1311 | − | |
| 1312 | − /* | |
| 1313 | − * page_ref_count() is signed. If that refcount overflows, then | |
| 1314 | − * page_ref_count() returns a negative value, and callers will avoid | |
| 1315 | − * further incrementing the refcount. | |
| 1316 | − * | |
| 1317 | − * Here, for that overflow case, use the signed bit to count a little | |
| 1318 | − * bit higher via unsigned math, and thus still get an accurate result. | |
| 1319 | − */ | |
| 1320 | − return ((unsigned int)page_ref_count(compound_head(page))) >= | |
| 1321 | − GUP_PIN_COUNTING_BIAS; | |
| 1322 | −} | |
| 1323 | − | |
| 1324 | 1280 | static inline bool is_cow_mapping(vm_flags_t flags) |
| 1325 | 1281 | { |
| 1326 | 1282 | return (flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE; |
| 1327 | 1283 | } |
| 1328 | 1284 | |
| 1329 | −/* | |
| 1330 | − * This should most likely only be called during fork() to see whether we | |
| 1331 | − * should break the cow immediately for a page on the src mm. | |
| 1332 | − */ | |
| 1333 | −static inline bool page_needs_cow_for_dma(struct vm_area_struct *vma, | |
| 1334 | − struct page *page) | |
| 1335 | −{ | |
| 1336 | − if (!is_cow_mapping(vma->vm_flags)) | |
| 1337 | − return false; | |
| 1338 | − | |
| 1339 | − if (!test_bit(MMF_HAS_PINNED, &vma->vm_mm->flags)) | |
| 1340 | − return false; | |
| 1341 | − | |
| 1342 | − return page_maybe_dma_pinned(page); | |
| 1343 | −} | |
| 1344 | − | |
| 1345 | 1285 | #if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP) |
| 1346 | 1286 | #define SECTION_IN_PAGE_FLAGS |
| 1347 | 1287 | #endif |
| @@ -1586,6 +1526,74 @@ static inline unsigned long folio_pfn(struct folio *folio) · 238 unmodified lines | ||
| 1586 | 1526 | return page_to_pfn(&folio->page); |
| 1587 | 1527 | } |
| 1588 | 1528 | |
| 1529 | +static inline atomic_t *folio_pincount_ptr(struct folio *folio) | |
| 1530 | +{ | |
| 1531 | + return &folio_page(folio, 1)->compound_pincount; | |
| 1532 | +} | |
| 1533 | + | |
| 1534 | +/** | |
| 1535 | + * folio_maybe_dma_pinned - Report if a folio may be pinned for DMA. | |
| 1536 | + * @folio: The folio. | |
| 1537 | + * | |
| 1538 | + * This function checks if a folio has been pinned via a call to | |
| 1539 | + * a function in the pin_user_pages() family. | |
| 1540 | + * | |
| 1541 | + * For small folios, the return value is partially fuzzy: false is not fuzzy, | |
| 1542 | + * because it means "definitely not pinned for DMA", but true means "probably | |
| 1543 | + * pinned for DMA, but possibly a false positive due to having at least | |
| 1544 | + * GUP_PIN_COUNTING_BIAS worth of normal folio references". | |
| 1545 | + * | |
| 1546 | + * False positives are OK, because: a) it's unlikely for a folio to | |
| 1547 | + * get that many refcounts, and b) all the callers of this routine are | |
| 1548 | + * expected to be able to deal gracefully with a false positive. | |
| 1549 | + * | |
| 1550 | + * For large folios, the result will be exactly correct. That's because | |
| 1551 | + * we have more tracking data available: the compound_pincount is used | |
| 1552 | + * instead of the GUP_PIN_COUNTING_BIAS scheme. | |
| 1553 | + * | |
| 1554 | + * For more information, please see Documentation/core-api/pin_user_pages.rst. | |
| 1555 | + * | |
| 1556 | + * Return: True, if it is likely that the page has been "dma-pinned". | |
| 1557 | + * False, if the page is definitely not dma-pinned. | |
| 1558 | + */ | |
| 1559 | +static inline bool folio_maybe_dma_pinned(struct folio *folio) | |
| 1560 | +{ | |
| 1561 | + if (folio_test_large(folio)) | |
| 1562 | + return atomic_read(folio_pincount_ptr(folio)) > 0; | |
| 1563 | + | |
| 1564 | + /* | |
| 1565 | + * folio_ref_count() is signed. If that refcount overflows, then | |
| 1566 | + * folio_ref_count() returns a negative value, and callers will avoid | |
| 1567 | + * further incrementing the refcount. | |
| 1568 | + * | |
| 1569 | + * Here, for that overflow case, use the sign bit to count a little | |
| 1570 | + * bit higher via unsigned math, and thus still get an accurate result. | |
| 1571 | + */ | |
| 1572 | + return ((unsigned int)folio_ref_count(folio)) >= | |
| 1573 | + GUP_PIN_COUNTING_BIAS; | |
| 1574 | +} | |
| 1575 | + | |
| 1576 | +static inline bool page_maybe_dma_pinned(struct page *page) | |
| 1577 | +{ | |
| 1578 | + return folio_maybe_dma_pinned(page_folio(page)); | |
| 1579 | +} | |
| 1580 | + | |
| 1581 | +/* | |
| 1582 | + * This should most likely only be called during fork() to see whether we | |
| 1583 | + * should break the cow immediately for a page on the src mm. | |
| 1584 | + */ | |
| 1585 | +static inline bool page_needs_cow_for_dma(struct vm_area_struct *vma, | |
| 1586 | + struct page *page) | |
| 1587 | +{ | |
| 1588 | + if (!is_cow_mapping(vma->vm_flags)) | |
| 1589 | + return false; | |
| 1590 | + | |
| 1591 | + if (!test_bit(MMF_HAS_PINNED, &vma->vm_mm->flags)) | |
| 1592 | + return false; | |
| 1593 | + | |
| 1594 | + return page_maybe_dma_pinned(page); | |
| 1595 | +} | |
| 1596 | + | |
| 1589 | 1597 | /* MIGRATE_CMA and ZONE_MOVABLE do not allow pin pages */ |
| 1590 | 1598 | #ifdef CONFIG_MIGRATION |
| 1591 | 1599 | static inline bool is_pinnable_page(struct page *page) |
| @@ -1600,6 +1608,11 @@ static inline bool is_pinnable_page(struct page *page) · 8 unmodified lines | ||
| 1600 | 1608 | } |
| 1601 | 1609 | #endif |
| 1602 | 1610 | |
| 1611 | +static inline bool folio_is_pinnable(struct folio *folio) | |
| 1612 | +{ | |
| 1613 | + return is_pinnable_page(&folio->page); | |
| 1614 | +} | |
| 1615 | + | |
| 1603 | 1616 | static inline void set_page_zone(struct page *page, enum zone_type zone) |
| 1604 | 1617 | { |
| 1605 | 1618 | page->flags &= ~(ZONES_MASK << ZONES_PGSHIFT); |
| @@ -1749,7 +1762,6 @@ static inline void *folio_address(const struct folio *folio) · 143 unmodified lines | ||
| 1749 | 1762 | } |
| 1750 | 1763 | |
| 1751 | 1764 | extern void *page_rmapping(struct page *page); |
| 1752 | −extern struct anon_vma *page_anon_vma(struct page *page); | |
| 1753 | 1765 | extern pgoff_t __page_file_index(struct page *page); |
| 1754 | 1766 | |
| 1755 | 1767 | /* |
| @@ -1855,7 +1867,6 @@ extern void truncate_setsize(struct inode *inode, loff_t newsize); · 99 unmodified lines | ||
| 1855 | 1867 | void pagecache_isize_extended(struct inode *inode, loff_t from, loff_t to); |
| 1856 | 1868 | void truncate_pagecache_range(struct inode *inode, loff_t offset, loff_t end); |
| 1857 | 1869 | int generic_error_remove_page(struct address_space *mapping, struct page *page); |
| 1858 | −int invalidate_inode_page(struct page *page); | |
| 1859 | 1870 | |
| 1860 | 1871 | #ifdef CONFIG_MMU |
| 1861 | 1872 | extern vm_fault_t handle_mm_fault(struct vm_area_struct *vma, |
| @@ -2921,13 +2932,11 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address, · 1059 unmodified lines | ||
| 2921 | 2932 | #define FOLL_FORCE 0x10 /* get_user_pages read/write w/o permission */ |
| 2922 | 2933 | #define FOLL_NOWAIT 0x20 /* if a disk transfer is needed, start the IO |
| 2923 | 2934 | * and return without waiting upon it */ |
| 2924 | −#define FOLL_POPULATE 0x40 /* fault in pages (with FOLL_MLOCK) */ | |
| 2925 | 2935 | #define FOLL_NOFAULT 0x80 /* do not fault in pages */ |
| 2926 | 2936 | #define FOLL_HWPOISON 0x100 /* check page is hwpoisoned */ |
| 2927 | 2937 | #define FOLL_NUMA 0x200 /* force NUMA hinting page fault */ |
| 2928 | 2938 | #define FOLL_MIGRATION 0x400 /* wait for page to replace migration entry */ |
| 2929 | 2939 | #define FOLL_TRIED 0x800 /* a retry, previous pass started an IO */ |
| 2930 | −#define FOLL_MLOCK 0x1000 /* lock present pages */ | |
| 2931 | 2940 | #define FOLL_REMOTE 0x2000 /* we are working on non-current tsk/mm */ |
| 2932 | 2941 | #define FOLL_COW 0x4000 /* internal GUP flag */ |
| 2933 | 2942 | #define FOLL_ANON 0x8000 /* don't do file mappings */ |
| @@ -3381,5 +3390,4 @@ madvise_set_anon_name(struct mm_struct *mm, unsigned long start, · 447 unmodified lines | ||
| 3381 | 3390 | } |
| 3382 | 3391 | #endif |
| 3383 | 3392 | |
| 3384 | −#endif /* __KERNEL__ */ | |
| 3385 | 3393 | #endif /* _LINUX_MM_H */ |
| @@ -99,7 +99,8 @@ void lruvec_add_folio(struct lruvec *lruvec, struct folio *folio) · 98 unmodified lines | ||
| 99 | 99 | |
| 100 | 100 | update_lru_size(lruvec, lru, folio_zonenum(folio), |
| 101 | 101 | folio_nr_pages(folio)); |
| 102 | − list_add(&folio->lru, &lruvec->lists[lru]); | |
| 102 | + if (lru != LRU_UNEVICTABLE) | |
| 103 | + list_add(&folio->lru, &lruvec->lists[lru]); | |
| 103 | 104 | } |
| 104 | 105 | |
| 105 | 106 | static __always_inline void add_page_to_lru_list(struct page *page, |
| @@ -115,6 +116,7 @@ void lruvec_add_folio_tail(struct lruvec *lruvec, struct folio *folio) · 9 unmodified lines | ||
| 115 | 116 | |
| 116 | 117 | update_lru_size(lruvec, lru, folio_zonenum(folio), |
| 117 | 118 | folio_nr_pages(folio)); |
| 119 | + /* This is not expected to be used on LRU_UNEVICTABLE */ | |
| 118 | 120 | list_add_tail(&folio->lru, &lruvec->lists[lru]); |
| 119 | 121 | } |
| 120 | 122 | |
| @@ -127,8 +129,11 @@ static __always_inline void add_page_to_lru_list_tail(struct page *page, · 6 unmodified lines | ||
| 127 | 129 | static __always_inline |
| 128 | 130 | void lruvec_del_folio(struct lruvec *lruvec, struct folio *folio) |
| 129 | 131 | { |
| 130 | − list_del(&folio->lru); | |
| 131 | − update_lru_size(lruvec, folio_lru_list(folio), folio_zonenum(folio), | |
| 132 | + enum lru_list lru = folio_lru_list(folio); | |
| 133 | + | |
| 134 | + if (lru != LRU_UNEVICTABLE) | |
| 135 | + list_del(&folio->lru); | |
| 136 | + update_lru_size(lruvec, lru, folio_zonenum(folio), | |
| 132 | 137 | -folio_nr_pages(folio)); |
| 133 | 138 | } |
| 134 | 139 | |
| @@ -85,7 +85,16 @@ struct page { · 84 unmodified lines | ||
| 85 | 85 | * lruvec->lru_lock. Sometimes used as a generic list |
| 86 | 86 | * by the page owner. |
| 87 | 87 | */ |
| 88 | − struct list_head lru; | |
| 88 | + union { | |
| 89 | + struct list_head lru; | |
| 90 | + /* Or, for the Unevictable "LRU list" slot */ | |
| 91 | + struct { | |
| 92 | + /* Always even, to negate PageTail */ | |
| 93 | + void *__filler; | |
| 94 | + /* Count page's or folio's mlocks */ | |
| 95 | + unsigned int mlock_count; | |
| 96 | + }; | |
| 97 | + }; | |
| 89 | 98 | /* See page-flags.h for PAGE_MAPPING_FLAGS */ |
| 90 | 99 | struct address_space *mapping; |
| 91 | 100 | pgoff_t index; /* Our offset within mapping. */ |
| @@ -126,11 +135,14 @@ struct page { · 34 unmodified lines | ||
| 126 | 135 | unsigned char compound_dtor; |
| 127 | 136 | unsigned char compound_order; |
| 128 | 137 | atomic_t compound_mapcount; |
| 138 | + atomic_t compound_pincount; | |
| 139 | +#ifdef CONFIG_64BIT | |
| 129 | 140 | unsigned int compound_nr; /* 1 << compound_order */ |
| 141 | +#endif | |
| 130 | 142 | }; |
| 131 | 143 | struct { /* Second tail page of compound page */ |
| 132 | 144 | unsigned long _compound_pad_1; /* compound_head */ |
| 133 | − atomic_t hpage_pinned_refcount; | |
| 145 | + unsigned long _compound_pad_2; | |
| 134 | 146 | /* For both global and memcg */ |
| 135 | 147 | struct list_head deferred_list; |
| 136 | 148 | }; |
| @@ -241,7 +253,13 @@ struct folio { · 104 unmodified lines | ||
| 241 | 253 | struct { |
| 242 | 254 | /* public: */ |
| 243 | 255 | unsigned long flags; |
| 244 | − struct list_head lru; | |
| 256 | + union { | |
| 257 | + struct list_head lru; | |
| 258 | + struct { | |
| 259 | + void *__filler; | |
| 260 | + unsigned int mlock_count; | |
| 261 | + }; | |
| 262 | + }; | |
| 245 | 263 | struct address_space *mapping; |
| 246 | 264 | pgoff_t index; |
| 247 | 265 | void *private; |
| @@ -285,7 +303,7 @@ static inline atomic_t *compound_mapcount_ptr(struct page *page) · 37 unmodified lines | ||
| 285 | 303 | |
| 286 | 304 | static inline atomic_t *compound_pincount_ptr(struct page *page) |
| 287 | 305 | { |
| 288 | − return &page[2].hpage_pinned_refcount; | |
| 306 | + return &page[1].compound_pincount; | |
| 289 | 307 | } |
| 290 | 308 | |
| 291 | 309 | /* |
| @@ -18,6 +18,120 @@ · 17 unmodified lines | ||
| 18 | 18 | |
| 19 | 19 | struct folio_batch; |
| 20 | 20 | |
| 21 | +unsigned long invalidate_mapping_pages(struct address_space *mapping, | |
| 22 | + pgoff_t start, pgoff_t end); | |
| 23 | + | |
| 24 | +static inline void invalidate_remote_inode(struct inode *inode) | |
| 25 | +{ | |
| 26 | + if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | |
| 27 | + S_ISLNK(inode->i_mode)) | |
| 28 | + invalidate_mapping_pages(inode->i_mapping, 0, -1); | |
| 29 | +} | |
| 30 | +int invalidate_inode_pages2(struct address_space *mapping); | |
| 31 | +int invalidate_inode_pages2_range(struct address_space *mapping, | |
| 32 | + pgoff_t start, pgoff_t end); | |
| 33 | +int write_inode_now(struct inode *, int sync); | |
| 34 | +int filemap_fdatawrite(struct address_space *); | |
| 35 | +int filemap_flush(struct address_space *); | |
| 36 | +int filemap_fdatawait_keep_errors(struct address_space *mapping); | |
| 37 | +int filemap_fdatawait_range(struct address_space *, loff_t lstart, loff_t lend); | |
| 38 | +int filemap_fdatawait_range_keep_errors(struct address_space *mapping, | |
| 39 | + loff_t start_byte, loff_t end_byte); | |
| 40 | + | |
| 41 | +static inline int filemap_fdatawait(struct address_space *mapping) | |
| 42 | +{ | |
| 43 | + return filemap_fdatawait_range(mapping, 0, LLONG_MAX); | |
| 44 | +} | |
| 45 | + | |
| 46 | +bool filemap_range_has_page(struct address_space *, loff_t lstart, loff_t lend); | |
| 47 | +int filemap_write_and_wait_range(struct address_space *mapping, | |
| 48 | + loff_t lstart, loff_t lend); | |
| 49 | +int __filemap_fdatawrite_range(struct address_space *mapping, | |
| 50 | + loff_t start, loff_t end, int sync_mode); | |
| 51 | +int filemap_fdatawrite_range(struct address_space *mapping, | |
| 52 | + loff_t start, loff_t end); | |
| 53 | +int filemap_check_errors(struct address_space *mapping); | |
| 54 | +void __filemap_set_wb_err(struct address_space *mapping, int err); | |
| 55 | +int filemap_fdatawrite_wbc(struct address_space *mapping, | |
| 56 | + struct writeback_control *wbc); | |
| 57 | + | |
| 58 | +static inline int filemap_write_and_wait(struct address_space *mapping) | |
| 59 | +{ | |
| 60 | + return filemap_write_and_wait_range(mapping, 0, LLONG_MAX); | |
| 61 | +} | |
| 62 | + | |
| 63 | +/** | |
| 64 | + * filemap_set_wb_err - set a writeback error on an address_space | |
| 65 | + * @mapping: mapping in which to set writeback error | |
| 66 | + * @err: error to be set in mapping | |
| 67 | + * | |
| 68 | + * When writeback fails in some way, we must record that error so that | |
| 69 | + * userspace can be informed when fsync and the like are called. We endeavor | |
| 70 | + * to report errors on any file that was open at the time of the error. Some | |
| 71 | + * internal callers also need to know when writeback errors have occurred. | |
| 72 | + * | |
| 73 | + * When a writeback error occurs, most filesystems will want to call | |
| 74 | + * filemap_set_wb_err to record the error in the mapping so that it will be | |
| 75 | + * automatically reported whenever fsync is called on the file. | |
| 76 | + */ | |
| 77 | +static inline void filemap_set_wb_err(struct address_space *mapping, int err) | |
| 78 | +{ | |
| 79 | + /* Fastpath for common case of no error */ | |
| 80 | + if (unlikely(err)) | |
| 81 | + __filemap_set_wb_err(mapping, err); | |
| 82 | +} | |
| 83 | + | |
| 84 | +/** | |
| 85 | + * filemap_check_wb_err - has an error occurred since the mark was sampled? | |
| 86 | + * @mapping: mapping to check for writeback errors | |
| 87 | + * @since: previously-sampled errseq_t | |
| 88 | + * | |
| 89 | + * Grab the errseq_t value from the mapping, and see if it has changed "since" | |
| 90 | + * the given value was sampled. | |
| 91 | + * | |
| 92 | + * If it has then report the latest error set, otherwise return 0. | |
| 93 | + */ | |
| 94 | +static inline int filemap_check_wb_err(struct address_space *mapping, | |
| 95 | + errseq_t since) | |
| 96 | +{ | |
| 97 | + return errseq_check(&mapping->wb_err, since); | |
| 98 | +} | |
| 99 | + | |
| 100 | +/** | |
| 101 | + * filemap_sample_wb_err - sample the current errseq_t to test for later errors | |
| 102 | + * @mapping: mapping to be sampled | |
| 103 | + * | |
| 104 | + * Writeback errors are always reported relative to a particular sample point | |
| 105 | + * in the past. This function provides those sample points. | |
| 106 | + */ | |
| 107 | +static inline errseq_t filemap_sample_wb_err(struct address_space *mapping) | |
| 108 | +{ | |
| 109 | + return errseq_sample(&mapping->wb_err); | |
| 110 | +} | |
| 111 | + | |
| 112 | +/** | |
| 113 | + * file_sample_sb_err - sample the current errseq_t to test for later errors | |
| 114 | + * @file: file pointer to be sampled | |
| 115 | + * | |
| 116 | + * Grab the most current superblock-level errseq_t value for the given | |
| 117 | + * struct file. | |
| 118 | + */ | |
| 119 | +static inline errseq_t file_sample_sb_err(struct file *file) | |
| 120 | +{ | |
| 121 | + return errseq_sample(&file->f_path.dentry->d_sb->s_wb_err); | |
| 122 | +} | |
| 123 | + | |
| 124 | +/* | |
| 125 | + * Flush file data before changing attributes. Caller must hold any locks | |
| 126 | + * required to prevent further writes to this file until we're done setting | |
| 127 | + * flags. | |
| 128 | + */ | |
| 129 | +static inline int inode_drain_writes(struct inode *inode) | |
| 130 | +{ | |
| 131 | + inode_dio_wait(inode); | |
| 132 | + return filemap_write_and_wait(inode->i_mapping); | |
| 133 | +} | |
| 134 | + | |
| 21 | 135 | static inline bool mapping_empty(struct address_space *mapping) |
| 22 | 136 | { |
| 23 | 137 | return xa_empty(&mapping->i_pages); |
| @@ -192,9 +306,14 @@ static inline void mapping_set_large_folios(struct address_space *mapping) · 168 unmodified lines | ||
| 192 | 306 | __set_bit(AS_LARGE_FOLIO_SUPPORT, &mapping->flags); |
| 193 | 307 | } |
| 194 | 308 | |
| 309 | +/* | |
| 310 | + * Large folio support currently depends on THP. These dependencies are | |
| 311 | + * being worked on but are not yet fixed. | |
| 312 | + */ | |
| 195 | 313 | static inline bool mapping_large_folio_support(struct address_space *mapping) |
| 196 | 314 | { |
| 197 | − return test_bit(AS_LARGE_FOLIO_SUPPORT, &mapping->flags); | |
| 315 | + return IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && | |
| 316 | + test_bit(AS_LARGE_FOLIO_SUPPORT, &mapping->flags); | |
| 198 | 317 | } |
| 199 | 318 | |
| 200 | 319 | static inline int filemap_nr_thps(struct address_space *mapping) |
| @@ -212,7 +331,7 @@ static inline void filemap_nr_thps_inc(struct address_space *mapping) · 11 unmodified lines | ||
| 212 | 331 | if (!mapping_large_folio_support(mapping)) |
| 213 | 332 | atomic_inc(&mapping->nr_thps); |
| 214 | 333 | #else |
| 215 | − WARN_ON_ONCE(1); | |
| 334 | + WARN_ON_ONCE(mapping_large_folio_support(mapping) == 0); | |
| 216 | 335 | #endif |
| 217 | 336 | } |
| 218 | 337 | |
| @@ -222,7 +341,7 @@ static inline void filemap_nr_thps_dec(struct address_space *mapping) · 3 unmodified lines | ||
| 222 | 341 | if (!mapping_large_folio_support(mapping)) |
| 223 | 342 | atomic_dec(&mapping->nr_thps); |
| 224 | 343 | #else |
| 225 | − WARN_ON_ONCE(1); | |
| 344 | + WARN_ON_ONCE(mapping_large_folio_support(mapping) == 0); | |
| 226 | 345 | #endif |
| 227 | 346 | } |
| 228 | 347 | |
| @@ -283,16 +402,6 @@ static inline struct inode *folio_inode(struct folio *folio) · 54 unmodified lines | ||
| 283 | 402 | return folio->mapping->host; |
| 284 | 403 | } |
| 285 | 404 | |
| 286 | −static inline bool page_cache_add_speculative(struct page *page, int count) | |
| 287 | −{ | |
| 288 | − return folio_ref_try_add_rcu((struct folio *)page, count); | |
| 289 | −} | |
| 290 | − | |
| 291 | −static inline bool page_cache_get_speculative(struct page *page) | |
| 292 | −{ | |
| 293 | − return page_cache_add_speculative(page, 1); | |
| 294 | −} | |
| 295 | − | |
| 296 | 405 | /** |
| 297 | 406 | * folio_attach_private - Attach private data to a folio. |
| 298 | 407 | * @folio: Folio to attach data to. |
| @@ -706,6 +815,17 @@ static inline loff_t folio_file_pos(struct folio *folio) · 407 unmodified lines | ||
| 706 | 815 | return page_file_offset(&folio->page); |
| 707 | 816 | } |
| 708 | 817 | |
| 818 | +/* | |
| 819 | + * Get the offset in PAGE_SIZE (even for hugetlb folios). | |
| 820 | + * (TODO: hugetlb folios should have ->index in PAGE_SIZE) | |
| 821 | + */ | |
| 822 | +static inline pgoff_t folio_pgoff(struct folio *folio) | |
| 823 | +{ | |
| 824 | + if (unlikely(folio_test_hugetlb(folio))) | |
| 825 | + return hugetlb_basepage_index(&folio->page); | |
| 826 | + return folio->index; | |
| 827 | +} | |
| 828 | + | |
| 709 | 829 | extern pgoff_t linear_hugepage_index(struct vm_area_struct *vma, |
| 710 | 830 | unsigned long address); |
| 711 | 831 | |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/rwsem.h> |
| 12 | 12 | #include <linux/memcontrol.h> |
| 13 | 13 | #include <linux/highmem.h> |
| 14 | +#include <linux/pagemap.h> | |
| 14 | 15 | |
| 15 | 16 | /* |
| 16 | 17 | * The anon_vma heads a list of private "related" vmas, to scan if |
| @@ -167,18 +168,19 @@ struct anon_vma *page_get_anon_vma(struct page *page); · 150 unmodified lines | ||
| 167 | 168 | */ |
| 168 | 169 | void page_move_anon_rmap(struct page *, struct vm_area_struct *); |
| 169 | 170 | void page_add_anon_rmap(struct page *, struct vm_area_struct *, |
| 170 | − unsigned long, bool); | |
| 171 | + unsigned long address, bool compound); | |
| 171 | 172 | void do_page_add_anon_rmap(struct page *, struct vm_area_struct *, |
| 172 | − unsigned long, int); | |
| 173 | + unsigned long address, int flags); | |
| 173 | 174 | void page_add_new_anon_rmap(struct page *, struct vm_area_struct *, |
| 174 | − unsigned long, bool); | |
| 175 | −void page_add_file_rmap(struct page *, bool); | |
| 176 | −void page_remove_rmap(struct page *, bool); | |
| 177 | − | |
| 175 | + unsigned long address, bool compound); | |
| 176 | +void page_add_file_rmap(struct page *, struct vm_area_struct *, | |
| 177 | + bool compound); | |
| 178 | +void page_remove_rmap(struct page *, struct vm_area_struct *, | |
| 179 | + bool compound); | |
| 178 | 180 | void hugepage_add_anon_rmap(struct page *, struct vm_area_struct *, |
| 179 | − unsigned long); | |
| 181 | + unsigned long address); | |
| 180 | 182 | void hugepage_add_new_anon_rmap(struct page *, struct vm_area_struct *, |
| 181 | − unsigned long); | |
| 183 | + unsigned long address); | |
| 182 | 184 | |
| 183 | 185 | static inline void page_dup_rmap(struct page *page, bool compound) |
| 184 | 186 | { |
| @@ -188,11 +190,11 @@ static inline void page_dup_rmap(struct page *page, bool compound) · 3 unmodified lines | ||
| 188 | 190 | /* |
| 189 | 191 | * Called from mm/vmscan.c to handle paging out |
| 190 | 192 | */ |
| 191 | −int page_referenced(struct page *, int is_locked, | |
| 193 | +int folio_referenced(struct folio *, int is_locked, | |
| 192 | 194 | struct mem_cgroup *memcg, unsigned long *vm_flags); |
| 193 | 195 | |
| 194 | −void try_to_migrate(struct page *page, enum ttu_flags flags); | |
| 195 | −void try_to_unmap(struct page *, enum ttu_flags flags); | |
| 196 | +void try_to_migrate(struct folio *folio, enum ttu_flags flags); | |
| 197 | +void try_to_unmap(struct folio *, enum ttu_flags flags); | |
| 196 | 198 | |
| 197 | 199 | int make_device_exclusive_range(struct mm_struct *mm, unsigned long start, |
| 198 | 200 | unsigned long end, struct page **pages, |
| @@ -200,11 +202,13 @@ int make_device_exclusive_range(struct mm_struct *mm, unsigned long start, · 1 unmodified line | ||
| 200 | 202 | |
| 201 | 203 | /* Avoid racy checks */ |
| 202 | 204 | #define PVMW_SYNC (1 << 0) |
| 203 | −/* Look for migarion entries rather than present PTEs */ | |
| 205 | +/* Look for migration entries rather than present PTEs */ | |
| 204 | 206 | #define PVMW_MIGRATION (1 << 1) |
| 205 | 207 | |
| 206 | 208 | struct page_vma_mapped_walk { |
| 207 | − struct page *page; | |
| 209 | + unsigned long pfn; | |
| 210 | + unsigned long nr_pages; | |
| 211 | + pgoff_t pgoff; | |
| 208 | 212 | struct vm_area_struct *vma; |
| 209 | 213 | unsigned long address; |
| 210 | 214 | pmd_t *pmd; |
| @@ -213,10 +217,30 @@ struct page_vma_mapped_walk { · 2 unmodified lines | ||
| 213 | 217 | unsigned int flags; |
| 214 | 218 | }; |
| 215 | 219 | |
| 220 | +#define DEFINE_PAGE_VMA_WALK(name, _page, _vma, _address, _flags) \ | |
| 221 | + struct page_vma_mapped_walk name = { \ | |
| 222 | + .pfn = page_to_pfn(_page), \ | |
| 223 | + .nr_pages = compound_nr(page), \ | |
| 224 | + .pgoff = page_to_pgoff(page), \ | |
| 225 | + .vma = _vma, \ | |
| 226 | + .address = _address, \ | |
| 227 | + .flags = _flags, \ | |
| 228 | + } | |
| 229 | + | |
| 230 | +#define DEFINE_FOLIO_VMA_WALK(name, _folio, _vma, _address, _flags) \ | |
| 231 | + struct page_vma_mapped_walk name = { \ | |
| 232 | + .pfn = folio_pfn(_folio), \ | |
| 233 | + .nr_pages = folio_nr_pages(_folio), \ | |
| 234 | + .pgoff = folio_pgoff(_folio), \ | |
| 235 | + .vma = _vma, \ | |
| 236 | + .address = _address, \ | |
| 237 | + .flags = _flags, \ | |
| 238 | + } | |
| 239 | + | |
| 216 | 240 | static inline void page_vma_mapped_walk_done(struct page_vma_mapped_walk *pvmw) |
| 217 | 241 | { |
| 218 | 242 | /* HugeTLB pte is set to the relevant page table entry without pte_mapped. */ |
| 219 | − if (pvmw->pte && !PageHuge(pvmw->page)) | |
| 243 | + if (pvmw->pte && !is_vm_hugetlb_page(pvmw->vma)) | |
| 220 | 244 | pte_unmap(pvmw->pte); |
| 221 | 245 | if (pvmw->ptl) |
| 222 | 246 | spin_unlock(pvmw->ptl); |
| @@ -237,18 +261,12 @@ unsigned long page_address_in_vma(struct page *, struct vm_area_struct *); · 14 unmodified lines | ||
| 237 | 261 | */ |
| 238 | 262 | int folio_mkclean(struct folio *); |
| 239 | 263 | |
| 240 | −/* | |
| 241 | − * called in munlock()/munmap() path to check for other vmas holding | |
| 242 | − * the page mlocked. | |
| 243 | − */ | |
| 244 | −void page_mlock(struct page *page); | |
| 245 | − | |
| 246 | −void remove_migration_ptes(struct page *old, struct page *new, bool locked); | |
| 264 | +void remove_migration_ptes(struct folio *src, struct folio *dst, bool locked); | |
| 247 | 265 | |
| 248 | 266 | /* |
| 249 | 267 | * Called by memory-failure.c to kill processes. |
| 250 | 268 | */ |
| 251 | −struct anon_vma *page_lock_anon_vma_read(struct page *page); | |
| 269 | +struct anon_vma *folio_lock_anon_vma_read(struct folio *folio); | |
| 252 | 270 | void page_unlock_anon_vma_read(struct anon_vma *anon_vma); |
| 253 | 271 | int page_mapped_in_vma(struct page *page, struct vm_area_struct *vma); |
| 254 | 272 | |
| @@ -267,15 +285,15 @@ struct rmap_walk_control { · 12 unmodified lines | ||
| 267 | 285 | * Return false if page table scanning in rmap_walk should be stopped. |
| 268 | 286 | * Otherwise, return true. |
| 269 | 287 | */ |
| 270 | − bool (*rmap_one)(struct page *page, struct vm_area_struct *vma, | |
| 288 | + bool (*rmap_one)(struct folio *folio, struct vm_area_struct *vma, | |
| 271 | 289 | unsigned long addr, void *arg); |
| 272 | − int (*done)(struct page *page); | |
| 273 | − struct anon_vma *(*anon_lock)(struct page *page); | |
| 290 | + int (*done)(struct folio *folio); | |
| 291 | + struct anon_vma *(*anon_lock)(struct folio *folio); | |
| 274 | 292 | bool (*invalid_vma)(struct vm_area_struct *vma, void *arg); |
| 275 | 293 | }; |
| 276 | 294 | |
| 277 | −void rmap_walk(struct page *page, struct rmap_walk_control *rwc); | |
| 278 | −void rmap_walk_locked(struct page *page, struct rmap_walk_control *rwc); | |
| 295 | +void rmap_walk(struct folio *folio, const struct rmap_walk_control *rwc); | |
| 296 | +void rmap_walk_locked(struct folio *folio, const struct rmap_walk_control *rwc); | |
| 279 | 297 | |
| 280 | 298 | #else /* !CONFIG_MMU */ |
| 281 | 299 | |
| @@ -283,7 +301,7 @@ void rmap_walk_locked(struct page *page, struct rmap_walk_control *rwc); · 1 unmodified line | ||
| 283 | 301 | #define anon_vma_prepare(vma) (0) |
| 284 | 302 | #define anon_vma_link(vma) do {} while (0) |
| 285 | 303 | |
| 286 | −static inline int page_referenced(struct page *page, int is_locked, | |
| 304 | +static inline int folio_referenced(struct folio *folio, int is_locked, | |
| 287 | 305 | struct mem_cgroup *memcg, |
| 288 | 306 | unsigned long *vm_flags) |
| 289 | 307 | { |
| @@ -291,7 +309,7 @@ static inline int page_referenced(struct page *page, int is_locked, · 1 unmodified line | ||
| 291 | 309 | return 0; |
| 292 | 310 | } |
| 293 | 311 | |
| 294 | −static inline void try_to_unmap(struct page *page, enum ttu_flags flags) | |
| 312 | +static inline void try_to_unmap(struct folio *folio, enum ttu_flags flags) | |
| 295 | 313 | { |
| 296 | 314 | } |
| 297 | 315 | |
| @@ -328,7 +328,7 @@ static inline swp_entry_t folio_swap_entry(struct folio *folio) · 327 unmodified lines | ||
| 328 | 328 | |
| 329 | 329 | /* linux/mm/workingset.c */ |
| 330 | 330 | void workingset_age_nonresident(struct lruvec *lruvec, unsigned long nr_pages); |
| 331 | −void *workingset_eviction(struct page *page, struct mem_cgroup *target_memcg); | |
| 331 | +void *workingset_eviction(struct folio *folio, struct mem_cgroup *target_memcg); | |
| 332 | 332 | void workingset_refault(struct folio *folio, void *shadow); |
| 333 | 333 | void workingset_activation(struct folio *folio); |
| 334 | 334 | |
| @@ -375,7 +375,6 @@ extern void lru_add_drain(void); · 40 unmodified lines | ||
| 375 | 375 | extern void lru_add_drain_cpu(int cpu); |
| 376 | 376 | extern void lru_add_drain_cpu_zone(struct zone *zone); |
| 377 | 377 | extern void lru_add_drain_all(void); |
| 378 | −extern void deactivate_file_page(struct page *page); | |
| 379 | 378 | extern void deactivate_page(struct page *page); |
| 380 | 379 | extern void mark_page_lazyfree(struct page *page); |
| 381 | 380 | extern void swap_setup(void); |
| @@ -397,7 +396,7 @@ extern unsigned long mem_cgroup_shrink_node(struct mem_cgroup *mem, · 15 unmodified lines | ||
| 397 | 396 | unsigned long *nr_scanned); |
| 398 | 397 | extern unsigned long shrink_all_memory(unsigned long nr_pages); |
| 399 | 398 | extern int vm_swappiness; |
| 400 | −extern int remove_mapping(struct address_space *mapping, struct page *page); | |
| 399 | +long remove_mapping(struct address_space *mapping, struct folio *folio); | |
| 401 | 400 | |
| 402 | 401 | extern unsigned long reclaim_pages(struct list_head *page_list); |
| 403 | 402 | #ifdef CONFIG_NUMA |
| @@ -743,7 +742,7 @@ static inline void cgroup_throttle_swaprate(struct page *page, gfp_t gfp_mask) · 339 unmodified lines | ||
| 743 | 742 | #endif |
| 744 | 743 | |
| 745 | 744 | #ifdef CONFIG_MEMCG_SWAP |
| 746 | −extern void mem_cgroup_swapout(struct page *page, swp_entry_t entry); | |
| 745 | +void mem_cgroup_swapout(struct folio *folio, swp_entry_t entry); | |
| 747 | 746 | extern int __mem_cgroup_try_charge_swap(struct page *page, swp_entry_t entry); |
| 748 | 747 | static inline int mem_cgroup_try_charge_swap(struct page *page, swp_entry_t entry) |
| 749 | 748 | { |
| @@ -763,7 +762,7 @@ static inline void mem_cgroup_uncharge_swap(swp_entry_t entry, unsigned int nr_p · 13 unmodified lines | ||
| 763 | 762 | extern long mem_cgroup_get_nr_swap_pages(struct mem_cgroup *memcg); |
| 764 | 763 | extern bool mem_cgroup_swap_full(struct page *page); |
| 765 | 764 | #else |
| 766 | −static inline void mem_cgroup_swapout(struct page *page, swp_entry_t entry) | |
| 765 | +static inline void mem_cgroup_swapout(struct folio *folio, swp_entry_t entry) | |
| 767 | 766 | { |
| 768 | 767 | } |
| 769 | 768 | |
| @@ -327,11 +327,11 @@ TRACE_EVENT(mm_vmscan_lru_isolate, · 326 unmodified lines | ||
| 327 | 327 | __print_symbolic(__entry->lru, LRU_NAMES)) |
| 328 | 328 | ); |
| 329 | 329 | |
| 330 | −TRACE_EVENT(mm_vmscan_writepage, | |
| 330 | +TRACE_EVENT(mm_vmscan_write_folio, | |
| 331 | 331 | |
| 332 | − TP_PROTO(struct page *page), | |
| 332 | + TP_PROTO(struct folio *folio), | |
| 333 | 333 | |
| 334 | − TP_ARGS(page), | |
| 334 | + TP_ARGS(folio), | |
| 335 | 335 | |
| 336 | 336 | TP_STRUCT__entry( |
| 337 | 337 | __field(unsigned long, pfn) |
| @@ -339,9 +339,9 @@ TRACE_EVENT(mm_vmscan_writepage, · 1 unmodified line | ||
| 339 | 339 | ), |
| 340 | 340 | |
| 341 | 341 | TP_fast_assign( |
| 342 | − __entry->pfn = page_to_pfn(page); | |
| 342 | + __entry->pfn = folio_pfn(folio); | |
| 343 | 343 | __entry->reclaim_flags = trace_reclaim_flags( |
| 344 | − page_is_file_lru(page)); | |
| 344 | + folio_is_file_lru(folio)); | |
| 345 | 345 | ), |
| 346 | 346 | |
| 347 | 347 | TP_printk("page=%p pfn=0x%lx flags=%s", |
| @@ -155,11 +155,7 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr, · 154 unmodified lines | ||
| 155 | 155 | struct page *old_page, struct page *new_page) |
| 156 | 156 | { |
| 157 | 157 | struct mm_struct *mm = vma->vm_mm; |
| 158 | − struct page_vma_mapped_walk pvmw = { | |
| 159 | − .page = compound_head(old_page), | |
| 160 | − .vma = vma, | |
| 161 | − .address = addr, | |
| 162 | − }; | |
| 158 | + DEFINE_FOLIO_VMA_WALK(pvmw, page_folio(old_page), vma, addr, 0); | |
| 163 | 159 | int err; |
| 164 | 160 | struct mmu_notifier_range range; |
| 165 | 161 | |
| @@ -173,7 +169,7 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr, · 7 unmodified lines | ||
| 173 | 169 | return err; |
| 174 | 170 | } |
| 175 | 171 | |
| 176 | − /* For try_to_free_swap() and munlock_vma_page() below */ | |
| 172 | + /* For try_to_free_swap() below */ | |
| 177 | 173 | lock_page(old_page); |
| 178 | 174 | |
| 179 | 175 | mmu_notifier_invalidate_range_start(&range); |
| @@ -201,13 +197,10 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr, · 21 unmodified lines | ||
| 201 | 197 | set_pte_at_notify(mm, addr, pvmw.pte, |
| 202 | 198 | mk_pte(new_page, vma->vm_page_prot)); |
| 203 | 199 | |
| 204 | − page_remove_rmap(old_page, false); | |
| 200 | + page_remove_rmap(old_page, vma, false); | |
| 205 | 201 | if (!page_mapped(old_page)) |
| 206 | 202 | try_to_free_swap(old_page); |
| 207 | 203 | page_vma_mapped_walk_done(&pvmw); |
| 208 | − | |
| 209 | − if ((vma->vm_flags & VM_LOCKED) && !PageCompound(old_page)) | |
| 210 | − munlock_vma_page(old_page); | |
| 211 | 204 | put_page(old_page); |
| 212 | 205 | |
| 213 | 206 | err = 0; |
| @@ -302,7 +302,7 @@ again: · 301 unmodified lines | ||
| 302 | 302 | * found it, but truncated or holepunched or subjected to |
| 303 | 303 | * invalidate_complete_page2 before we got the page lock (also |
| 304 | 304 | * cases which we are happy to fail). And we hold a reference, |
| 305 | − * so refcount care in invalidate_complete_page's remove_mapping | |
| 305 | + * so refcount care in invalidate_inode_page's remove_mapping | |
| 306 | 306 | * prevents drop_caches from setting mapping to NULL beneath us. |
| 307 | 307 | * |
| 308 | 308 | * The case we do have to guard against is when memory pressure made |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <linux/kernel.h> |
| 13 | 13 | #include <linux/cdev.h> |
| 14 | 14 | #include <linux/device.h> |
| 15 | +#include <linux/memremap.h> | |
| 15 | 16 | #include <linux/mutex.h> |
| 16 | 17 | #include <linux/rwsem.h> |
| 17 | 18 | #include <linux/sched.h> |
| @@ -26,6 +27,8 @@ · 8 unmodified lines | ||
| 26 | 27 | #include <linux/sched/mm.h> |
| 27 | 28 | #include <linux/platform_device.h> |
| 28 | 29 | #include <linux/rmap.h> |
| 30 | +#include <linux/mmu_notifier.h> | |
| 31 | +#include <linux/migrate.h> | |
| 29 | 32 | |
| 30 | 33 | #include "test_hmm_uapi.h" |
| 31 | 34 | |
| @@ -563,7 +566,6 @@ static struct page *dmirror_devmem_alloc_page(struct dmirror_device *mdevice) · 531 unmodified lines | ||
| 563 | 566 | } |
| 564 | 567 | |
| 565 | 568 | dpage->zone_device_data = rpage; |
| 566 | − get_page(dpage); | |
| 567 | 569 | lock_page(dpage); |
| 568 | 570 | return dpage; |
| 569 | 571 | |
| @@ -249,6 +249,9 @@ config MIGRATION · 248 unmodified lines | ||
| 249 | 249 | pages as migration can relocate pages to satisfy a huge page |
| 250 | 250 | allocation instead of reclaiming. |
| 251 | 251 | |
| 252 | +config DEVICE_MIGRATION | |
| 253 | + def_bool MIGRATION && ZONE_DEVICE | |
| 254 | + | |
| 252 | 255 | config ARCH_ENABLE_HUGEPAGE_MIGRATION |
| 253 | 256 | bool |
| 254 | 257 | |
| @@ -791,9 +794,6 @@ config ZONE_DEVICE · 536 unmodified lines | ||
| 791 | 794 | |
| 792 | 795 | If FS_DAX is enabled, then say Y. |
| 793 | 796 | |
| 794 | −config DEV_PAGEMAP_OPS | |
| 795 | − bool | |
| 796 | − | |
| 797 | 797 | # |
| 798 | 798 | # Helpers to mirror range of the CPU page tables of a process into device page |
| 799 | 799 | # tables. |
| @@ -805,7 +805,6 @@ config HMM_MIRROR · 5 unmodified lines | ||
| 805 | 805 | config DEVICE_PRIVATE |
| 806 | 806 | bool "Unaddressable device memory (GPU memory, ...)" |
| 807 | 807 | depends on ZONE_DEVICE |
| 808 | − select DEV_PAGEMAP_OPS | |
| 809 | 808 | |
| 810 | 809 | help |
| 811 | 810 | Allows creation of struct pages to represent unaddressable device |
| @@ -92,6 +92,7 @@ obj-$(CONFIG_KFENCE) += kfence/ · 91 unmodified lines | ||
| 92 | 92 | obj-$(CONFIG_FAILSLAB) += failslab.o |
| 93 | 93 | obj-$(CONFIG_MEMTEST) += memtest.o |
| 94 | 94 | obj-$(CONFIG_MIGRATION) += migrate.o |
| 95 | +obj-$(CONFIG_DEVICE_MIGRATION) += migrate_device.o | |
| 95 | 96 | obj-$(CONFIG_TRANSPARENT_HUGEPAGE) += huge_memory.o khugepaged.o |
| 96 | 97 | obj-$(CONFIG_PAGE_COUNTER) += page_counter.o |
| 97 | 98 | obj-$(CONFIG_MEMCG) += memcontrol.o vmpressure.o |
| @@ -16,14 +16,10 @@ · 15 unmodified lines | ||
| 16 | 16 | #include "../internal.h" |
| 17 | 17 | #include "ops-common.h" |
| 18 | 18 | |
| 19 | −static bool __damon_pa_mkold(struct page *page, struct vm_area_struct *vma, | |
| 19 | +static bool __damon_pa_mkold(struct folio *folio, struct vm_area_struct *vma, | |
| 20 | 20 | unsigned long addr, void *arg) |
| 21 | 21 | { |
| 22 | − struct page_vma_mapped_walk pvmw = { | |
| 23 | − .page = page, | |
| 24 | − .vma = vma, | |
| 25 | − .address = addr, | |
| 26 | − }; | |
| 22 | + DEFINE_FOLIO_VMA_WALK(pvmw, folio, vma, addr, 0); | |
| 27 | 23 | |
| 28 | 24 | while (page_vma_mapped_walk(&pvmw)) { |
| 29 | 25 | addr = pvmw.address; |
| @@ -37,32 +33,34 @@ static bool __damon_pa_mkold(struct page *page, struct vm_area_struct *vma, · 7 unmodified lines | ||
| 37 | 33 | |
| 38 | 34 | static void damon_pa_mkold(unsigned long paddr) |
| 39 | 35 | { |
| 36 | + struct folio *folio; | |
| 40 | 37 | struct page *page = damon_get_page(PHYS_PFN(paddr)); |
| 41 | 38 | struct rmap_walk_control rwc = { |
| 42 | 39 | .rmap_one = __damon_pa_mkold, |
| 43 | − .anon_lock = page_lock_anon_vma_read, | |
| 40 | + .anon_lock = folio_lock_anon_vma_read, | |
| 44 | 41 | }; |
| 45 | 42 | bool need_lock; |
| 46 | 43 | |
| 47 | 44 | if (!page) |
| 48 | 45 | return; |
| 46 | + folio = page_folio(page); | |
| 49 | 47 | |
| 50 | − if (!page_mapped(page) || !page_rmapping(page)) { | |
| 51 | − set_page_idle(page); | |
| 48 | + if (!folio_mapped(folio) || !folio_raw_mapping(folio)) { | |
| 49 | + folio_set_idle(folio); | |
| 52 | 50 | goto out; |
| 53 | 51 | } |
| 54 | 52 | |
| 55 | − need_lock = !PageAnon(page) || PageKsm(page); | |
| 56 | − if (need_lock && !trylock_page(page)) | |
| 53 | + need_lock = !folio_test_anon(folio) || folio_test_ksm(folio); | |
| 54 | + if (need_lock && !folio_trylock(folio)) | |
| 57 | 55 | goto out; |
| 58 | 56 | |
| 59 | − rmap_walk(page, &rwc); | |
| 57 | + rmap_walk(folio, &rwc); | |
| 60 | 58 | |
| 61 | 59 | if (need_lock) |
| 62 | − unlock_page(page); | |
| 60 | + folio_unlock(folio); | |
| 63 | 61 | |
| 64 | 62 | out: |
| 65 | − put_page(page); | |
| 63 | + folio_put(folio); | |
| 66 | 64 | } |
| 67 | 65 | |
| 68 | 66 | static void __damon_pa_prepare_access_check(struct damon_ctx *ctx, |
| @@ -89,15 +87,11 @@ struct damon_pa_access_chk_result { · 20 unmodified lines | ||
| 89 | 87 | bool accessed; |
| 90 | 88 | }; |
| 91 | 89 | |
| 92 | −static bool __damon_pa_young(struct page *page, struct vm_area_struct *vma, | |
| 90 | +static bool __damon_pa_young(struct folio *folio, struct vm_area_struct *vma, | |
| 93 | 91 | unsigned long addr, void *arg) |
| 94 | 92 | { |
| 95 | 93 | struct damon_pa_access_chk_result *result = arg; |
| 96 | − struct page_vma_mapped_walk pvmw = { | |
| 97 | − .page = page, | |
| 98 | − .vma = vma, | |
| 99 | − .address = addr, | |
| 100 | − }; | |
| 94 | + DEFINE_FOLIO_VMA_WALK(pvmw, folio, vma, addr, 0); | |
| 101 | 95 | |
| 102 | 96 | result->accessed = false; |
| 103 | 97 | result->page_sz = PAGE_SIZE; |
| @@ -105,12 +99,12 @@ static bool __damon_pa_young(struct page *page, struct vm_area_struct *vma, · 1 unmodified line | ||
| 105 | 99 | addr = pvmw.address; |
| 106 | 100 | if (pvmw.pte) { |
| 107 | 101 | result->accessed = pte_young(*pvmw.pte) || |
| 108 | − !page_is_idle(page) || | |
| 102 | + !folio_test_idle(folio) || | |
| 109 | 103 | mmu_notifier_test_young(vma->vm_mm, addr); |
| 110 | 104 | } else { |
| 111 | 105 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
| 112 | 106 | result->accessed = pmd_young(*pvmw.pmd) || |
| 113 | − !page_is_idle(page) || | |
| 107 | + !folio_test_idle(folio) || | |
| 114 | 108 | mmu_notifier_test_young(vma->vm_mm, addr); |
| 115 | 109 | result->page_sz = ((1UL) << HPAGE_PMD_SHIFT); |
| 116 | 110 | #else |
| @@ -129,6 +123,7 @@ static bool __damon_pa_young(struct page *page, struct vm_area_struct *vma, · 12 unmodified lines | ||
| 129 | 123 | |
| 130 | 124 | static bool damon_pa_young(unsigned long paddr, unsigned long *page_sz) |
| 131 | 125 | { |
| 126 | + struct folio *folio; | |
| 132 | 127 | struct page *page = damon_get_page(PHYS_PFN(paddr)); |
| 133 | 128 | struct damon_pa_access_chk_result result = { |
| 134 | 129 | .page_sz = PAGE_SIZE, |
| @@ -137,33 +132,34 @@ static bool damon_pa_young(unsigned long paddr, unsigned long *page_sz) · 2 unmodified lines | ||
| 137 | 132 | struct rmap_walk_control rwc = { |
| 138 | 133 | .arg = &result, |
| 139 | 134 | .rmap_one = __damon_pa_young, |
| 140 | − .anon_lock = page_lock_anon_vma_read, | |
| 135 | + .anon_lock = folio_lock_anon_vma_read, | |
| 141 | 136 | }; |
| 142 | 137 | bool need_lock; |
| 143 | 138 | |
| 144 | 139 | if (!page) |
| 145 | 140 | return false; |
| 141 | + folio = page_folio(page); | |
| 146 | 142 | |
| 147 | − if (!page_mapped(page) || !page_rmapping(page)) { | |
| 148 | − if (page_is_idle(page)) | |
| 143 | + if (!folio_mapped(folio) || !folio_raw_mapping(folio)) { | |
| 144 | + if (folio_test_idle(folio)) | |
| 149 | 145 | result.accessed = false; |
| 150 | 146 | else |
| 151 | 147 | result.accessed = true; |
| 152 | − put_page(page); | |
| 148 | + folio_put(folio); | |
| 153 | 149 | goto out; |
| 154 | 150 | } |
| 155 | 151 | |
| 156 | − need_lock = !PageAnon(page) || PageKsm(page); | |
| 157 | − if (need_lock && !trylock_page(page)) { | |
| 158 | − put_page(page); | |
| 159 | − return NULL; | |
| 152 | + need_lock = !folio_test_anon(folio) || folio_test_ksm(folio); | |
| 153 | + if (need_lock && !folio_trylock(folio)) { | |
| 154 | + folio_put(folio); | |
| 155 | + return false; | |
| 160 | 156 | } |
| 161 | 157 | |
| 162 | − rmap_walk(page, &rwc); | |
| 158 | + rmap_walk(folio, &rwc); | |
| 163 | 159 | |
| 164 | 160 | if (need_lock) |
| 165 | − unlock_page(page); | |
| 166 | − put_page(page); | |
| 161 | + folio_unlock(folio); | |
| 162 | + folio_put(folio); | |
| 167 | 163 | |
| 168 | 164 | out: |
| 169 | 165 | *page_sz = result.page_sz; |
| @@ -48,7 +48,8 @@ const struct trace_print_flags vmaflag_names[] = { · 47 unmodified lines | ||
| 48 | 48 | |
| 49 | 49 | static void __dump_page(struct page *page) |
| 50 | 50 | { |
| 51 | − struct page *head = compound_head(page); | |
| 51 | + struct folio *folio = page_folio(page); | |
| 52 | + struct page *head = &folio->page; | |
| 52 | 53 | struct address_space *mapping; |
| 53 | 54 | bool compound = PageCompound(page); |
| 54 | 55 | /* |
| @@ -76,6 +77,7 @@ static void __dump_page(struct page *page) · 21 unmodified lines | ||
| 76 | 77 | else |
| 77 | 78 | mapping = (void *)(tmp & ~PAGE_MAPPING_FLAGS); |
| 78 | 79 | head = page; |
| 80 | + folio = (struct folio *)page; | |
| 79 | 81 | compound = false; |
| 80 | 82 | } else { |
| 81 | 83 | mapping = page_mapping(page); |
| @@ -92,16 +94,10 @@ static void __dump_page(struct page *page) · 10 unmodified lines | ||
| 92 | 94 | page, page_ref_count(head), mapcount, mapping, |
| 93 | 95 | page_to_pgoff(page), page_to_pfn(page)); |
| 94 | 96 | if (compound) { |
| 95 | − if (hpage_pincount_available(page)) { | |
| 96 | − pr_warn("head:%p order:%u compound_mapcount:%d compound_pincount:%d\n", | |
| 97 | − head, compound_order(head), | |
| 98 | − head_compound_mapcount(head), | |
| 99 | − head_compound_pincount(head)); | |
| 100 | − } else { | |
| 101 | − pr_warn("head:%p order:%u compound_mapcount:%d\n", | |
| 102 | − head, compound_order(head), | |
| 103 | − head_compound_mapcount(head)); | |
| 104 | − } | |
| 97 | + pr_warn("head:%p order:%u compound_mapcount:%d compound_pincount:%d\n", | |
| 98 | + head, compound_order(head), | |
| 99 | + folio_entire_mapcount(folio), | |
| 100 | + head_compound_pincount(head)); | |
| 105 | 101 | } |
| 106 | 102 | |
| 107 | 103 | #ifdef CONFIG_MEMCG |
| @@ -842,26 +842,27 @@ noinline int __filemap_add_folio(struct address_space *mapping, · 841 unmodified lines | ||
| 842 | 842 | { |
| 843 | 843 | XA_STATE(xas, &mapping->i_pages, index); |
| 844 | 844 | int huge = folio_test_hugetlb(folio); |
| 845 | − int error; | |
| 846 | 845 | bool charged = false; |
| 846 | + long nr = 1; | |
| 847 | 847 | |
| 848 | 848 | VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio); |
| 849 | 849 | VM_BUG_ON_FOLIO(folio_test_swapbacked(folio), folio); |
| 850 | 850 | mapping_set_update(&xas, mapping); |
| 851 | 851 | |
| 852 | − folio_get(folio); | |
| 853 | − folio->mapping = mapping; | |
| 854 | − folio->index = index; | |
| 855 | − | |
| 856 | 852 | if (!huge) { |
| 857 | − error = mem_cgroup_charge(folio, NULL, gfp); | |
| 853 | + int error = mem_cgroup_charge(folio, NULL, gfp); | |
| 858 | 854 | VM_BUG_ON_FOLIO(index & (folio_nr_pages(folio) - 1), folio); |
| 859 | 855 | if (error) |
| 860 | − goto error; | |
| 856 | + return error; | |
| 861 | 857 | charged = true; |
| 858 | + xas_set_order(&xas, index, folio_order(folio)); | |
| 859 | + nr = folio_nr_pages(folio); | |
| 862 | 860 | } |
| 863 | 861 | |
| 864 | 862 | gfp &= GFP_RECLAIM_MASK; |
| 863 | + folio_ref_add(folio, nr); | |
| 864 | + folio->mapping = mapping; | |
| 865 | + folio->index = xas.xa_index; | |
| 865 | 866 | |
| 866 | 867 | do { |
| 867 | 868 | unsigned int order = xa_get_order(xas.xa, xas.xa_index); |
| @@ -885,6 +886,8 @@ noinline int __filemap_add_folio(struct address_space *mapping, · 17 unmodified lines | ||
| 885 | 886 | /* entry may have been split before we acquired lock */ |
| 886 | 887 | order = xa_get_order(xas.xa, xas.xa_index); |
| 887 | 888 | if (order > folio_order(folio)) { |
| 889 | + /* How to handle large swap entries? */ | |
| 890 | + BUG_ON(shmem_mapping(mapping)); | |
| 888 | 891 | xas_split(&xas, old, order); |
| 889 | 892 | xas_reset(&xas); |
| 890 | 893 | } |
| @@ -894,29 +897,31 @@ noinline int __filemap_add_folio(struct address_space *mapping, · 3 unmodified lines | ||
| 894 | 897 | if (xas_error(&xas)) |
| 895 | 898 | goto unlock; |
| 896 | 899 | |
| 897 | − mapping->nrpages++; | |
| 900 | + mapping->nrpages += nr; | |
| 898 | 901 | |
| 899 | 902 | /* hugetlb pages do not participate in page cache accounting */ |
| 900 | − if (!huge) | |
| 901 | − __lruvec_stat_add_folio(folio, NR_FILE_PAGES); | |
| 903 | + if (!huge) { | |
| 904 | + __lruvec_stat_mod_folio(folio, NR_FILE_PAGES, nr); | |
| 905 | + if (folio_test_pmd_mappable(folio)) | |
| 906 | + __lruvec_stat_mod_folio(folio, | |
| 907 | + NR_FILE_THPS, nr); | |
| 908 | + } | |
| 902 | 909 | unlock: |
| 903 | 910 | xas_unlock_irq(&xas); |
| 904 | 911 | } while (xas_nomem(&xas, gfp)); |
| 905 | 912 | |
| 906 | − if (xas_error(&xas)) { | |
| 907 | − error = xas_error(&xas); | |
| 908 | − if (charged) | |
| 909 | − mem_cgroup_uncharge(folio); | |
| 913 | + if (xas_error(&xas)) | |
| 910 | 914 | goto error; |
| 911 | − } | |
| 912 | 915 | |
| 913 | 916 | trace_mm_filemap_add_to_page_cache(folio); |
| 914 | 917 | return 0; |
| 915 | 918 | error: |
| 919 | + if (charged) | |
| 920 | + mem_cgroup_uncharge(folio); | |
| 916 | 921 | folio->mapping = NULL; |
| 917 | 922 | /* Leave page->index set: truncation relies upon it */ |
| 918 | − folio_put(folio); | |
| 919 | − return error; | |
| 923 | + folio_put_refs(folio, nr); | |
| 924 | + return xas_error(&xas); | |
| 920 | 925 | } |
| 921 | 926 | ALLOW_ERROR_INJECTION(__filemap_add_folio, ERRNO); |
| 922 | 927 | |
| @@ -2997,6 +3002,24 @@ static struct file *do_sync_mmap_readahead(struct vm_fault *vmf) · 2074 unmodified lines | ||
| 2997 | 3002 | struct file *fpin = NULL; |
| 2998 | 3003 | unsigned int mmap_miss; |
| 2999 | 3004 | |
| 3005 | +#ifdef CONFIG_TRANSPARENT_HUGEPAGE | |
| 3006 | + /* Use the readahead code, even if readahead is disabled */ | |
| 3007 | + if (vmf->vma->vm_flags & VM_HUGEPAGE) { | |
| 3008 | + fpin = maybe_unlock_mmap_for_io(vmf, fpin); | |
| 3009 | + ractl._index &= ~((unsigned long)HPAGE_PMD_NR - 1); | |
| 3010 | + ra->size = HPAGE_PMD_NR; | |
| 3011 | + /* | |
| 3012 | + * Fetch two PMD folios, so we get the chance to actually | |
| 3013 | + * readahead, unless we've been told not to. | |
| 3014 | + */ | |
| 3015 | + if (!(vmf->vma->vm_flags & VM_RAND_READ)) | |
| 3016 | + ra->size *= 2; | |
| 3017 | + ra->async_size = HPAGE_PMD_NR; | |
| 3018 | + page_cache_ra_order(&ractl, ra, HPAGE_PMD_ORDER); | |
| 3019 | + return fpin; | |
| 3020 | + } | |
| 3021 | +#endif | |
| 3022 | + | |
| 3000 | 3023 | /* If we don't want any read-ahead, don't bother */ |
| 3001 | 3024 | if (vmf->vma->vm_flags & VM_RAND_READ) |
| 3002 | 3025 | return fpin; |
| @@ -3029,7 +3052,7 @@ static struct file *do_sync_mmap_readahead(struct vm_fault *vmf) · 26 unmodified lines | ||
| 3029 | 3052 | ra->size = ra->ra_pages; |
| 3030 | 3053 | ra->async_size = ra->ra_pages / 4; |
| 3031 | 3054 | ractl._index = ra->start; |
| 3032 | − do_page_cache_ra(&ractl, ra->size, ra->async_size); | |
| 3055 | + page_cache_ra_order(&ractl, ra, 0); | |
| 3033 | 3056 | return fpin; |
| 3034 | 3057 | } |
| 3035 | 3058 | |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <linux/migrate.h> |
| 8 | 8 | #include <linux/pagemap.h> |
| 9 | 9 | #include <linux/swap.h> |
| 10 | +#include "internal.h" | |
| 10 | 11 | |
| 11 | 12 | struct address_space *page_mapping(struct page *page) |
| 12 | 13 | { |
| @@ -151,3 +152,15 @@ int try_to_release_page(struct page *page, gfp_t gfp) · 138 unmodified lines | ||
| 151 | 152 | return filemap_release_folio(page_folio(page), gfp); |
| 152 | 153 | } |
| 153 | 154 | EXPORT_SYMBOL(try_to_release_page); |
| 155 | + | |
| 156 | +int isolate_lru_page(struct page *page) | |
| 157 | +{ | |
| 158 | + if (WARN_RATELIMIT(PageTail(page), "trying to isolate tail page")) | |
| 159 | + return -EBUSY; | |
| 160 | + return folio_isolate_lru((struct folio *)page); | |
| 161 | +} | |
| 162 | + | |
| 163 | +void putback_lru_page(struct page *page) | |
| 164 | +{ | |
| 165 | + folio_putback_lru(page_folio(page)); | |
| 166 | +} | |
| @@ -29,107 +29,71 @@ struct follow_page_context { · 28 unmodified lines | ||
| 29 | 29 | unsigned int page_mask; |
| 30 | 30 | }; |
| 31 | 31 | |
| 32 | −static void hpage_pincount_add(struct page *page, int refs) | |
| 33 | −{ | |
| 34 | − VM_BUG_ON_PAGE(!hpage_pincount_available(page), page); | |
| 35 | − VM_BUG_ON_PAGE(page != compound_head(page), page); | |
| 36 | − | |
| 37 | − atomic_add(refs, compound_pincount_ptr(page)); | |
| 38 | −} | |
| 39 | − | |
| 40 | −static void hpage_pincount_sub(struct page *page, int refs) | |
| 41 | −{ | |
| 42 | − VM_BUG_ON_PAGE(!hpage_pincount_available(page), page); | |
| 43 | − VM_BUG_ON_PAGE(page != compound_head(page), page); | |
| 44 | − | |
| 45 | − atomic_sub(refs, compound_pincount_ptr(page)); | |
| 46 | −} | |
| 47 | − | |
| 48 | −/* Equivalent to calling put_page() @refs times. */ | |
| 49 | −static void put_page_refs(struct page *page, int refs) | |
| 50 | −{ | |
| 51 | −#ifdef CONFIG_DEBUG_VM | |
| 52 | − if (VM_WARN_ON_ONCE_PAGE(page_ref_count(page) < refs, page)) | |
| 53 | − return; | |
| 54 | −#endif | |
| 55 | − | |
| 56 | − /* | |
| 57 | − * Calling put_page() for each ref is unnecessarily slow. Only the last | |
| 58 | − * ref needs a put_page(). | |
| 59 | − */ | |
| 60 | − if (refs > 1) | |
| 61 | − page_ref_sub(page, refs - 1); | |
| 62 | − put_page(page); | |
| 63 | −} | |
| 64 | − | |
| 65 | 32 | /* |
| 66 | − * Return the compound head page with ref appropriately incremented, | |
| 33 | + * Return the folio with ref appropriately incremented, | |
| 67 | 34 | * or NULL if that failed. |
| 68 | 35 | */ |
| 69 | −static inline struct page *try_get_compound_head(struct page *page, int refs) | |
| 36 | +static inline struct folio *try_get_folio(struct page *page, int refs) | |
| 70 | 37 | { |
| 71 | − struct page *head = compound_head(page); | |
| 38 | + struct folio *folio; | |
| 72 | 39 | |
| 73 | − if (WARN_ON_ONCE(page_ref_count(head) < 0)) | |
| 40 | +retry: | |
| 41 | + folio = page_folio(page); | |
| 42 | + if (WARN_ON_ONCE(folio_ref_count(folio) < 0)) | |
| 74 | 43 | return NULL; |
| 75 | − if (unlikely(!page_cache_add_speculative(head, refs))) | |
| 44 | + if (unlikely(!folio_ref_try_add_rcu(folio, refs))) | |
| 76 | 45 | return NULL; |
| 77 | 46 | |
| 78 | 47 | /* |
| 79 | − * At this point we have a stable reference to the head page; but it | |
| 80 | − * could be that between the compound_head() lookup and the refcount | |
| 81 | − * increment, the compound page was split, in which case we'd end up | |
| 82 | − * holding a reference on a page that has nothing to do with the page | |
| 48 | + * At this point we have a stable reference to the folio; but it | |
| 49 | + * could be that between calling page_folio() and the refcount | |
| 50 | + * increment, the folio was split, in which case we'd end up | |
| 51 | + * holding a reference on a folio that has nothing to do with the page | |
| 83 | 52 | * we were given anymore. |
| 84 | − * So now that the head page is stable, recheck that the pages still | |
| 85 | − * belong together. | |
| 53 | + * So now that the folio is stable, recheck that the page still | |
| 54 | + * belongs to this folio. | |
| 86 | 55 | */ |
| 87 | − if (unlikely(compound_head(page) != head)) { | |
| 88 | − put_page_refs(head, refs); | |
| 89 | − return NULL; | |
| 56 | + if (unlikely(page_folio(page) != folio)) { | |
| 57 | + folio_put_refs(folio, refs); | |
| 58 | + goto retry; | |
| 90 | 59 | } |
| 91 | 60 | |
| 92 | − return head; | |
| 61 | + return folio; | |
| 93 | 62 | } |
| 94 | 63 | |
| 95 | 64 | /** |
| 96 | − * try_grab_compound_head() - attempt to elevate a page's refcount, by a | |
| 97 | − * flags-dependent amount. | |
| 98 | − * | |
| 99 | − * Even though the name includes "compound_head", this function is still | |
| 100 | − * appropriate for callers that have a non-compound @page to get. | |
| 101 | − * | |
| 65 | + * try_grab_folio() - Attempt to get or pin a folio. | |
| 102 | 66 | * @page: pointer to page to be grabbed |
| 103 | − * @refs: the value to (effectively) add to the page's refcount | |
| 67 | + * @refs: the value to (effectively) add to the folio's refcount | |
| 104 | 68 | * @flags: gup flags: these are the FOLL_* flag values. |
| 105 | 69 | * |
| 106 | 70 | * "grab" names in this file mean, "look at flags to decide whether to use |
| 107 | − * FOLL_PIN or FOLL_GET behavior, when incrementing the page's refcount. | |
| 71 | + * FOLL_PIN or FOLL_GET behavior, when incrementing the folio's refcount. | |
| 108 | 72 | * |
| 109 | 73 | * Either FOLL_PIN or FOLL_GET (or neither) must be set, but not both at the |
| 110 | 74 | * same time. (That's true throughout the get_user_pages*() and |
| 111 | 75 | * pin_user_pages*() APIs.) Cases: |
| 112 | 76 | * |
| 113 | − * FOLL_GET: page's refcount will be incremented by @refs. | |
| 77 | + * FOLL_GET: folio's refcount will be incremented by @refs. | |
| 114 | 78 | * |
| 115 | − * FOLL_PIN on compound pages that are > two pages long: page's refcount will | |
| 116 | − * be incremented by @refs, and page[2].hpage_pinned_refcount will be | |
| 117 | − * incremented by @refs * GUP_PIN_COUNTING_BIAS. | |
| 79 | + * FOLL_PIN on large folios: folio's refcount will be incremented by | |
| 80 | + * @refs, and its compound_pincount will be incremented by @refs. | |
| 118 | 81 | * |
| 119 | − * FOLL_PIN on normal pages, or compound pages that are two pages long: | |
| 120 | − * page's refcount will be incremented by @refs * GUP_PIN_COUNTING_BIAS. | |
| 82 | + * FOLL_PIN on single-page folios: folio's refcount will be incremented by | |
| 83 | + * @refs * GUP_PIN_COUNTING_BIAS. | |
| 121 | 84 | * |
| 122 | − * Return: head page (with refcount appropriately incremented) for success, or | |
| 123 | − * NULL upon failure. If neither FOLL_GET nor FOLL_PIN was set, that's | |
| 124 | − * considered failure, and furthermore, a likely bug in the caller, so a warning | |
| 125 | − * is also emitted. | |
| 85 | + * Return: The folio containing @page (with refcount appropriately | |
| 86 | + * incremented) for success, or NULL upon failure. If neither FOLL_GET | |
| 87 | + * nor FOLL_PIN was set, that's considered failure, and furthermore, | |
| 88 | + * a likely bug in the caller, so a warning is also emitted. | |
| 126 | 89 | */ |
| 127 | −__maybe_unused struct page *try_grab_compound_head(struct page *page, | |
| 128 | − int refs, unsigned int flags) | |
| 90 | +struct folio *try_grab_folio(struct page *page, int refs, unsigned int flags) | |
| 129 | 91 | { |
| 130 | 92 | if (flags & FOLL_GET) |
| 131 | − return try_get_compound_head(page, refs); | |
| 93 | + return try_get_folio(page, refs); | |
| 132 | 94 | else if (flags & FOLL_PIN) { |
| 95 | + struct folio *folio; | |
| 96 | + | |
| 133 | 97 | /* |
| 134 | 98 | * Can't do FOLL_LONGTERM + FOLL_PIN gup fast path if not in a |
| 135 | 99 | * right zone, so fail and let the caller fall back to the slow |
| @@ -143,63 +107,57 @@ __maybe_unused struct page *try_grab_compound_head(struct page *page, · 7 unmodified lines | ||
| 143 | 107 | * CAUTION: Don't use compound_head() on the page before this |
| 144 | 108 | * point, the result won't be stable. |
| 145 | 109 | */ |
| 146 | − page = try_get_compound_head(page, refs); | |
| 147 | − if (!page) | |
| 110 | + folio = try_get_folio(page, refs); | |
| 111 | + if (!folio) | |
| 148 | 112 | return NULL; |
| 149 | 113 | |
| 150 | 114 | /* |
| 151 | − * When pinning a compound page of order > 1 (which is what | |
| 152 | − * hpage_pincount_available() checks for), use an exact count to | |
| 153 | − * track it, via hpage_pincount_add/_sub(). | |
| 115 | + * When pinning a large folio, use an exact count to track it. | |
| 154 | 116 | * |
| 155 | − * However, be sure to *also* increment the normal page refcount | |
| 156 | − * field at least once, so that the page really is pinned. | |
| 157 | − * That's why the refcount from the earlier | |
| 158 | − * try_get_compound_head() is left intact. | |
| 117 | + * However, be sure to *also* increment the normal folio | |
| 118 | + * refcount field at least once, so that the folio really | |
| 119 | + * is pinned. That's why the refcount from the earlier | |
| 120 | + * try_get_folio() is left intact. | |
| 159 | 121 | */ |
| 160 | − if (hpage_pincount_available(page)) | |
| 161 | − hpage_pincount_add(page, refs); | |
| 122 | + if (folio_test_large(folio)) | |
| 123 | + atomic_add(refs, folio_pincount_ptr(folio)); | |
| 162 | 124 | else |
| 163 | − page_ref_add(page, refs * (GUP_PIN_COUNTING_BIAS - 1)); | |
| 164 | − | |
| 165 | − mod_node_page_state(page_pgdat(page), NR_FOLL_PIN_ACQUIRED, | |
| 166 | − refs); | |
| 125 | + folio_ref_add(folio, | |
| 126 | + refs * (GUP_PIN_COUNTING_BIAS - 1)); | |
| 127 | + node_stat_mod_folio(folio, NR_FOLL_PIN_ACQUIRED, refs); | |
| 167 | 128 | |
| 168 | − return page; | |
| 129 | + return folio; | |
| 169 | 130 | } |
| 170 | 131 | |
| 171 | 132 | WARN_ON_ONCE(1); |
| 172 | 133 | return NULL; |
| 173 | 134 | } |
| 174 | 135 | |
| 175 | −static void put_compound_head(struct page *page, int refs, unsigned int flags) | |
| 136 | +static void gup_put_folio(struct folio *folio, int refs, unsigned int flags) | |
| 176 | 137 | { |
| 177 | 138 | if (flags & FOLL_PIN) { |
| 178 | − mod_node_page_state(page_pgdat(page), NR_FOLL_PIN_RELEASED, | |
| 179 | − refs); | |
| 180 | − | |
| 181 | − if (hpage_pincount_available(page)) | |
| 182 | − hpage_pincount_sub(page, refs); | |
| 139 | + node_stat_mod_folio(folio, NR_FOLL_PIN_RELEASED, refs); | |
| 140 | + if (folio_test_large(folio)) | |
| 141 | + atomic_sub(refs, folio_pincount_ptr(folio)); | |
| 183 | 142 | else |
| 184 | 143 | refs *= GUP_PIN_COUNTING_BIAS; |
| 185 | 144 | } |
| 186 | 145 | |
| 187 | − put_page_refs(page, refs); | |
| 146 | + folio_put_refs(folio, refs); | |
| 188 | 147 | } |
| 189 | 148 | |
| 190 | 149 | /** |
| 191 | 150 | * try_grab_page() - elevate a page's refcount by a flag-dependent amount |
| 151 | + * @page: pointer to page to be grabbed | |
| 152 | + * @flags: gup flags: these are the FOLL_* flag values. | |
| 192 | 153 | * |
| 193 | 154 | * This might not do anything at all, depending on the flags argument. |
| 194 | 155 | * |
| 195 | 156 | * "grab" names in this file mean, "look at flags to decide whether to use |
| 196 | 157 | * FOLL_PIN or FOLL_GET behavior, when incrementing the page's refcount. |
| 197 | 158 | * |
| 198 | − * @page: pointer to page to be grabbed | |
| 199 | − * @flags: gup flags: these are the FOLL_* flag values. | |
| 200 | − * | |
| 201 | 159 | * Either FOLL_PIN or FOLL_GET (or neither) may be set, but not both at the same |
| 202 | − * time. Cases: please see the try_grab_compound_head() documentation, with | |
| 160 | + * time. Cases: please see the try_grab_folio() documentation, with | |
| 203 | 161 | * "refs=1". |
| 204 | 162 | * |
| 205 | 163 | * Return: true for success, or if no action was required (if neither FOLL_PIN |
| @@ -208,32 +166,28 @@ static void put_compound_head(struct page *page, int refs, unsigned int flags) · 2 unmodified lines | ||
| 208 | 166 | */ |
| 209 | 167 | bool __must_check try_grab_page(struct page *page, unsigned int flags) |
| 210 | 168 | { |
| 169 | + struct folio *folio = page_folio(page); | |
| 170 | + | |
| 211 | 171 | WARN_ON_ONCE((flags & (FOLL_GET | FOLL_PIN)) == (FOLL_GET | FOLL_PIN)); |
| 172 | + if (WARN_ON_ONCE(folio_ref_count(folio) <= 0)) | |
| 173 | + return false; | |
| 212 | 174 | |
| 213 | 175 | if (flags & FOLL_GET) |
| 214 | − return try_get_page(page); | |
| 176 | + folio_ref_inc(folio); | |
| 215 | 177 | else if (flags & FOLL_PIN) { |
| 216 | − int refs = 1; | |
| 217 | − | |
| 218 | − page = compound_head(page); | |
| 219 | − | |
| 220 | − if (WARN_ON_ONCE(page_ref_count(page) <= 0)) | |
| 221 | − return false; | |
| 222 | − | |
| 223 | − if (hpage_pincount_available(page)) | |
| 224 | − hpage_pincount_add(page, 1); | |
| 225 | − else | |
| 226 | − refs = GUP_PIN_COUNTING_BIAS; | |
| 227 | − | |
| 228 | 178 | /* |
| 229 | − * Similar to try_grab_compound_head(): even if using the | |
| 230 | − * hpage_pincount_add/_sub() routines, be sure to | |
| 231 | − * *also* increment the normal page refcount field at least | |
| 232 | − * once, so that the page really is pinned. | |
| 179 | + * Similar to try_grab_folio(): be sure to *also* | |
| 180 | + * increment the normal page refcount field at least once, | |
| 181 | + * so that the page really is pinned. | |
| 233 | 182 | */ |
| 234 | − page_ref_add(page, refs); | |
| 183 | + if (folio_test_large(folio)) { | |
| 184 | + folio_ref_add(folio, 1); | |
| 185 | + atomic_add(1, folio_pincount_ptr(folio)); | |
| 186 | + } else { | |
| 187 | + folio_ref_add(folio, GUP_PIN_COUNTING_BIAS); | |
| 188 | + } | |
| 235 | 189 | |
| 236 | − mod_node_page_state(page_pgdat(page), NR_FOLL_PIN_ACQUIRED, 1); | |
| 190 | + node_stat_mod_folio(folio, NR_FOLL_PIN_ACQUIRED, 1); | |
| 237 | 191 | } |
| 238 | 192 | |
| 239 | 193 | return true; |
| @@ -250,62 +204,40 @@ bool __must_check try_grab_page(struct page *page, unsigned int flags) · 10 unmodified lines | ||
| 250 | 204 | */ |
| 251 | 205 | void unpin_user_page(struct page *page) |
| 252 | 206 | { |
| 253 | − put_compound_head(compound_head(page), 1, FOLL_PIN); | |
| 207 | + gup_put_folio(page_folio(page), 1, FOLL_PIN); | |
| 254 | 208 | } |
| 255 | 209 | EXPORT_SYMBOL(unpin_user_page); |
| 256 | 210 | |
| 257 | −static inline void compound_range_next(unsigned long i, unsigned long npages, | |
| 258 | − struct page **list, struct page **head, | |
| 259 | − unsigned int *ntails) | |
| 211 | +static inline struct folio *gup_folio_range_next(struct page *start, | |
| 212 | + unsigned long npages, unsigned long i, unsigned int *ntails) | |
| 260 | 213 | { |
| 261 | − struct page *next, *page; | |
| 214 | + struct page *next = nth_page(start, i); | |
| 215 | + struct folio *folio = page_folio(next); | |
| 262 | 216 | unsigned int nr = 1; |
| 263 | 217 | |
| 264 | − if (i >= npages) | |
| 265 | − return; | |
| 266 | − | |
| 267 | − next = *list + i; | |
| 268 | − page = compound_head(next); | |
| 269 | − if (PageCompound(page) && compound_order(page) >= 1) | |
| 270 | − nr = min_t(unsigned int, | |
| 271 | − page + compound_nr(page) - next, npages - i); | |
| 218 | + if (folio_test_large(folio)) | |
| 219 | + nr = min_t(unsigned int, npages - i, | |
| 220 | + folio_nr_pages(folio) - folio_page_idx(folio, next)); | |
| 272 | 221 | |
| 273 | − *head = page; | |
| 274 | 222 | *ntails = nr; |
| 223 | + return folio; | |
| 275 | 224 | } |
| 276 | 225 | |
| 277 | −#define for_each_compound_range(__i, __list, __npages, __head, __ntails) \ | |
| 278 | − for (__i = 0, \ | |
| 279 | − compound_range_next(__i, __npages, __list, &(__head), &(__ntails)); \ | |
| 280 | − __i < __npages; __i += __ntails, \ | |
| 281 | − compound_range_next(__i, __npages, __list, &(__head), &(__ntails))) | |
| 282 | − | |
| 283 | −static inline void compound_next(unsigned long i, unsigned long npages, | |
| 284 | − struct page **list, struct page **head, | |
| 285 | − unsigned int *ntails) | |
| 226 | +static inline struct folio *gup_folio_next(struct page **list, | |
| 227 | + unsigned long npages, unsigned long i, unsigned int *ntails) | |
| 286 | 228 | { |
| 287 | − struct page *page; | |
| 229 | + struct folio *folio = page_folio(list[i]); | |
| 288 | 230 | unsigned int nr; |
| 289 | 231 | |
| 290 | − if (i >= npages) | |
| 291 | − return; | |
| 292 | − | |
| 293 | − page = compound_head(list[i]); | |
| 294 | 232 | for (nr = i + 1; nr < npages; nr++) { |
| 295 | − if (compound_head(list[nr]) != page) | |
| 233 | + if (page_folio(list[nr]) != folio) | |
| 296 | 234 | break; |
| 297 | 235 | } |
| 298 | 236 | |
| 299 | − *head = page; | |
| 300 | 237 | *ntails = nr - i; |
| 238 | + return folio; | |
| 301 | 239 | } |
| 302 | 240 | |
| 303 | −#define for_each_compound_head(__i, __list, __npages, __head, __ntails) \ | |
| 304 | − for (__i = 0, \ | |
| 305 | − compound_next(__i, __npages, __list, &(__head), &(__ntails)); \ | |
| 306 | − __i < __npages; __i += __ntails, \ | |
| 307 | − compound_next(__i, __npages, __list, &(__head), &(__ntails))) | |
| 308 | − | |
| 309 | 241 | /** |
| 310 | 242 | * unpin_user_pages_dirty_lock() - release and optionally dirty gup-pinned pages |
| 311 | 243 | * @pages: array of pages to be maybe marked dirty, and definitely released. |
| @@ -331,16 +263,17 @@ static inline void compound_next(unsigned long i, unsigned long npages, · 19 unmodified lines | ||
| 331 | 263 | void unpin_user_pages_dirty_lock(struct page **pages, unsigned long npages, |
| 332 | 264 | bool make_dirty) |
| 333 | 265 | { |
| 334 | − unsigned long index; | |
| 335 | − struct page *head; | |
| 336 | − unsigned int ntails; | |
| 266 | + unsigned long i; | |
| 267 | + struct folio *folio; | |
| 268 | + unsigned int nr; | |
| 337 | 269 | |
| 338 | 270 | if (!make_dirty) { |
| 339 | 271 | unpin_user_pages(pages, npages); |
| 340 | 272 | return; |
| 341 | 273 | } |
| 342 | 274 | |
| 343 | − for_each_compound_head(index, pages, npages, head, ntails) { | |
| 275 | + for (i = 0; i < npages; i += nr) { | |
| 276 | + folio = gup_folio_next(pages, npages, i, &nr); | |
| 344 | 277 | /* |
| 345 | 278 | * Checking PageDirty at this point may race with |
| 346 | 279 | * clear_page_dirty_for_io(), but that's OK. Two key |
| @@ -361,9 +294,12 @@ void unpin_user_pages_dirty_lock(struct page **pages, unsigned long npages, · 14 unmodified lines | ||
| 361 | 294 | * written back, so it gets written back again in the |
| 362 | 295 | * next writeback cycle. This is harmless. |
| 363 | 296 | */ |
| 364 | − if (!PageDirty(head)) | |
| 365 | − set_page_dirty_lock(head); | |
| 366 | − put_compound_head(head, ntails, FOLL_PIN); | |
| 297 | + if (!folio_test_dirty(folio)) { | |
| 298 | + folio_lock(folio); | |
| 299 | + folio_mark_dirty(folio); | |
| 300 | + folio_unlock(folio); | |
| 301 | + } | |
| 302 | + gup_put_folio(folio, nr, FOLL_PIN); | |
| 367 | 303 | } |
| 368 | 304 | } |
| 369 | 305 | EXPORT_SYMBOL(unpin_user_pages_dirty_lock); |
| @@ -392,14 +328,18 @@ EXPORT_SYMBOL(unpin_user_pages_dirty_lock); · 22 unmodified lines | ||
| 392 | 328 | void unpin_user_page_range_dirty_lock(struct page *page, unsigned long npages, |
| 393 | 329 | bool make_dirty) |
| 394 | 330 | { |
| 395 | − unsigned long index; | |
| 396 | − struct page *head; | |
| 397 | − unsigned int ntails; | |
| 331 | + unsigned long i; | |
| 332 | + struct folio *folio; | |
| 333 | + unsigned int nr; | |
| 398 | 334 | |
| 399 | − for_each_compound_range(index, &page, npages, head, ntails) { | |
| 400 | − if (make_dirty && !PageDirty(head)) | |
| 401 | − set_page_dirty_lock(head); | |
| 402 | − put_compound_head(head, ntails, FOLL_PIN); | |
| 335 | + for (i = 0; i < npages; i += nr) { | |
| 336 | + folio = gup_folio_range_next(page, npages, i, &nr); | |
| 337 | + if (make_dirty && !folio_test_dirty(folio)) { | |
| 338 | + folio_lock(folio); | |
| 339 | + folio_mark_dirty(folio); | |
| 340 | + folio_unlock(folio); | |
| 341 | + } | |
| 342 | + gup_put_folio(folio, nr, FOLL_PIN); | |
| 403 | 343 | } |
| 404 | 344 | } |
| 405 | 345 | EXPORT_SYMBOL(unpin_user_page_range_dirty_lock); |
| @@ -415,9 +355,9 @@ EXPORT_SYMBOL(unpin_user_page_range_dirty_lock); · 9 unmodified lines | ||
| 415 | 355 | */ |
| 416 | 356 | void unpin_user_pages(struct page **pages, unsigned long npages) |
| 417 | 357 | { |
| 418 | − unsigned long index; | |
| 419 | − struct page *head; | |
| 420 | − unsigned int ntails; | |
| 358 | + unsigned long i; | |
| 359 | + struct folio *folio; | |
| 360 | + unsigned int nr; | |
| 421 | 361 | |
| 422 | 362 | /* |
| 423 | 363 | * If this WARN_ON() fires, then the system *might* be leaking pages (by |
| @@ -427,8 +367,10 @@ void unpin_user_pages(struct page **pages, unsigned long npages) · 3 unmodified lines | ||
| 427 | 367 | if (WARN_ON(IS_ERR_VALUE(npages))) |
| 428 | 368 | return; |
| 429 | 369 | |
| 430 | − for_each_compound_head(index, pages, npages, head, ntails) | |
| 431 | − put_compound_head(head, ntails, FOLL_PIN); | |
| 370 | + for (i = 0; i < npages; i += nr) { | |
| 371 | + folio = gup_folio_next(pages, npages, i, &nr); | |
| 372 | + gup_put_folio(folio, nr, FOLL_PIN); | |
| 373 | + } | |
| 432 | 374 | } |
| 433 | 375 | EXPORT_SYMBOL(unpin_user_pages); |
| 434 | 376 | |
| @@ -593,32 +535,6 @@ retry: · 158 unmodified lines | ||
| 593 | 535 | */ |
| 594 | 536 | mark_page_accessed(page); |
| 595 | 537 | } |
| 596 | − if ((flags & FOLL_MLOCK) && (vma->vm_flags & VM_LOCKED)) { | |
| 597 | − /* Do not mlock pte-mapped THP */ | |
| 598 | − if (PageTransCompound(page)) | |
| 599 | − goto out; | |
| 600 | − | |
| 601 | − /* | |
| 602 | − * The preliminary mapping check is mainly to avoid the | |
| 603 | − * pointless overhead of lock_page on the ZERO_PAGE | |
| 604 | − * which might bounce very badly if there is contention. | |
| 605 | − * | |
| 606 | − * If the page is already locked, we don't need to | |
| 607 | − * handle it now - vmscan will handle it later if and | |
| 608 | − * when it attempts to reclaim the page. | |
| 609 | − */ | |
| 610 | − if (page->mapping && trylock_page(page)) { | |
| 611 | − lru_add_drain(); /* push cached pages to LRU */ | |
| 612 | − /* | |
| 613 | − * Because we lock page here, and migration is | |
| 614 | − * blocked by the pte's page reference, and we | |
| 615 | − * know the page is still mapped, we don't even | |
| 616 | − * need to check for file-cache page truncation. | |
| 617 | − */ | |
| 618 | − mlock_vma_page(page); | |
| 619 | − unlock_page(page); | |
| 620 | − } | |
| 621 | − } | |
| 622 | 538 | out: |
| 623 | 539 | pte_unmap_unlock(ptep, ptl); |
| 624 | 540 | return page; |
| @@ -941,9 +857,6 @@ static int faultin_page(struct vm_area_struct *vma, · 316 unmodified lines | ||
| 941 | 857 | unsigned int fault_flags = 0; |
| 942 | 858 | vm_fault_t ret; |
| 943 | 859 | |
| 944 | − /* mlock all present pages, but do not fault in new pages */ | |
| 945 | − if ((*flags & (FOLL_POPULATE | FOLL_MLOCK)) == FOLL_MLOCK) | |
| 946 | − return -ENOENT; | |
| 947 | 860 | if (*flags & FOLL_NOFAULT) |
| 948 | 861 | return -EFAULT; |
| 949 | 862 | if (*flags & FOLL_WRITE) |
| @@ -1194,8 +1107,6 @@ retry: · 244 unmodified lines | ||
| 1194 | 1107 | case -ENOMEM: |
| 1195 | 1108 | case -EHWPOISON: |
| 1196 | 1109 | goto out; |
| 1197 | − case -ENOENT: | |
| 1198 | − goto next_page; | |
| 1199 | 1110 | } |
| 1200 | 1111 | BUG(); |
| 1201 | 1112 | } else if (PTR_ERR(page) == -EEXIST) { |
| @@ -1500,9 +1411,14 @@ long populate_vma_page_range(struct vm_area_struct *vma, · 298 unmodified lines | ||
| 1500 | 1411 | VM_BUG_ON_VMA(end > vma->vm_end, vma); |
| 1501 | 1412 | mmap_assert_locked(mm); |
| 1502 | 1413 | |
| 1503 | − gup_flags = FOLL_TOUCH | FOLL_POPULATE | FOLL_MLOCK; | |
| 1414 | + /* | |
| 1415 | + * Rightly or wrongly, the VM_LOCKONFAULT case has never used | |
| 1416 | + * faultin_page() to break COW, so it has no work to do here. | |
| 1417 | + */ | |
| 1504 | 1418 | if (vma->vm_flags & VM_LOCKONFAULT) |
| 1505 | − gup_flags &= ~FOLL_POPULATE; | |
| 1419 | + return nr_pages; | |
| 1420 | + | |
| 1421 | + gup_flags = FOLL_TOUCH; | |
| 1506 | 1422 | /* |
| 1507 | 1423 | * We want to touch writable mappings with a write fault in order |
| 1508 | 1424 | * to break COW, except for shared mappings because these don't COW |
| @@ -1569,10 +1485,9 @@ long faultin_vma_page_range(struct vm_area_struct *vma, unsigned long start, · 60 unmodified lines | ||
| 1569 | 1485 | * in the page table. |
| 1570 | 1486 | * FOLL_HWPOISON: Return -EHWPOISON instead of -EFAULT when we hit |
| 1571 | 1487 | * a poisoned page. |
| 1572 | − * FOLL_POPULATE: Always populate memory with VM_LOCKONFAULT. | |
| 1573 | 1488 | * !FOLL_FORCE: Require proper access permissions. |
| 1574 | 1489 | */ |
| 1575 | − gup_flags = FOLL_TOUCH | FOLL_POPULATE | FOLL_MLOCK | FOLL_HWPOISON; | |
| 1490 | + gup_flags = FOLL_TOUCH | FOLL_HWPOISON; | |
| 1576 | 1491 | if (write) |
| 1577 | 1492 | gup_flags |= FOLL_WRITE; |
| 1578 | 1493 | |
| @@ -1852,72 +1767,80 @@ static long check_and_migrate_movable_pages(unsigned long nr_pages, · 273 unmodified lines | ||
| 1852 | 1767 | struct page **pages, |
| 1853 | 1768 | unsigned int gup_flags) |
| 1854 | 1769 | { |
| 1855 | − unsigned long i; | |
| 1856 | − unsigned long isolation_error_count = 0; | |
| 1857 | − bool drain_allow = true; | |
| 1770 | + unsigned long isolation_error_count = 0, i; | |
| 1771 | + struct folio *prev_folio = NULL; | |
| 1858 | 1772 | LIST_HEAD(movable_page_list); |
| 1859 | − long ret = 0; | |
| 1860 | − struct page *prev_head = NULL; | |
| 1861 | − struct page *head; | |
| 1862 | − struct migration_target_control mtc = { | |
| 1863 | − .nid = NUMA_NO_NODE, | |
| 1864 | − .gfp_mask = GFP_USER | __GFP_NOWARN, | |
| 1865 | − }; | |
| 1773 | + bool drain_allow = true; | |
| 1774 | + int ret = 0; | |
| 1866 | 1775 | |
| 1867 | 1776 | for (i = 0; i < nr_pages; i++) { |
| 1868 | − head = compound_head(pages[i]); | |
| 1869 | − if (head == prev_head) | |
| 1777 | + struct folio *folio = page_folio(pages[i]); | |
| 1778 | + | |
| 1779 | + if (folio == prev_folio) | |
| 1870 | 1780 | continue; |
| 1871 | − prev_head = head; | |
| 1781 | + prev_folio = folio; | |
| 1782 | + | |
| 1783 | + if (folio_is_pinnable(folio)) | |
| 1784 | + continue; | |
| 1785 | + | |
| 1872 | 1786 | /* |
| 1873 | − * If we get a movable page, since we are going to be pinning | |
| 1874 | − * these entries, try to move them out if possible. | |
| 1787 | + * Try to move out any movable page before pinning the range. | |
| 1875 | 1788 | */ |
| 1876 | − if (!is_pinnable_page(head)) { | |
| 1877 | − if (PageHuge(head)) { | |
| 1878 | − if (!isolate_huge_page(head, &movable_page_list)) | |
| 1879 | − isolation_error_count++; | |
| 1880 | − } else { | |
| 1881 | − if (!PageLRU(head) && drain_allow) { | |
| 1882 | − lru_add_drain_all(); | |
| 1883 | − drain_allow = false; | |
| 1884 | − } | |
| 1789 | + if (folio_test_hugetlb(folio)) { | |
| 1790 | + if (!isolate_huge_page(&folio->page, | |
| 1791 | + &movable_page_list)) | |
| 1792 | + isolation_error_count++; | |
| 1793 | + continue; | |
| 1794 | + } | |
| 1885 | 1795 | |
| 1886 | − if (isolate_lru_page(head)) { | |
| 1887 | − isolation_error_count++; | |
| 1888 | − continue; | |
| 1889 | − } | |
| 1890 | − list_add_tail(&head->lru, &movable_page_list); | |
| 1891 | − mod_node_page_state(page_pgdat(head), | |
| 1892 | − NR_ISOLATED_ANON + | |
| 1893 | − page_is_file_lru(head), | |
| 1894 | − thp_nr_pages(head)); | |
| 1895 | − } | |
| 1796 | + if (!folio_test_lru(folio) && drain_allow) { | |
| 1797 | + lru_add_drain_all(); | |
| 1798 | + drain_allow = false; | |
| 1799 | + } | |
| 1800 | + | |
| 1801 | + if (folio_isolate_lru(folio)) { | |
| 1802 | + isolation_error_count++; | |
| 1803 | + continue; | |
| 1896 | 1804 | } |
| 1805 | + list_add_tail(&folio->lru, &movable_page_list); | |
| 1806 | + node_stat_mod_folio(folio, | |
| 1807 | + NR_ISOLATED_ANON + folio_is_file_lru(folio), | |
| 1808 | + folio_nr_pages(folio)); | |
| 1897 | 1809 | } |
| 1898 | 1810 | |
| 1811 | + if (!list_empty(&movable_page_list) || isolation_error_count) | |
| 1812 | + goto unpin_pages; | |
| 1813 | + | |
| 1899 | 1814 | /* |
| 1900 | 1815 | * If list is empty, and no isolation errors, means that all pages are |
| 1901 | 1816 | * in the correct zone. |
| 1902 | 1817 | */ |
| 1903 | − if (list_empty(&movable_page_list) && !isolation_error_count) | |
| 1904 | − return nr_pages; | |
| 1818 | + return nr_pages; | |
| 1905 | 1819 | |
| 1820 | +unpin_pages: | |
| 1906 | 1821 | if (gup_flags & FOLL_PIN) { |
| 1907 | 1822 | unpin_user_pages(pages, nr_pages); |
| 1908 | 1823 | } else { |
| 1909 | 1824 | for (i = 0; i < nr_pages; i++) |
| 1910 | 1825 | put_page(pages[i]); |
| 1911 | 1826 | } |
| 1827 | + | |
| 1912 | 1828 | if (!list_empty(&movable_page_list)) { |
| 1829 | + struct migration_target_control mtc = { | |
| 1830 | + .nid = NUMA_NO_NODE, | |
| 1831 | + .gfp_mask = GFP_USER | __GFP_NOWARN, | |
| 1832 | + }; | |
| 1833 | + | |
| 1913 | 1834 | ret = migrate_pages(&movable_page_list, alloc_migration_target, |
| 1914 | 1835 | NULL, (unsigned long)&mtc, MIGRATE_SYNC, |
| 1915 | 1836 | MR_LONGTERM_PIN, NULL); |
| 1916 | − if (ret && !list_empty(&movable_page_list)) | |
| 1917 | − putback_movable_pages(&movable_page_list); | |
| 1837 | + if (ret > 0) /* number of pages not migrated */ | |
| 1838 | + ret = -ENOMEM; | |
| 1918 | 1839 | } |
| 1919 | 1840 | |
| 1920 | − return ret > 0 ? -ENOMEM : ret; | |
| 1841 | + if (ret && !list_empty(&movable_page_list)) | |
| 1842 | + putback_movable_pages(&movable_page_list); | |
| 1843 | + return ret; | |
| 1921 | 1844 | } |
| 1922 | 1845 | #else |
| 1923 | 1846 | static long check_and_migrate_movable_pages(unsigned long nr_pages, |
| @@ -2227,7 +2150,8 @@ static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end, · 303 unmodified lines | ||
| 2227 | 2150 | ptem = ptep = pte_offset_map(&pmd, addr); |
| 2228 | 2151 | do { |
| 2229 | 2152 | pte_t pte = ptep_get_lockless(ptep); |
| 2230 | − struct page *head, *page; | |
| 2153 | + struct page *page; | |
| 2154 | + struct folio *folio; | |
| 2231 | 2155 | |
| 2232 | 2156 | /* |
| 2233 | 2157 | * Similar to the PMD case below, NUMA hinting must take slow |
| @@ -2254,22 +2178,20 @@ static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end, · 20 unmodified lines | ||
| 2254 | 2178 | VM_BUG_ON(!pfn_valid(pte_pfn(pte))); |
| 2255 | 2179 | page = pte_page(pte); |
| 2256 | 2180 | |
| 2257 | − head = try_grab_compound_head(page, 1, flags); | |
| 2258 | − if (!head) | |
| 2181 | + folio = try_grab_folio(page, 1, flags); | |
| 2182 | + if (!folio) | |
| 2259 | 2183 | goto pte_unmap; |
| 2260 | 2184 | |
| 2261 | 2185 | if (unlikely(page_is_secretmem(page))) { |
| 2262 | − put_compound_head(head, 1, flags); | |
| 2186 | + gup_put_folio(folio, 1, flags); | |
| 2263 | 2187 | goto pte_unmap; |
| 2264 | 2188 | } |
| 2265 | 2189 | |
| 2266 | 2190 | if (unlikely(pte_val(pte) != pte_val(*ptep))) { |
| 2267 | − put_compound_head(head, 1, flags); | |
| 2191 | + gup_put_folio(folio, 1, flags); | |
| 2268 | 2192 | goto pte_unmap; |
| 2269 | 2193 | } |
| 2270 | 2194 | |
| 2271 | − VM_BUG_ON_PAGE(compound_head(page) != head, page); | |
| 2272 | − | |
| 2273 | 2195 | /* |
| 2274 | 2196 | * We need to make the page accessible if and only if we are |
| 2275 | 2197 | * going to access its content (the FOLL_PIN case). Please |
| @@ -2279,14 +2201,13 @@ static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end, · 3 unmodified lines | ||
| 2279 | 2201 | if (flags & FOLL_PIN) { |
| 2280 | 2202 | ret = arch_make_page_accessible(page); |
| 2281 | 2203 | if (ret) { |
| 2282 | − unpin_user_page(page); | |
| 2204 | + gup_put_folio(folio, 1, flags); | |
| 2283 | 2205 | goto pte_unmap; |
| 2284 | 2206 | } |
| 2285 | 2207 | } |
| 2286 | − SetPageReferenced(page); | |
| 2208 | + folio_set_referenced(folio); | |
| 2287 | 2209 | pages[*nr] = page; |
| 2288 | 2210 | (*nr)++; |
| 2289 | − | |
| 2290 | 2211 | } while (ptep++, addr += PAGE_SIZE, addr != end); |
| 2291 | 2212 | |
| 2292 | 2213 | ret = 1; |
| @@ -2403,8 +2324,8 @@ static int record_subpages(struct page *page, unsigned long addr, · 110 unmodified lines | ||
| 2403 | 2324 | { |
| 2404 | 2325 | int nr; |
| 2405 | 2326 | |
| 2406 | − for (nr = 0; addr != end; addr += PAGE_SIZE) | |
| 2407 | − pages[nr++] = page++; | |
| 2327 | + for (nr = 0; addr != end; nr++, addr += PAGE_SIZE) | |
| 2328 | + pages[nr] = nth_page(page, nr); | |
| 2408 | 2329 | |
| 2409 | 2330 | return nr; |
| 2410 | 2331 | } |
| @@ -2422,7 +2343,8 @@ static int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr, · 11 unmodified lines | ||
| 2422 | 2343 | struct page **pages, int *nr) |
| 2423 | 2344 | { |
| 2424 | 2345 | unsigned long pte_end; |
| 2425 | − struct page *head, *page; | |
| 2346 | + struct page *page; | |
| 2347 | + struct folio *folio; | |
| 2426 | 2348 | pte_t pte; |
| 2427 | 2349 | int refs; |
| 2428 | 2350 | |
| @@ -2438,21 +2360,20 @@ static int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr, · 9 unmodified lines | ||
| 2438 | 2360 | /* hugepages are never "special" */ |
| 2439 | 2361 | VM_BUG_ON(!pfn_valid(pte_pfn(pte))); |
| 2440 | 2362 | |
| 2441 | − head = pte_page(pte); | |
| 2442 | − page = head + ((addr & (sz-1)) >> PAGE_SHIFT); | |
| 2363 | + page = nth_page(pte_page(pte), (addr & (sz - 1)) >> PAGE_SHIFT); | |
| 2443 | 2364 | refs = record_subpages(page, addr, end, pages + *nr); |
| 2444 | 2365 | |
| 2445 | − head = try_grab_compound_head(head, refs, flags); | |
| 2446 | − if (!head) | |
| 2366 | + folio = try_grab_folio(page, refs, flags); | |
| 2367 | + if (!folio) | |
| 2447 | 2368 | return 0; |
| 2448 | 2369 | |
| 2449 | 2370 | if (unlikely(pte_val(pte) != pte_val(*ptep))) { |
| 2450 | − put_compound_head(head, refs, flags); | |
| 2371 | + gup_put_folio(folio, refs, flags); | |
| 2451 | 2372 | return 0; |
| 2452 | 2373 | } |
| 2453 | 2374 | |
| 2454 | 2375 | *nr += refs; |
| 2455 | − SetPageReferenced(head); | |
| 2376 | + folio_set_referenced(folio); | |
| 2456 | 2377 | return 1; |
| 2457 | 2378 | } |
| 2458 | 2379 | |
| @@ -2486,7 +2407,8 @@ static int gup_huge_pmd(pmd_t orig, pmd_t *pmdp, unsigned long addr, · 27 unmodified lines | ||
| 2486 | 2407 | unsigned long end, unsigned int flags, |
| 2487 | 2408 | struct page **pages, int *nr) |
| 2488 | 2409 | { |
| 2489 | − struct page *head, *page; | |
| 2410 | + struct page *page; | |
| 2411 | + struct folio *folio; | |
| 2490 | 2412 | int refs; |
| 2491 | 2413 | |
| 2492 | 2414 | if (!pmd_access_permitted(orig, flags & FOLL_WRITE)) |
| @@ -2499,20 +2421,20 @@ static int gup_huge_pmd(pmd_t orig, pmd_t *pmdp, unsigned long addr, · 6 unmodified lines | ||
| 2499 | 2421 | pages, nr); |
| 2500 | 2422 | } |
| 2501 | 2423 | |
| 2502 | − page = pmd_page(orig) + ((addr & ~PMD_MASK) >> PAGE_SHIFT); | |
| 2424 | + page = nth_page(pmd_page(orig), (addr & ~PMD_MASK) >> PAGE_SHIFT); | |
| 2503 | 2425 | refs = record_subpages(page, addr, end, pages + *nr); |
| 2504 | 2426 | |
| 2505 | − head = try_grab_compound_head(pmd_page(orig), refs, flags); | |
| 2506 | − if (!head) | |
| 2427 | + folio = try_grab_folio(page, refs, flags); | |
| 2428 | + if (!folio) | |
| 2507 | 2429 | return 0; |
| 2508 | 2430 | |
| 2509 | 2431 | if (unlikely(pmd_val(orig) != pmd_val(*pmdp))) { |
| 2510 | − put_compound_head(head, refs, flags); | |
| 2432 | + gup_put_folio(folio, refs, flags); | |
| 2511 | 2433 | return 0; |
| 2512 | 2434 | } |
| 2513 | 2435 | |
| 2514 | 2436 | *nr += refs; |
| 2515 | − SetPageReferenced(head); | |
| 2437 | + folio_set_referenced(folio); | |
| 2516 | 2438 | return 1; |
| 2517 | 2439 | } |
| 2518 | 2440 | |
| @@ -2520,7 +2442,8 @@ static int gup_huge_pud(pud_t orig, pud_t *pudp, unsigned long addr, · 1 unmodified line | ||
| 2520 | 2442 | unsigned long end, unsigned int flags, |
| 2521 | 2443 | struct page **pages, int *nr) |
| 2522 | 2444 | { |
| 2523 | − struct page *head, *page; | |
| 2445 | + struct page *page; | |
| 2446 | + struct folio *folio; | |
| 2524 | 2447 | int refs; |
| 2525 | 2448 | |
| 2526 | 2449 | if (!pud_access_permitted(orig, flags & FOLL_WRITE)) |
| @@ -2533,20 +2456,20 @@ static int gup_huge_pud(pud_t orig, pud_t *pudp, unsigned long addr, · 6 unmodified lines | ||
| 2533 | 2456 | pages, nr); |
| 2534 | 2457 | } |
| 2535 | 2458 | |
| 2536 | − page = pud_page(orig) + ((addr & ~PUD_MASK) >> PAGE_SHIFT); | |
| 2459 | + page = nth_page(pud_page(orig), (addr & ~PUD_MASK) >> PAGE_SHIFT); | |
| 2537 | 2460 | refs = record_subpages(page, addr, end, pages + *nr); |
| 2538 | 2461 | |
| 2539 | − head = try_grab_compound_head(pud_page(orig), refs, flags); | |
| 2540 | − if (!head) | |
| 2462 | + folio = try_grab_folio(page, refs, flags); | |
| 2463 | + if (!folio) | |
| 2541 | 2464 | return 0; |
| 2542 | 2465 | |
| 2543 | 2466 | if (unlikely(pud_val(orig) != pud_val(*pudp))) { |
| 2544 | − put_compound_head(head, refs, flags); | |
| 2467 | + gup_put_folio(folio, refs, flags); | |
| 2545 | 2468 | return 0; |
| 2546 | 2469 | } |
| 2547 | 2470 | |
| 2548 | 2471 | *nr += refs; |
| 2549 | − SetPageReferenced(head); | |
| 2472 | + folio_set_referenced(folio); | |
| 2550 | 2473 | return 1; |
| 2551 | 2474 | } |
| 2552 | 2475 | |
| @@ -2555,27 +2478,28 @@ static int gup_huge_pgd(pgd_t orig, pgd_t *pgdp, unsigned long addr, · 2 unmodified lines | ||
| 2555 | 2478 | struct page **pages, int *nr) |
| 2556 | 2479 | { |
| 2557 | 2480 | int refs; |
| 2558 | − struct page *head, *page; | |
| 2481 | + struct page *page; | |
| 2482 | + struct folio *folio; | |
| 2559 | 2483 | |
| 2560 | 2484 | if (!pgd_access_permitted(orig, flags & FOLL_WRITE)) |
| 2561 | 2485 | return 0; |
| 2562 | 2486 | |
| 2563 | 2487 | BUILD_BUG_ON(pgd_devmap(orig)); |
| 2564 | 2488 | |
| 2565 | − page = pgd_page(orig) + ((addr & ~PGDIR_MASK) >> PAGE_SHIFT); | |
| 2489 | + page = nth_page(pgd_page(orig), (addr & ~PGDIR_MASK) >> PAGE_SHIFT); | |
| 2566 | 2490 | refs = record_subpages(page, addr, end, pages + *nr); |
| 2567 | 2491 | |
| 2568 | − head = try_grab_compound_head(pgd_page(orig), refs, flags); | |
| 2569 | − if (!head) | |
| 2492 | + folio = try_grab_folio(page, refs, flags); | |
| 2493 | + if (!folio) | |
| 2570 | 2494 | return 0; |
| 2571 | 2495 | |
| 2572 | 2496 | if (unlikely(pgd_val(orig) != pgd_val(*pgdp))) { |
| 2573 | − put_compound_head(head, refs, flags); | |
| 2497 | + gup_put_folio(folio, refs, flags); | |
| 2574 | 2498 | return 0; |
| 2575 | 2499 | } |
| 2576 | 2500 | |
| 2577 | 2501 | *nr += refs; |
| 2578 | − SetPageReferenced(head); | |
| 2502 | + folio_set_referenced(folio); | |
| 2579 | 2503 | return 1; |
| 2580 | 2504 | } |
| 2581 | 2505 | |
| @@ -583,13 +583,10 @@ unsigned long thp_get_unmapped_area(struct file *filp, unsigned long addr, · 582 unmodified lines | ||
| 583 | 583 | unsigned long ret; |
| 584 | 584 | loff_t off = (loff_t)pgoff << PAGE_SHIFT; |
| 585 | 585 | |
| 586 | − if (!IS_DAX(filp->f_mapping->host) || !IS_ENABLED(CONFIG_FS_DAX_PMD)) | |
| 587 | − goto out; | |
| 588 | − | |
| 589 | 586 | ret = __thp_get_unmapped_area(filp, addr, len, off, flags, PMD_SIZE); |
| 590 | 587 | if (ret) |
| 591 | 588 | return ret; |
| 592 | −out: | |
| 589 | + | |
| 593 | 590 | return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags); |
| 594 | 591 | } |
| 595 | 592 | EXPORT_SYMBOL_GPL(thp_get_unmapped_area); |
| @@ -1381,39 +1378,6 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma, · 785 unmodified lines | ||
| 1381 | 1378 | if (flags & FOLL_TOUCH) |
| 1382 | 1379 | touch_pmd(vma, addr, pmd, flags); |
| 1383 | 1380 | |
| 1384 | − if ((flags & FOLL_MLOCK) && (vma->vm_flags & VM_LOCKED)) { | |
| 1385 | − /* | |
| 1386 | − * We don't mlock() pte-mapped THPs. This way we can avoid | |
| 1387 | − * leaking mlocked pages into non-VM_LOCKED VMAs. | |
| 1388 | − * | |
| 1389 | − * For anon THP: | |
| 1390 | − * | |
| 1391 | − * In most cases the pmd is the only mapping of the page as we | |
| 1392 | − * break COW for the mlock() -- see gup_flags |= FOLL_WRITE for | |
| 1393 | − * writable private mappings in populate_vma_page_range(). | |
| 1394 | − * | |
| 1395 | − * The only scenario when we have the page shared here is if we | |
| 1396 | − * mlocking read-only mapping shared over fork(). We skip | |
| 1397 | − * mlocking such pages. | |
| 1398 | − * | |
| 1399 | − * For file THP: | |
| 1400 | − * | |
| 1401 | − * We can expect PageDoubleMap() to be stable under page lock: | |
| 1402 | − * for file pages we set it in page_add_file_rmap(), which | |
| 1403 | − * requires page to be locked. | |
| 1404 | − */ | |
| 1405 | − | |
| 1406 | − if (PageAnon(page) && compound_mapcount(page) != 1) | |
| 1407 | − goto skip_mlock; | |
| 1408 | − if (PageDoubleMap(page) || !page->mapping) | |
| 1409 | − goto skip_mlock; | |
| 1410 | − if (!trylock_page(page)) | |
| 1411 | − goto skip_mlock; | |
| 1412 | − if (page->mapping && !PageDoubleMap(page)) | |
| 1413 | − mlock_vma_page(page); | |
| 1414 | − unlock_page(page); | |
| 1415 | − } | |
| 1416 | −skip_mlock: | |
| 1417 | 1381 | page += (addr & ~HPAGE_PMD_MASK) >> PAGE_SHIFT; |
| 1418 | 1382 | VM_BUG_ON_PAGE(!PageCompound(page) && !is_zone_device_page(page), page); |
| 1419 | 1383 | |
| @@ -1611,7 +1575,7 @@ int zap_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma, · 191 unmodified lines | ||
| 1611 | 1575 | |
| 1612 | 1576 | if (pmd_present(orig_pmd)) { |
| 1613 | 1577 | page = pmd_page(orig_pmd); |
| 1614 | − page_remove_rmap(page, true); | |
| 1578 | + page_remove_rmap(page, vma, true); | |
| 1615 | 1579 | VM_BUG_ON_PAGE(page_mapcount(page) < 0, page); |
| 1616 | 1580 | VM_BUG_ON_PAGE(!PageHead(page), page); |
| 1617 | 1581 | } else if (thp_migration_supported()) { |
| @@ -2007,7 +1971,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd, · 389 unmodified lines | ||
| 2007 | 1971 | set_page_dirty(page); |
| 2008 | 1972 | if (!PageReferenced(page) && pmd_young(old_pmd)) |
| 2009 | 1973 | SetPageReferenced(page); |
| 2010 | − page_remove_rmap(page, true); | |
| 1974 | + page_remove_rmap(page, vma, true); | |
| 2011 | 1975 | put_page(page); |
| 2012 | 1976 | } |
| 2013 | 1977 | add_mm_counter(mm, mm_counter_file(page), -HPAGE_PMD_NR); |
| @@ -2141,6 +2105,9 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd, · 127 unmodified lines | ||
| 2141 | 2105 | } |
| 2142 | 2106 | } |
| 2143 | 2107 | unlock_page_memcg(page); |
| 2108 | + | |
| 2109 | + /* Above is effectively page_remove_rmap(page, vma, true) */ | |
| 2110 | + munlock_vma_page(page, vma, true); | |
| 2144 | 2111 | } |
| 2145 | 2112 | |
| 2146 | 2113 | smp_wmb(); /* make pte visible before pmd */ |
| @@ -2148,18 +2115,18 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd, · 1 unmodified line | ||
| 2148 | 2115 | |
| 2149 | 2116 | if (freeze) { |
| 2150 | 2117 | for (i = 0; i < HPAGE_PMD_NR; i++) { |
| 2151 | − page_remove_rmap(page + i, false); | |
| 2118 | + page_remove_rmap(page + i, vma, false); | |
| 2152 | 2119 | put_page(page + i); |
| 2153 | 2120 | } |
| 2154 | 2121 | } |
| 2155 | 2122 | } |
| 2156 | 2123 | |
| 2157 | 2124 | void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, |
| 2158 | − unsigned long address, bool freeze, struct page *page) | |
| 2125 | + unsigned long address, bool freeze, struct folio *folio) | |
| 2159 | 2126 | { |
| 2160 | 2127 | spinlock_t *ptl; |
| 2161 | 2128 | struct mmu_notifier_range range; |
| 2162 | − bool do_unlock_page = false; | |
| 2129 | + bool do_unlock_folio = false; | |
| 2163 | 2130 | pmd_t _pmd; |
| 2164 | 2131 | |
| 2165 | 2132 | mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, vma->vm_mm, |
| @@ -2169,20 +2136,20 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, · 3 unmodified lines | ||
| 2169 | 2136 | ptl = pmd_lock(vma->vm_mm, pmd); |
| 2170 | 2137 | |
| 2171 | 2138 | /* |
| 2172 | − * If caller asks to setup a migration entries, we need a page to check | |
| 2173 | − * pmd against. Otherwise we can end up replacing wrong page. | |
| 2139 | + * If caller asks to setup a migration entry, we need a folio to check | |
| 2140 | + * pmd against. Otherwise we can end up replacing wrong folio. | |
| 2174 | 2141 | */ |
| 2175 | − VM_BUG_ON(freeze && !page); | |
| 2176 | − if (page) { | |
| 2177 | − VM_WARN_ON_ONCE(!PageLocked(page)); | |
| 2178 | − if (page != pmd_page(*pmd)) | |
| 2142 | + VM_BUG_ON(freeze && !folio); | |
| 2143 | + if (folio) { | |
| 2144 | + VM_WARN_ON_ONCE(!folio_test_locked(folio)); | |
| 2145 | + if (folio != page_folio(pmd_page(*pmd))) | |
| 2179 | 2146 | goto out; |
| 2180 | 2147 | } |
| 2181 | 2148 | |
| 2182 | 2149 | repeat: |
| 2183 | 2150 | if (pmd_trans_huge(*pmd)) { |
| 2184 | − if (!page) { | |
| 2185 | − page = pmd_page(*pmd); | |
| 2151 | + if (!folio) { | |
| 2152 | + folio = page_folio(pmd_page(*pmd)); | |
| 2186 | 2153 | /* |
| 2187 | 2154 | * An anonymous page must be locked, to ensure that a |
| 2188 | 2155 | * concurrent reuse_swap_page() sees stable mapcount; |
| @@ -2190,33 +2157,31 @@ repeat: · 1 unmodified line | ||
| 2190 | 2157 | * and page lock must not be taken when zap_pmd_range() |
| 2191 | 2158 | * calls __split_huge_pmd() while i_mmap_lock is held. |
| 2192 | 2159 | */ |
| 2193 | − if (PageAnon(page)) { | |
| 2194 | − if (unlikely(!trylock_page(page))) { | |
| 2195 | − get_page(page); | |
| 2160 | + if (folio_test_anon(folio)) { | |
| 2161 | + if (unlikely(!folio_trylock(folio))) { | |
| 2162 | + folio_get(folio); | |
| 2196 | 2163 | _pmd = *pmd; |
| 2197 | 2164 | spin_unlock(ptl); |
| 2198 | − lock_page(page); | |
| 2165 | + folio_lock(folio); | |
| 2199 | 2166 | spin_lock(ptl); |
| 2200 | 2167 | if (unlikely(!pmd_same(*pmd, _pmd))) { |
| 2201 | − unlock_page(page); | |
| 2202 | − put_page(page); | |
| 2203 | − page = NULL; | |
| 2168 | + folio_unlock(folio); | |
| 2169 | + folio_put(folio); | |
| 2170 | + folio = NULL; | |
| 2204 | 2171 | goto repeat; |
| 2205 | 2172 | } |
| 2206 | − put_page(page); | |
| 2173 | + folio_put(folio); | |
| 2207 | 2174 | } |
| 2208 | − do_unlock_page = true; | |
| 2175 | + do_unlock_folio = true; | |
| 2209 | 2176 | } |
| 2210 | 2177 | } |
| 2211 | − if (PageMlocked(page)) | |
| 2212 | − clear_page_mlock(page); | |
| 2213 | 2178 | } else if (!(pmd_devmap(*pmd) || is_pmd_migration_entry(*pmd))) |
| 2214 | 2179 | goto out; |
| 2215 | 2180 | __split_huge_pmd_locked(vma, pmd, range.start, freeze); |
| 2216 | 2181 | out: |
| 2217 | 2182 | spin_unlock(ptl); |
| 2218 | − if (do_unlock_page) | |
| 2219 | − unlock_page(page); | |
| 2183 | + if (do_unlock_folio) | |
| 2184 | + folio_unlock(folio); | |
| 2220 | 2185 | /* |
| 2221 | 2186 | * No need to double call mmu_notifier->invalidate_range() callback. |
| 2222 | 2187 | * They are 3 cases to consider inside __split_huge_pmd_locked(): |
| @@ -2234,7 +2199,7 @@ out: · 11 unmodified lines | ||
| 2234 | 2199 | } |
| 2235 | 2200 | |
| 2236 | 2201 | void split_huge_pmd_address(struct vm_area_struct *vma, unsigned long address, |
| 2237 | − bool freeze, struct page *page) | |
| 2202 | + bool freeze, struct folio *folio) | |
| 2238 | 2203 | { |
| 2239 | 2204 | pgd_t *pgd; |
| 2240 | 2205 | p4d_t *p4d; |
| @@ -2255,7 +2220,7 @@ void split_huge_pmd_address(struct vm_area_struct *vma, unsigned long address, · 14 unmodified lines | ||
| 2255 | 2220 | |
| 2256 | 2221 | pmd = pmd_offset(pud, address); |
| 2257 | 2222 | |
| 2258 | − __split_huge_pmd(vma, pmd, address, freeze, page); | |
| 2223 | + __split_huge_pmd(vma, pmd, address, freeze, folio); | |
| 2259 | 2224 | } |
| 2260 | 2225 | |
| 2261 | 2226 | static inline void split_huge_pmd_if_needed(struct vm_area_struct *vma, unsigned long address) |
| @@ -2295,6 +2260,7 @@ void vma_adjust_trans_huge(struct vm_area_struct *vma, · 33 unmodified lines | ||
| 2295 | 2260 | |
| 2296 | 2261 | static void unmap_page(struct page *page) |
| 2297 | 2262 | { |
| 2263 | + struct folio *folio = page_folio(page); | |
| 2298 | 2264 | enum ttu_flags ttu_flags = TTU_RMAP_LOCKED | TTU_SPLIT_HUGE_PMD | |
| 2299 | 2265 | TTU_SYNC; |
| 2300 | 2266 | |
| @@ -2305,26 +2271,27 @@ static void unmap_page(struct page *page) · 4 unmodified lines | ||
| 2305 | 2271 | * pages can simply be left unmapped, then faulted back on demand. |
| 2306 | 2272 | * If that is ever changed (perhaps for mlock), update remap_page(). |
| 2307 | 2273 | */ |
| 2308 | − if (PageAnon(page)) | |
| 2309 | − try_to_migrate(page, ttu_flags); | |
| 2274 | + if (folio_test_anon(folio)) | |
| 2275 | + try_to_migrate(folio, ttu_flags); | |
| 2310 | 2276 | else |
| 2311 | − try_to_unmap(page, ttu_flags | TTU_IGNORE_MLOCK); | |
| 2277 | + try_to_unmap(folio, ttu_flags | TTU_IGNORE_MLOCK); | |
| 2312 | 2278 | |
| 2313 | 2279 | VM_WARN_ON_ONCE_PAGE(page_mapped(page), page); |
| 2314 | 2280 | } |
| 2315 | 2281 | |
| 2316 | −static void remap_page(struct page *page, unsigned int nr) | |
| 2282 | +static void remap_page(struct folio *folio, unsigned long nr) | |
| 2317 | 2283 | { |
| 2318 | − int i; | |
| 2284 | + int i = 0; | |
| 2319 | 2285 | |
| 2320 | 2286 | /* If unmap_page() uses try_to_migrate() on file, remove this check */ |
| 2321 | − if (!PageAnon(page)) | |
| 2287 | + if (!folio_test_anon(folio)) | |
| 2322 | 2288 | return; |
| 2323 | − if (PageTransHuge(page)) { | |
| 2324 | − remove_migration_ptes(page, page, true); | |
| 2325 | − } else { | |
| 2326 | − for (i = 0; i < nr; i++) | |
| 2327 | − remove_migration_ptes(page + i, page + i, true); | |
| 2289 | + for (;;) { | |
| 2290 | + remove_migration_ptes(folio, folio, true); | |
| 2291 | + i += folio_nr_pages(folio); | |
| 2292 | + if (i >= nr) | |
| 2293 | + break; | |
| 2294 | + folio = folio_next(folio); | |
| 2328 | 2295 | } |
| 2329 | 2296 | } |
| 2330 | 2297 | |
| @@ -2344,8 +2311,11 @@ static void lru_add_page_tail(struct page *head, struct page *tail, · 13 unmodified lines | ||
| 2344 | 2311 | } else { |
| 2345 | 2312 | /* head is still on lru (and we have it frozen) */ |
| 2346 | 2313 | VM_WARN_ON(!PageLRU(head)); |
| 2314 | + if (PageUnevictable(tail)) | |
| 2315 | + tail->mlock_count = 0; | |
| 2316 | + else | |
| 2317 | + list_add_tail(&tail->lru, &head->lru); | |
| 2347 | 2318 | SetPageLRU(tail); |
| 2348 | − list_add_tail(&tail->lru, &head->lru); | |
| 2349 | 2319 | } |
| 2350 | 2320 | } |
| 2351 | 2321 | |
| @@ -2481,7 +2451,7 @@ static void __split_huge_page(struct page *page, struct list_head *list, · 129 unmodified lines | ||
| 2481 | 2451 | } |
| 2482 | 2452 | local_irq_enable(); |
| 2483 | 2453 | |
| 2484 | − remap_page(head, nr); | |
| 2454 | + remap_page(folio, nr); | |
| 2485 | 2455 | |
| 2486 | 2456 | if (PageSwapCache(head)) { |
| 2487 | 2457 | swp_entry_t entry = { .val = page_private(head) }; |
| @@ -2506,30 +2476,6 @@ static void __split_huge_page(struct page *page, struct list_head *list, · 18 unmodified lines | ||
| 2506 | 2476 | } |
| 2507 | 2477 | } |
| 2508 | 2478 | |
| 2509 | −int total_mapcount(struct page *page) | |
| 2510 | −{ | |
| 2511 | − int i, compound, nr, ret; | |
| 2512 | − | |
| 2513 | − VM_BUG_ON_PAGE(PageTail(page), page); | |
| 2514 | − | |
| 2515 | − if (likely(!PageCompound(page))) | |
| 2516 | − return atomic_read(&page->_mapcount) + 1; | |
| 2517 | − | |
| 2518 | − compound = compound_mapcount(page); | |
| 2519 | − nr = compound_nr(page); | |
| 2520 | − if (PageHuge(page)) | |
| 2521 | − return compound; | |
| 2522 | − ret = compound; | |
| 2523 | − for (i = 0; i < nr; i++) | |
| 2524 | − ret += atomic_read(&page[i]._mapcount) + 1; | |
| 2525 | − /* File pages has compound_mapcount included in _mapcount */ | |
| 2526 | − if (!PageAnon(page)) | |
| 2527 | − return ret - compound * nr; | |
| 2528 | − if (PageDoubleMap(page)) | |
| 2529 | − ret -= nr; | |
| 2530 | − return ret; | |
| 2531 | −} | |
| 2532 | − | |
| 2533 | 2479 | /* |
| 2534 | 2480 | * This calculates accurately how many mappings a transparent hugepage |
| 2535 | 2481 | * has (unlike page_mapcount() which isn't fully accurate). This full |
| @@ -2579,18 +2525,19 @@ int page_trans_huge_mapcount(struct page *page) · 43 unmodified lines | ||
| 2579 | 2525 | } |
| 2580 | 2526 | |
| 2581 | 2527 | /* Racy check whether the huge page can be split */ |
| 2582 | −bool can_split_huge_page(struct page *page, int *pextra_pins) | |
| 2528 | +bool can_split_folio(struct folio *folio, int *pextra_pins) | |
| 2583 | 2529 | { |
| 2584 | 2530 | int extra_pins; |
| 2585 | 2531 | |
| 2586 | 2532 | /* Additional pins from page cache */ |
| 2587 | − if (PageAnon(page)) | |
| 2588 | − extra_pins = PageSwapCache(page) ? thp_nr_pages(page) : 0; | |
| 2533 | + if (folio_test_anon(folio)) | |
| 2534 | + extra_pins = folio_test_swapcache(folio) ? | |
| 2535 | + folio_nr_pages(folio) : 0; | |
| 2589 | 2536 | else |
| 2590 | − extra_pins = thp_nr_pages(page); | |
| 2537 | + extra_pins = folio_nr_pages(folio); | |
| 2591 | 2538 | if (pextra_pins) |
| 2592 | 2539 | *pextra_pins = extra_pins; |
| 2593 | − return total_mapcount(page) == page_count(page) - extra_pins - 1; | |
| 2540 | + return folio_mapcount(folio) == folio_ref_count(folio) - extra_pins - 1; | |
| 2594 | 2541 | } |
| 2595 | 2542 | |
| 2596 | 2543 | /* |
| @@ -2614,7 +2561,8 @@ bool can_split_huge_page(struct page *page, int *pextra_pins) · 17 unmodified lines | ||
| 2614 | 2561 | */ |
| 2615 | 2562 | int split_huge_page_to_list(struct page *page, struct list_head *list) |
| 2616 | 2563 | { |
| 2617 | − struct page *head = compound_head(page); | |
| 2564 | + struct folio *folio = page_folio(page); | |
| 2565 | + struct page *head = &folio->page; | |
| 2618 | 2566 | struct deferred_split *ds_queue = get_deferred_split_queue(head); |
| 2619 | 2567 | XA_STATE(xas, &head->mapping->i_pages, head->index); |
| 2620 | 2568 | struct anon_vma *anon_vma = NULL; |
| @@ -2634,7 +2582,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list) · 13 unmodified lines | ||
| 2634 | 2582 | * The caller does not necessarily hold an mmap_lock that would |
| 2635 | 2583 | * prevent the anon_vma disappearing so we first we take a |
| 2636 | 2584 | * reference to it and then lock the anon_vma for write. This |
| 2637 | − * is similar to page_lock_anon_vma_read except the write lock | |
| 2585 | + * is similar to folio_lock_anon_vma_read except the write lock | |
| 2638 | 2586 | * is taken to serialise against parallel split or collapse |
| 2639 | 2587 | * operations. |
| 2640 | 2588 | */ |
| @@ -2681,7 +2629,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list) · 40 unmodified lines | ||
| 2681 | 2629 | * Racy check if we can split the page, before unmap_page() will |
| 2682 | 2630 | * split PMDs |
| 2683 | 2631 | */ |
| 2684 | − if (!can_split_huge_page(head, &extra_pins)) { | |
| 2632 | + if (!can_split_folio(folio, &extra_pins)) { | |
| 2685 | 2633 | ret = -EBUSY; |
| 2686 | 2634 | goto out_unlock; |
| 2687 | 2635 | } |
| @@ -2731,7 +2679,7 @@ fail: · 43 unmodified lines | ||
| 2731 | 2679 | if (mapping) |
| 2732 | 2680 | xas_unlock(&xas); |
| 2733 | 2681 | local_irq_enable(); |
| 2734 | − remap_page(head, thp_nr_pages(head)); | |
| 2682 | + remap_page(folio, folio_nr_pages(folio)); | |
| 2735 | 2683 | ret = -EBUSY; |
| 2736 | 2684 | } |
| 2737 | 2685 | |
| @@ -2988,7 +2936,7 @@ static int split_huge_pages_pid(int pid, unsigned long vaddr_start, · 250 unmodified lines | ||
| 2988 | 2936 | goto next; |
| 2989 | 2937 | |
| 2990 | 2938 | total++; |
| 2991 | − if (!can_split_huge_page(compound_head(page), NULL)) | |
| 2939 | + if (!can_split_folio(page_folio(page), NULL)) | |
| 2992 | 2940 | goto next; |
| 2993 | 2941 | |
| 2994 | 2942 | if (!trylock_page(page)) |
| @@ -3181,7 +3129,7 @@ void set_pmd_migration_entry(struct page_vma_mapped_walk *pvmw, · 186 unmodified lines | ||
| 3181 | 3129 | if (pmd_soft_dirty(pmdval)) |
| 3182 | 3130 | pmdswp = pmd_swp_mksoft_dirty(pmdswp); |
| 3183 | 3131 | set_pmd_at(mm, address, pvmw->pmd, pmdswp); |
| 3184 | − page_remove_rmap(page, true); | |
| 3132 | + page_remove_rmap(page, vma, true); | |
| 3185 | 3133 | put_page(page); |
| 3186 | 3134 | } |
| 3187 | 3135 | |
| @@ -3210,10 +3158,8 @@ void remove_migration_pmd(struct page_vma_mapped_walk *pvmw, struct page *new) · 22 unmodified lines | ||
| 3210 | 3158 | if (PageAnon(new)) |
| 3211 | 3159 | page_add_anon_rmap(new, vma, mmun_start, true); |
| 3212 | 3160 | else |
| 3213 | − page_add_file_rmap(new, true); | |
| 3161 | + page_add_file_rmap(new, vma, true); | |
| 3214 | 3162 | set_pmd_at(mm, mmun_start, pvmw->pmd, pmde); |
| 3215 | − if ((vma->vm_flags & VM_LOCKED) && !PageDoubleMap(new)) | |
| 3216 | − mlock_vma_page(new); | |
| 3217 | 3163 | |
| 3218 | 3164 | /* No need to invalidate - it was non-present before */ |
| 3219 | 3165 | update_mmu_cache_pmd(vma, address, pvmw->pmd); |
| @@ -1321,7 +1321,9 @@ static void __destroy_compound_gigantic_page(struct page *page, · 1320 unmodified lines | ||
| 1321 | 1321 | } |
| 1322 | 1322 | |
| 1323 | 1323 | set_compound_order(page, 0); |
| 1324 | +#ifdef CONFIG_64BIT | |
| 1324 | 1325 | page[1].compound_nr = 0; |
| 1326 | +#endif | |
| 1325 | 1327 | __ClearPageHead(page); |
| 1326 | 1328 | } |
| 1327 | 1329 | |
| @@ -1813,7 +1815,9 @@ out_error: · 485 unmodified lines | ||
| 1813 | 1815 | for (; j < nr_pages; j++, p = mem_map_next(p, page, j)) |
| 1814 | 1816 | __ClearPageReserved(p); |
| 1815 | 1817 | set_compound_order(page, 0); |
| 1818 | +#ifdef CONFIG_64BIT | |
| 1816 | 1819 | page[1].compound_nr = 0; |
| 1820 | +#endif | |
| 1817 | 1821 | __ClearPageHead(page); |
| 1818 | 1822 | return false; |
| 1819 | 1823 | } |
| @@ -5013,7 +5017,7 @@ static void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct · 3193 unmodified lines | ||
| 5013 | 5017 | set_page_dirty(page); |
| 5014 | 5018 | |
| 5015 | 5019 | hugetlb_count_sub(pages_per_huge_page(h), mm); |
| 5016 | − page_remove_rmap(page, true); | |
| 5020 | + page_remove_rmap(page, vma, true); | |
| 5017 | 5021 | |
| 5018 | 5022 | spin_unlock(ptl); |
| 5019 | 5023 | tlb_remove_page_size(tlb, page, huge_page_size(h)); |
| @@ -5258,7 +5262,7 @@ retry_avoidcopy: · 238 unmodified lines | ||
| 5258 | 5262 | /* Break COW */ |
| 5259 | 5263 | huge_ptep_clear_flush(vma, haddr, ptep); |
| 5260 | 5264 | mmu_notifier_invalidate_range(mm, range.start, range.end); |
| 5261 | − page_remove_rmap(old_page, true); | |
| 5265 | + page_remove_rmap(old_page, vma, true); | |
| 5262 | 5266 | hugepage_add_new_anon_rmap(new_page, vma, haddr); |
| 5263 | 5267 | set_huge_pte_at(mm, haddr, ptep, |
| 5264 | 5268 | make_huge_pte(vma, new_page, 1)); |
| @@ -6074,7 +6078,7 @@ long follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, · 809 unmodified lines | ||
| 6074 | 6078 | |
| 6075 | 6079 | if (pages) { |
| 6076 | 6080 | /* |
| 6077 | − * try_grab_compound_head() should always succeed here, | |
| 6081 | + * try_grab_folio() should always succeed here, | |
| 6078 | 6082 | * because: a) we hold the ptl lock, and b) we've just |
| 6079 | 6083 | * checked that the huge page is present in the page |
| 6080 | 6084 | * tables. If the huge page is present, then the tail |
| @@ -6083,9 +6087,8 @@ long follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, · 2 unmodified lines | ||
| 6083 | 6087 | * any way. So this page must be available at this |
| 6084 | 6088 | * point, unless the page refcount overflowed: |
| 6085 | 6089 | */ |
| 6086 | − if (WARN_ON_ONCE(!try_grab_compound_head(pages[i], | |
| 6087 | − refs, | |
| 6088 | − flags))) { | |
| 6090 | + if (WARN_ON_ONCE(!try_grab_folio(pages[i], refs, | |
| 6091 | + flags))) { | |
| 6089 | 6092 | spin_unlock(ptl); |
| 6090 | 6093 | remainder = 0; |
| 6091 | 6094 | err = -ENOMEM; |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | #include <linux/fs.h> |
| 11 | 11 | #include <linux/mm.h> |
| 12 | 12 | #include <linux/pagemap.h> |
| 13 | +#include <linux/rmap.h> | |
| 13 | 14 | #include <linux/tracepoint-defs.h> |
| 14 | 15 | |
| 15 | 16 | struct folio_batch; |
| @@ -66,24 +67,20 @@ static inline void wake_throttle_isolated(pg_data_t *pgdat) · 50 unmodified lines | ||
| 66 | 67 | vm_fault_t do_swap_page(struct vm_fault *vmf); |
| 67 | 68 | void folio_rotate_reclaimable(struct folio *folio); |
| 68 | 69 | bool __folio_end_writeback(struct folio *folio); |
| 70 | +void deactivate_file_folio(struct folio *folio); | |
| 69 | 71 | |
| 70 | 72 | void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *start_vma, |
| 71 | 73 | unsigned long floor, unsigned long ceiling); |
| 72 | 74 | void pmd_install(struct mm_struct *mm, pmd_t *pmd, pgtable_t *pte); |
| 73 | 75 | |
| 74 | −static inline bool can_madv_lru_vma(struct vm_area_struct *vma) | |
| 75 | −{ | |
| 76 | − return !(vma->vm_flags & (VM_LOCKED|VM_HUGETLB|VM_PFNMAP)); | |
| 77 | −} | |
| 78 | − | |
| 79 | 76 | struct zap_details; |
| 80 | 77 | void unmap_page_range(struct mmu_gather *tlb, |
| 81 | 78 | struct vm_area_struct *vma, |
| 82 | 79 | unsigned long addr, unsigned long end, |
| 83 | 80 | struct zap_details *details); |
| 84 | 81 | |
| 85 | −void do_page_cache_ra(struct readahead_control *, unsigned long nr_to_read, | |
| 86 | − unsigned long lookahead_size); | |
| 82 | +void page_cache_ra_order(struct readahead_control *, struct file_ra_state *, | |
| 83 | + unsigned int order); | |
| 87 | 84 | void force_page_cache_ra(struct readahead_control *, unsigned long nr); |
| 88 | 85 | static inline void force_page_cache_readahead(struct address_space *mapping, |
| 89 | 86 | struct file *file, pgoff_t index, unsigned long nr_to_read) |
| @@ -100,6 +97,9 @@ void filemap_free_folio(struct address_space *mapping, struct folio *folio); · 10 unmodified lines | ||
| 100 | 97 | int truncate_inode_folio(struct address_space *mapping, struct folio *folio); |
| 101 | 98 | bool truncate_inode_partial_folio(struct folio *folio, loff_t start, |
| 102 | 99 | loff_t end); |
| 100 | +long invalidate_inode_page(struct page *page); | |
| 101 | +unsigned long invalidate_mapping_pagevec(struct address_space *mapping, | |
| 102 | + pgoff_t start, pgoff_t end, unsigned long *nr_pagevec); | |
| 103 | 103 | |
| 104 | 104 | /** |
| 105 | 105 | * folio_evictable - Test whether a folio is evictable. |
| @@ -163,8 +163,10 @@ pgprot_t __init early_memremap_pgprot_adjust(resource_size_t phys_addr, · 57 unmodified lines | ||
| 163 | 163 | /* |
| 164 | 164 | * in mm/vmscan.c: |
| 165 | 165 | */ |
| 166 | −extern int isolate_lru_page(struct page *page); | |
| 167 | −extern void putback_lru_page(struct page *page); | |
| 166 | +int isolate_lru_page(struct page *page); | |
| 167 | +int folio_isolate_lru(struct folio *folio); | |
| 168 | +void putback_lru_page(struct page *page); | |
| 169 | +void folio_putback_lru(struct folio *folio); | |
| 168 | 170 | extern void reclaim_throttle(pg_data_t *pgdat, enum vmscan_throttle_state reason); |
| 169 | 171 | |
| 170 | 172 | /* |
| @@ -396,6 +398,7 @@ static inline bool is_data_mapping(vm_flags_t flags) · 225 unmodified lines | ||
| 396 | 398 | void __vma_link_list(struct mm_struct *mm, struct vm_area_struct *vma, |
| 397 | 399 | struct vm_area_struct *prev); |
| 398 | 400 | void __vma_unlink_list(struct mm_struct *mm, struct vm_area_struct *vma); |
| 401 | +struct anon_vma *folio_anon_vma(struct folio *folio); | |
| 399 | 402 | |
| 400 | 403 | #ifdef CONFIG_MMU |
| 401 | 404 | void unmap_mapping_folio(struct folio *folio); |
| @@ -404,32 +407,56 @@ extern long populate_vma_page_range(struct vm_area_struct *vma, · 2 unmodified lines | ||
| 404 | 407 | extern long faultin_vma_page_range(struct vm_area_struct *vma, |
| 405 | 408 | unsigned long start, unsigned long end, |
| 406 | 409 | bool write, int *locked); |
| 407 | −extern void munlock_vma_pages_range(struct vm_area_struct *vma, | |
| 408 | − unsigned long start, unsigned long end); | |
| 409 | −static inline void munlock_vma_pages_all(struct vm_area_struct *vma) | |
| 410 | −{ | |
| 411 | − munlock_vma_pages_range(vma, vma->vm_start, vma->vm_end); | |
| 412 | −} | |
| 413 | − | |
| 414 | −/* | |
| 415 | − * must be called with vma's mmap_lock held for read or write, and page locked. | |
| 416 | − */ | |
| 417 | −extern void mlock_vma_page(struct page *page); | |
| 418 | −extern unsigned int munlock_vma_page(struct page *page); | |
| 419 | − | |
| 420 | 410 | extern int mlock_future_check(struct mm_struct *mm, unsigned long flags, |
| 421 | 411 | unsigned long len); |
| 422 | − | |
| 423 | 412 | /* |
| 424 | − * Clear the page's PageMlocked(). This can be useful in a situation where | |
| 425 | − * we want to unconditionally remove a page from the pagecache -- e.g., | |
| 426 | − * on truncation or freeing. | |
| 413 | + * mlock_vma_page() and munlock_vma_page(): | |
| 414 | + * should be called with vma's mmap_lock held for read or write, | |
| 415 | + * under page table lock for the pte/pmd being added or removed. | |
| 427 | 416 | * |
| 428 | − * It is legal to call this function for any page, mlocked or not. | |
| 429 | − * If called for a page that is still mapped by mlocked vmas, all we do | |
| 430 | − * is revert to lazy LRU behaviour -- semantics are not broken. | |
| 417 | + * mlock is usually called at the end of page_add_*_rmap(), | |
| 418 | + * munlock at the end of page_remove_rmap(); but new anon | |
| 419 | + * pages are managed by lru_cache_add_inactive_or_unevictable() | |
| 420 | + * calling mlock_new_page(). | |
| 421 | + * | |
| 422 | + * @compound is used to include pmd mappings of THPs, but filter out | |
| 423 | + * pte mappings of THPs, which cannot be consistently counted: a pte | |
| 424 | + * mapping of the THP head cannot be distinguished by the page alone. | |
| 431 | 425 | */ |
| 432 | −extern void clear_page_mlock(struct page *page); | |
| 426 | +void mlock_folio(struct folio *folio); | |
| 427 | +static inline void mlock_vma_folio(struct folio *folio, | |
| 428 | + struct vm_area_struct *vma, bool compound) | |
| 429 | +{ | |
| 430 | + /* | |
| 431 | + * The VM_SPECIAL check here serves two purposes. | |
| 432 | + * 1) VM_IO check prevents migration from double-counting during mlock. | |
| 433 | + * 2) Although mmap_region() and mlock_fixup() take care that VM_LOCKED | |
| 434 | + * is never left set on a VM_SPECIAL vma, there is an interval while | |
| 435 | + * file->f_op->mmap() is using vm_insert_page(s), when VM_LOCKED may | |
| 436 | + * still be set while VM_SPECIAL bits are added: so ignore it then. | |
| 437 | + */ | |
| 438 | + if (unlikely((vma->vm_flags & (VM_LOCKED|VM_SPECIAL)) == VM_LOCKED) && | |
| 439 | + (compound || !folio_test_large(folio))) | |
| 440 | + mlock_folio(folio); | |
| 441 | +} | |
| 442 | + | |
| 443 | +static inline void mlock_vma_page(struct page *page, | |
| 444 | + struct vm_area_struct *vma, bool compound) | |
| 445 | +{ | |
| 446 | + mlock_vma_folio(page_folio(page), vma, compound); | |
| 447 | +} | |
| 448 | + | |
| 449 | +void munlock_page(struct page *page); | |
| 450 | +static inline void munlock_vma_page(struct page *page, | |
| 451 | + struct vm_area_struct *vma, bool compound) | |
| 452 | +{ | |
| 453 | + if (unlikely(vma->vm_flags & VM_LOCKED) && | |
| 454 | + (compound || !PageTransCompound(page))) | |
| 455 | + munlock_page(page); | |
| 456 | +} | |
| 457 | +void mlock_new_page(struct page *page); | |
| 458 | +bool need_mlock_page_drain(int cpu); | |
| 459 | +void mlock_page_drain(int cpu); | |
| 433 | 460 | |
| 434 | 461 | extern pmd_t maybe_pmd_mkwrite(pmd_t pmd, struct vm_area_struct *vma); |
| 435 | 462 | |
| @@ -463,18 +490,20 @@ vma_address(struct page *page, struct vm_area_struct *vma) · 27 unmodified lines | ||
| 463 | 490 | } |
| 464 | 491 | |
| 465 | 492 | /* |
| 466 | − * Then at what user virtual address will none of the page be found in vma? | |
| 493 | + * Then at what user virtual address will none of the range be found in vma? | |
| 467 | 494 | * Assumes that vma_address() already returned a good starting address. |
| 468 | − * If page is a compound head, the entire compound page is considered. | |
| 469 | 495 | */ |
| 470 | −static inline unsigned long | |
| 471 | −vma_address_end(struct page *page, struct vm_area_struct *vma) | |
| 496 | +static inline unsigned long vma_address_end(struct page_vma_mapped_walk *pvmw) | |
| 472 | 497 | { |
| 498 | + struct vm_area_struct *vma = pvmw->vma; | |
| 473 | 499 | pgoff_t pgoff; |
| 474 | 500 | unsigned long address; |
| 475 | 501 | |
| 476 | − VM_BUG_ON_PAGE(PageKsm(page), page); /* KSM page->index unusable */ | |
| 477 | − pgoff = page_to_pgoff(page) + compound_nr(page); | |
| 502 | + /* Common case, plus ->pgoff is invalid for KSM */ | |
| 503 | + if (pvmw->nr_pages == 1) | |
| 504 | + return pvmw->address + PAGE_SIZE; | |
| 505 | + | |
| 506 | + pgoff = pvmw->pgoff + pvmw->nr_pages; | |
| 478 | 507 | address = vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT); |
| 479 | 508 | /* Check for address beyond vma (or wrapped through 0?) */ |
| 480 | 509 | if (address < vma->vm_start || address > vma->vm_end) |
| @@ -504,8 +533,13 @@ static inline struct file *maybe_unlock_mmap_for_io(struct vm_fault *vmf, · 23 unmodified lines | ||
| 504 | 533 | } |
| 505 | 534 | #else /* !CONFIG_MMU */ |
| 506 | 535 | static inline void unmap_mapping_folio(struct folio *folio) { } |
| 507 | −static inline void clear_page_mlock(struct page *page) { } | |
| 508 | −static inline void mlock_vma_page(struct page *page) { } | |
| 536 | +static inline void mlock_vma_page(struct page *page, | |
| 537 | + struct vm_area_struct *vma, bool compound) { } | |
| 538 | +static inline void munlock_vma_page(struct page *page, | |
| 539 | + struct vm_area_struct *vma, bool compound) { } | |
| 540 | +static inline void mlock_new_page(struct page *page) { } | |
| 541 | +static inline bool need_mlock_page_drain(int cpu) { return false; } | |
| 542 | +static inline void mlock_page_drain(int cpu) { } | |
| 509 | 543 | static inline void vunmap_range_noflush(unsigned long start, unsigned long end) |
| 510 | 544 | { |
| 511 | 545 | } |
| @@ -713,6 +747,13 @@ void vunmap_range_noflush(unsigned long start, unsigned long end); · 201 unmodified lines | ||
| 713 | 747 | int numa_migrate_prep(struct page *page, struct vm_area_struct *vma, |
| 714 | 748 | unsigned long addr, int page_nid, int *flags); |
| 715 | 749 | |
| 750 | +void free_zone_device_page(struct page *page); | |
| 751 | + | |
| 752 | +/* | |
| 753 | + * mm/gup.c | |
| 754 | + */ | |
| 755 | +struct folio *try_grab_folio(struct page *page, int refs, unsigned int flags); | |
| 756 | + | |
| 716 | 757 | DECLARE_PER_CPU(struct per_cpu_nodestat, boot_nodestats); |
| 717 | 758 | |
| 718 | 759 | #endif /* __MM_INTERNAL_H */ |
| @@ -774,7 +774,7 @@ static void __collapse_huge_page_copy(pte_t *pte, struct page *page, · 773 unmodified lines | ||
| 774 | 774 | */ |
| 775 | 775 | spin_lock(ptl); |
| 776 | 776 | ptep_clear(vma->vm_mm, address, _pte); |
| 777 | − page_remove_rmap(src_page, false); | |
| 777 | + page_remove_rmap(src_page, vma, false); | |
| 778 | 778 | spin_unlock(ptl); |
| 779 | 779 | free_page_and_swap_cache(src_page); |
| 780 | 780 | } |
| @@ -1513,7 +1513,7 @@ void collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr) · 732 unmodified lines | ||
| 1513 | 1513 | if (pte_none(*pte)) |
| 1514 | 1514 | continue; |
| 1515 | 1515 | page = vm_normal_page(vma, addr, *pte); |
| 1516 | − page_remove_rmap(page, false); | |
| 1516 | + page_remove_rmap(page, vma, false); | |
| 1517 | 1517 | } |
| 1518 | 1518 | |
| 1519 | 1519 | pte_unmap_unlock(start_pte, ptl); |
| @@ -1834,13 +1834,13 @@ static void collapse_file(struct mm_struct *mm, · 314 unmodified lines | ||
| 1834 | 1834 | } |
| 1835 | 1835 | |
| 1836 | 1836 | if (page_mapped(page)) |
| 1837 | − unmap_mapping_pages(mapping, index, 1, false); | |
| 1837 | + try_to_unmap(page_folio(page), | |
| 1838 | + TTU_IGNORE_MLOCK | TTU_BATCH_FLUSH); | |
| 1838 | 1839 | |
| 1839 | 1840 | xas_lock_irq(&xas); |
| 1840 | 1841 | xas_set(&xas, index); |
| 1841 | 1842 | |
| 1842 | 1843 | VM_BUG_ON_PAGE(page != xas_load(&xas), page); |
| 1843 | − VM_BUG_ON_PAGE(page_mapped(page), page); | |
| 1844 | 1844 | |
| 1845 | 1845 | /* |
| 1846 | 1846 | * The page is expected to have page_count() == 3: |
| @@ -1904,6 +1904,13 @@ xa_locked: · 57 unmodified lines | ||
| 1904 | 1904 | xas_unlock_irq(&xas); |
| 1905 | 1905 | xa_unlocked: |
| 1906 | 1906 | |
| 1907 | + /* | |
| 1908 | + * If collapse is successful, flush must be done now before copying. | |
| 1909 | + * If collapse is unsuccessful, does flush actually need to be done? | |
| 1910 | + * Do it anyway, to clear the state. | |
| 1911 | + */ | |
| 1912 | + try_to_unmap_flush(); | |
| 1913 | + | |
| 1907 | 1914 | if (result == SCAN_SUCCEED) { |
| 1908 | 1915 | struct page *page, *tmp; |
| 1909 | 1916 | |
| @@ -1034,10 +1034,7 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page, · 1033 unmodified lines | ||
| 1034 | 1034 | pte_t *orig_pte) |
| 1035 | 1035 | { |
| 1036 | 1036 | struct mm_struct *mm = vma->vm_mm; |
| 1037 | − struct page_vma_mapped_walk pvmw = { | |
| 1038 | − .page = page, | |
| 1039 | − .vma = vma, | |
| 1040 | − }; | |
| 1037 | + DEFINE_PAGE_VMA_WALK(pvmw, page, vma, 0, 0); | |
| 1041 | 1038 | int swapped; |
| 1042 | 1039 | int err = -EFAULT; |
| 1043 | 1040 | struct mmu_notifier_range range; |
| @@ -1177,7 +1174,7 @@ static int replace_page(struct vm_area_struct *vma, struct page *page, · 133 unmodified lines | ||
| 1177 | 1174 | ptep_clear_flush(vma, addr, ptep); |
| 1178 | 1175 | set_pte_at_notify(mm, addr, ptep, newpte); |
| 1179 | 1176 | |
| 1180 | − page_remove_rmap(page, false); | |
| 1177 | + page_remove_rmap(page, vma, false); | |
| 1181 | 1178 | if (!page_mapped(page)) |
| 1182 | 1179 | try_to_free_swap(page); |
| 1183 | 1180 | put_page(page); |
| @@ -1252,16 +1249,6 @@ static int try_to_merge_one_page(struct vm_area_struct *vma, · 68 unmodified lines | ||
| 1252 | 1249 | err = replace_page(vma, page, kpage, orig_pte); |
| 1253 | 1250 | } |
| 1254 | 1251 | |
| 1255 | − if ((vma->vm_flags & VM_LOCKED) && kpage && !err) { | |
| 1256 | − munlock_vma_page(page); | |
| 1257 | − if (!PageMlocked(kpage)) { | |
| 1258 | − unlock_page(page); | |
| 1259 | − lock_page(kpage); | |
| 1260 | − mlock_vma_page(kpage); | |
| 1261 | − page = kpage; /* for final unlock */ | |
| 1262 | − } | |
| 1263 | − } | |
| 1264 | − | |
| 1265 | 1252 | out_unlock: |
| 1266 | 1253 | unlock_page(page); |
| 1267 | 1254 | out: |
| @@ -2567,7 +2554,8 @@ void __ksm_exit(struct mm_struct *mm) · 1299 unmodified lines | ||
| 2567 | 2554 | struct page *ksm_might_need_to_copy(struct page *page, |
| 2568 | 2555 | struct vm_area_struct *vma, unsigned long address) |
| 2569 | 2556 | { |
| 2570 | − struct anon_vma *anon_vma = page_anon_vma(page); | |
| 2557 | + struct folio *folio = page_folio(page); | |
| 2558 | + struct anon_vma *anon_vma = folio_anon_vma(folio); | |
| 2571 | 2559 | struct page *new_page; |
| 2572 | 2560 | |
| 2573 | 2561 | if (PageKsm(page)) { |
| @@ -2603,21 +2591,21 @@ struct page *ksm_might_need_to_copy(struct page *page, · 29 unmodified lines | ||
| 2603 | 2591 | return new_page; |
| 2604 | 2592 | } |
| 2605 | 2593 | |
| 2606 | −void rmap_walk_ksm(struct page *page, struct rmap_walk_control *rwc) | |
| 2594 | +void rmap_walk_ksm(struct folio *folio, const struct rmap_walk_control *rwc) | |
| 2607 | 2595 | { |
| 2608 | 2596 | struct stable_node *stable_node; |
| 2609 | 2597 | struct rmap_item *rmap_item; |
| 2610 | 2598 | int search_new_forks = 0; |
| 2611 | 2599 | |
| 2612 | − VM_BUG_ON_PAGE(!PageKsm(page), page); | |
| 2600 | + VM_BUG_ON_FOLIO(!folio_test_ksm(folio), folio); | |
| 2613 | 2601 | |
| 2614 | 2602 | /* |
| 2615 | 2603 | * Rely on the page lock to protect against concurrent modifications |
| 2616 | 2604 | * to that page's node of the stable tree. |
| 2617 | 2605 | */ |
| 2618 | − VM_BUG_ON_PAGE(!PageLocked(page), page); | |
| 2606 | + VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio); | |
| 2619 | 2607 | |
| 2620 | − stable_node = page_stable_node(page); | |
| 2608 | + stable_node = folio_stable_node(folio); | |
| 2621 | 2609 | if (!stable_node) |
| 2622 | 2610 | return; |
| 2623 | 2611 | again: |
| @@ -2652,11 +2640,11 @@ again: · 28 unmodified lines | ||
| 2652 | 2640 | if (rwc->invalid_vma && rwc->invalid_vma(vma, rwc->arg)) |
| 2653 | 2641 | continue; |
| 2654 | 2642 | |
| 2655 | − if (!rwc->rmap_one(page, vma, addr, rwc->arg)) { | |
| 2643 | + if (!rwc->rmap_one(folio, vma, addr, rwc->arg)) { | |
| 2656 | 2644 | anon_vma_unlock_read(anon_vma); |
| 2657 | 2645 | return; |
| 2658 | 2646 | } |
| 2659 | − if (rwc->done && rwc->done(page)) { | |
| 2647 | + if (rwc->done && rwc->done(folio)) { | |
| 2660 | 2648 | anon_vma_unlock_read(anon_vma); |
| 2661 | 2649 | return; |
| 2662 | 2650 | } |
| @@ -502,6 +502,11 @@ static void madvise_cold_page_range(struct mmu_gather *tlb, · 501 unmodified lines | ||
| 502 | 502 | tlb_end_vma(tlb, vma); |
| 503 | 503 | } |
| 504 | 504 | |
| 505 | +static inline bool can_madv_lru_vma(struct vm_area_struct *vma) | |
| 506 | +{ | |
| 507 | + return !(vma->vm_flags & (VM_LOCKED|VM_HUGETLB|VM_PFNMAP)); | |
| 508 | +} | |
| 509 | + | |
| 505 | 510 | static long madvise_cold(struct vm_area_struct *vma, |
| 506 | 511 | struct vm_area_struct **prev, |
| 507 | 512 | unsigned long start_addr, unsigned long end_addr) |
| @@ -53,6 +53,7 @@ · 52 unmodified lines | ||
| 53 | 53 | #include <linux/fs.h> |
| 54 | 54 | #include <linux/seq_file.h> |
| 55 | 55 | #include <linux/vmpressure.h> |
| 56 | +#include <linux/memremap.h> | |
| 56 | 57 | #include <linux/mm_inline.h> |
| 57 | 58 | #include <linux/swap_cgroup.h> |
| 58 | 59 | #include <linux/cpu.h> |
| @@ -1271,8 +1272,7 @@ struct lruvec *folio_lruvec_lock_irqsave(struct folio *folio, · 1212 unmodified lines | ||
| 1271 | 1272 | * @nr_pages: positive when adding or negative when removing |
| 1272 | 1273 | * |
| 1273 | 1274 | * This function must be called under lru_lock, just before a page is added |
| 1274 | − * to or just after a page is removed from an lru list (that ordering being | |
| 1275 | − * so as to allow it to check that lru_size 0 is consistent with list_empty). | |
| 1275 | + * to or just after a page is removed from an lru list. | |
| 1276 | 1276 | */ |
| 1277 | 1277 | void mem_cgroup_update_lru_size(struct lruvec *lruvec, enum lru_list lru, |
| 1278 | 1278 | int zid, int nr_pages) |
| @@ -5436,17 +5436,12 @@ static struct page *mc_handle_swap_pte(struct vm_area_struct *vma, · 4157 unmodified lines | ||
| 5436 | 5436 | return NULL; |
| 5437 | 5437 | |
| 5438 | 5438 | /* |
| 5439 | − * Handle MEMORY_DEVICE_PRIVATE which are ZONE_DEVICE page belonging to | |
| 5440 | − * a device and because they are not accessible by CPU they are store | |
| 5441 | − * as special swap entry in the CPU page table. | |
| 5439 | + * Handle device private pages that are not accessible by the CPU, but | |
| 5440 | + * stored as special swap entries in the page table. | |
| 5442 | 5441 | */ |
| 5443 | 5442 | if (is_device_private_entry(ent)) { |
| 5444 | 5443 | page = pfn_swap_entry_to_page(ent); |
| 5445 | − /* | |
| 5446 | − * MEMORY_DEVICE_PRIVATE means ZONE_DEVICE page and which have | |
| 5447 | − * a refcount of 1 when free (unlike normal page) | |
| 5448 | − */ | |
| 5449 | − if (!page_ref_add_unless(page, 1, 1)) | |
| 5444 | + if (!get_page_unless_zero(page)) | |
| 5450 | 5445 | return NULL; |
| 5451 | 5446 | return page; |
| 5452 | 5447 | } |
| @@ -7053,19 +7048,19 @@ static struct mem_cgroup *mem_cgroup_id_get_online(struct mem_cgroup *memcg) · 1600 unmodified lines | ||
| 7053 | 7048 | |
| 7054 | 7049 | /** |
| 7055 | 7050 | * mem_cgroup_swapout - transfer a memsw charge to swap |
| 7056 | − * @page: page whose memsw charge to transfer | |
| 7051 | + * @folio: folio whose memsw charge to transfer | |
| 7057 | 7052 | * @entry: swap entry to move the charge to |
| 7058 | 7053 | * |
| 7059 | − * Transfer the memsw charge of @page to @entry. | |
| 7054 | + * Transfer the memsw charge of @folio to @entry. | |
| 7060 | 7055 | */ |
| 7061 | −void mem_cgroup_swapout(struct page *page, swp_entry_t entry) | |
| 7056 | +void mem_cgroup_swapout(struct folio *folio, swp_entry_t entry) | |
| 7062 | 7057 | { |
| 7063 | 7058 | struct mem_cgroup *memcg, *swap_memcg; |
| 7064 | 7059 | unsigned int nr_entries; |
| 7065 | 7060 | unsigned short oldid; |
| 7066 | 7061 | |
| 7067 | − VM_BUG_ON_PAGE(PageLRU(page), page); | |
| 7068 | − VM_BUG_ON_PAGE(page_count(page), page); | |
| 7062 | + VM_BUG_ON_FOLIO(folio_test_lru(folio), folio); | |
| 7063 | + VM_BUG_ON_FOLIO(folio_ref_count(folio), folio); | |
| 7069 | 7064 | |
| 7070 | 7065 | if (mem_cgroup_disabled()) |
| 7071 | 7066 | return; |
| @@ -7073,9 +7068,9 @@ void mem_cgroup_swapout(struct page *page, swp_entry_t entry) · 1 unmodified line | ||
| 7073 | 7068 | if (cgroup_subsys_on_dfl(memory_cgrp_subsys)) |
| 7074 | 7069 | return; |
| 7075 | 7070 | |
| 7076 | − memcg = page_memcg(page); | |
| 7071 | + memcg = folio_memcg(folio); | |
| 7077 | 7072 | |
| 7078 | − VM_WARN_ON_ONCE_PAGE(!memcg, page); | |
| 7073 | + VM_WARN_ON_ONCE_FOLIO(!memcg, folio); | |
| 7079 | 7074 | if (!memcg) |
| 7080 | 7075 | return; |
| 7081 | 7076 | |
| @@ -7085,16 +7080,16 @@ void mem_cgroup_swapout(struct page *page, swp_entry_t entry) · 3 unmodified lines | ||
| 7085 | 7080 | * ancestor for the swap instead and transfer the memory+swap charge. |
| 7086 | 7081 | */ |
| 7087 | 7082 | swap_memcg = mem_cgroup_id_get_online(memcg); |
| 7088 | − nr_entries = thp_nr_pages(page); | |
| 7083 | + nr_entries = folio_nr_pages(folio); | |
| 7089 | 7084 | /* Get references for the tail pages, too */ |
| 7090 | 7085 | if (nr_entries > 1) |
| 7091 | 7086 | mem_cgroup_id_get_many(swap_memcg, nr_entries - 1); |
| 7092 | 7087 | oldid = swap_cgroup_record(entry, mem_cgroup_id(swap_memcg), |
| 7093 | 7088 | nr_entries); |
| 7094 | − VM_BUG_ON_PAGE(oldid, page); | |
| 7089 | + VM_BUG_ON_FOLIO(oldid, folio); | |
| 7095 | 7090 | mod_memcg_state(swap_memcg, MEMCG_SWAP, nr_entries); |
| 7096 | 7091 | |
| 7097 | − page->memcg_data = 0; | |
| 7092 | + folio->memcg_data = 0; | |
| 7098 | 7093 | |
| 7099 | 7094 | if (!mem_cgroup_is_root(memcg)) |
| 7100 | 7095 | page_counter_uncharge(&memcg->memory, nr_entries); |
| @@ -7114,7 +7109,7 @@ void mem_cgroup_swapout(struct page *page, swp_entry_t entry) · 13 unmodified lines | ||
| 7114 | 7109 | memcg_stats_lock(); |
| 7115 | 7110 | mem_cgroup_charge_statistics(memcg, -nr_entries); |
| 7116 | 7111 | memcg_stats_unlock(); |
| 7117 | − memcg_check_events(memcg, page_to_nid(page)); | |
| 7112 | + memcg_check_events(memcg, folio_nid(folio)); | |
| 7118 | 7113 | |
| 7119 | 7114 | css_put(&memcg->css); |
| 7120 | 7115 | } |
| @@ -478,12 +478,13 @@ static struct task_struct *task_early_kill(struct task_struct *tsk, · 477 unmodified lines | ||
| 478 | 478 | static void collect_procs_anon(struct page *page, struct list_head *to_kill, |
| 479 | 479 | int force_early) |
| 480 | 480 | { |
| 481 | + struct folio *folio = page_folio(page); | |
| 481 | 482 | struct vm_area_struct *vma; |
| 482 | 483 | struct task_struct *tsk; |
| 483 | 484 | struct anon_vma *av; |
| 484 | 485 | pgoff_t pgoff; |
| 485 | 486 | |
| 486 | − av = page_lock_anon_vma_read(page); | |
| 487 | + av = folio_lock_anon_vma_read(folio); | |
| 487 | 488 | if (av == NULL) /* Not actually mapped anymore */ |
| 488 | 489 | return; |
| 489 | 490 | |
| @@ -1347,6 +1348,7 @@ static int get_hwpoison_page(struct page *p, unsigned long flags) · 857 unmodified lines | ||
| 1347 | 1348 | static bool hwpoison_user_mappings(struct page *p, unsigned long pfn, |
| 1348 | 1349 | int flags, struct page *hpage) |
| 1349 | 1350 | { |
| 1351 | + struct folio *folio = page_folio(hpage); | |
| 1350 | 1352 | enum ttu_flags ttu = TTU_IGNORE_MLOCK | TTU_SYNC; |
| 1351 | 1353 | struct address_space *mapping; |
| 1352 | 1354 | LIST_HEAD(tokill); |
| @@ -1421,12 +1423,12 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn, · 68 unmodified lines | ||
| 1421 | 1423 | */ |
| 1422 | 1424 | mapping = hugetlb_page_mapping_lock_write(hpage); |
| 1423 | 1425 | if (mapping) { |
| 1424 | − try_to_unmap(hpage, ttu|TTU_RMAP_LOCKED); | |
| 1426 | + try_to_unmap(folio, ttu|TTU_RMAP_LOCKED); | |
| 1425 | 1427 | i_mmap_unlock_write(mapping); |
| 1426 | 1428 | } else |
| 1427 | 1429 | pr_info("Memory failure: %#lx: could not lock mapping for mapped huge page\n", pfn); |
| 1428 | 1430 | } else { |
| 1429 | − try_to_unmap(hpage, ttu); | |
| 1431 | + try_to_unmap(folio, ttu); | |
| 1430 | 1432 | } |
| 1431 | 1433 | |
| 1432 | 1434 | unmap_success = !page_mapped(hpage); |
| @@ -2169,7 +2171,7 @@ static bool isolate_page(struct page *page, struct list_head *pagelist) · 736 unmodified lines | ||
| 2169 | 2171 | */ |
| 2170 | 2172 | static int __soft_offline_page(struct page *page) |
| 2171 | 2173 | { |
| 2172 | − int ret = 0; | |
| 2174 | + long ret = 0; | |
| 2173 | 2175 | unsigned long pfn = page_to_pfn(page); |
| 2174 | 2176 | struct page *hpage = compound_head(page); |
| 2175 | 2177 | char const *msg_page[] = {"page", "hugepage"}; |
| @@ -2216,7 +2218,7 @@ static int __soft_offline_page(struct page *page) · 40 unmodified lines | ||
| 2216 | 2218 | if (!list_empty(&pagelist)) |
| 2217 | 2219 | putback_movable_pages(&pagelist); |
| 2218 | 2220 | |
| 2219 | − pr_info("soft offline: %#lx: %s migration failed %d, type %pGp\n", | |
| 2221 | + pr_info("soft offline: %#lx: %s migration failed %ld, type %pGp\n", | |
| 2220 | 2222 | pfn, msg_page[huge], ret, &page->flags); |
| 2221 | 2223 | if (ret > 0) |
| 2222 | 2224 | ret = -EBUSY; |
| @@ -735,9 +735,6 @@ static void restore_exclusive_pte(struct vm_area_struct *vma, · 734 unmodified lines | ||
| 735 | 735 | |
| 736 | 736 | set_pte_at(vma->vm_mm, address, ptep, pte); |
| 737 | 737 | |
| 738 | − if (vma->vm_flags & VM_LOCKED) | |
| 739 | − mlock_vma_page(page); | |
| 740 | − | |
| 741 | 738 | /* |
| 742 | 739 | * No need to invalidate - it was non-present before. However |
| 743 | 740 | * secondary CPUs may have mappings that need invalidating. |
| @@ -1389,7 +1386,7 @@ again: · 645 unmodified lines | ||
| 1389 | 1386 | mark_page_accessed(page); |
| 1390 | 1387 | } |
| 1391 | 1388 | rss[mm_counter(page)]--; |
| 1392 | − page_remove_rmap(page, false); | |
| 1389 | + page_remove_rmap(page, vma, false); | |
| 1393 | 1390 | if (unlikely(page_mapcount(page) < 0)) |
| 1394 | 1391 | print_bad_pte(vma, addr, ptent, page); |
| 1395 | 1392 | if (unlikely(__tlb_remove_page(tlb, page))) { |
| @@ -1408,7 +1405,7 @@ again: · 12 unmodified lines | ||
| 1408 | 1405 | continue; |
| 1409 | 1406 | rss[mm_counter(page)]--; |
| 1410 | 1407 | if (is_device_private_entry(entry)) |
| 1411 | − page_remove_rmap(page, false); | |
| 1408 | + page_remove_rmap(page, vma, false); | |
| 1412 | 1409 | put_page(page); |
| 1413 | 1410 | } else if (!non_swap_entry(entry)) { |
| 1414 | 1411 | /* Genuine swap entry, hence a private anon page */ |
| @@ -1763,16 +1760,16 @@ static int validate_page_before_insert(struct page *page) · 348 unmodified lines | ||
| 1763 | 1760 | return 0; |
| 1764 | 1761 | } |
| 1765 | 1762 | |
| 1766 | −static int insert_page_into_pte_locked(struct mm_struct *mm, pte_t *pte, | |
| 1763 | +static int insert_page_into_pte_locked(struct vm_area_struct *vma, pte_t *pte, | |
| 1767 | 1764 | unsigned long addr, struct page *page, pgprot_t prot) |
| 1768 | 1765 | { |
| 1769 | 1766 | if (!pte_none(*pte)) |
| 1770 | 1767 | return -EBUSY; |
| 1771 | 1768 | /* Ok, finally just insert the thing.. */ |
| 1772 | 1769 | get_page(page); |
| 1773 | − inc_mm_counter_fast(mm, mm_counter_file(page)); | |
| 1774 | − page_add_file_rmap(page, false); | |
| 1775 | − set_pte_at(mm, addr, pte, mk_pte(page, prot)); | |
| 1770 | + inc_mm_counter_fast(vma->vm_mm, mm_counter_file(page)); | |
| 1771 | + page_add_file_rmap(page, vma, false); | |
| 1772 | + set_pte_at(vma->vm_mm, addr, pte, mk_pte(page, prot)); | |
| 1776 | 1773 | return 0; |
| 1777 | 1774 | } |
| 1778 | 1775 | |
| @@ -1786,7 +1783,6 @@ static int insert_page_into_pte_locked(struct mm_struct *mm, pte_t *pte, · 7 unmodified lines | ||
| 1786 | 1783 | static int insert_page(struct vm_area_struct *vma, unsigned long addr, |
| 1787 | 1784 | struct page *page, pgprot_t prot) |
| 1788 | 1785 | { |
| 1789 | − struct mm_struct *mm = vma->vm_mm; | |
| 1790 | 1786 | int retval; |
| 1791 | 1787 | pte_t *pte; |
| 1792 | 1788 | spinlock_t *ptl; |
| @@ -1795,17 +1791,17 @@ static int insert_page(struct vm_area_struct *vma, unsigned long addr, · 2 unmodified lines | ||
| 1795 | 1791 | if (retval) |
| 1796 | 1792 | goto out; |
| 1797 | 1793 | retval = -ENOMEM; |
| 1798 | − pte = get_locked_pte(mm, addr, &ptl); | |
| 1794 | + pte = get_locked_pte(vma->vm_mm, addr, &ptl); | |
| 1799 | 1795 | if (!pte) |
| 1800 | 1796 | goto out; |
| 1801 | − retval = insert_page_into_pte_locked(mm, pte, addr, page, prot); | |
| 1797 | + retval = insert_page_into_pte_locked(vma, pte, addr, page, prot); | |
| 1802 | 1798 | pte_unmap_unlock(pte, ptl); |
| 1803 | 1799 | out: |
| 1804 | 1800 | return retval; |
| 1805 | 1801 | } |
| 1806 | 1802 | |
| 1807 | 1803 | #ifdef pte_index |
| 1808 | −static int insert_page_in_batch_locked(struct mm_struct *mm, pte_t *pte, | |
| 1804 | +static int insert_page_in_batch_locked(struct vm_area_struct *vma, pte_t *pte, | |
| 1809 | 1805 | unsigned long addr, struct page *page, pgprot_t prot) |
| 1810 | 1806 | { |
| 1811 | 1807 | int err; |
| @@ -1815,7 +1811,7 @@ static int insert_page_in_batch_locked(struct mm_struct *mm, pte_t *pte, · 3 unmodified lines | ||
| 1815 | 1811 | err = validate_page_before_insert(page); |
| 1816 | 1812 | if (err) |
| 1817 | 1813 | return err; |
| 1818 | − return insert_page_into_pte_locked(mm, pte, addr, page, prot); | |
| 1814 | + return insert_page_into_pte_locked(vma, pte, addr, page, prot); | |
| 1819 | 1815 | } |
| 1820 | 1816 | |
| 1821 | 1817 | /* insert_pages() amortizes the cost of spinlock operations |
| @@ -1852,7 +1848,7 @@ more: · 30 unmodified lines | ||
| 1852 | 1848 | |
| 1853 | 1849 | start_pte = pte_offset_map_lock(mm, pmd, addr, &pte_lock); |
| 1854 | 1850 | for (pte = start_pte; pte_idx < batch_size; ++pte, ++pte_idx) { |
| 1855 | − int err = insert_page_in_batch_locked(mm, pte, | |
| 1851 | + int err = insert_page_in_batch_locked(vma, pte, | |
| 1856 | 1852 | addr, pages[curr_page_idx], prot); |
| 1857 | 1853 | if (unlikely(err)) { |
| 1858 | 1854 | pte_unmap_unlock(start_pte, pte_lock); |
| @@ -3108,7 +3104,7 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf) · 1249 unmodified lines | ||
| 3108 | 3104 | * mapcount is visible. So transitively, TLBs to |
| 3109 | 3105 | * old page will be flushed before it can be reused. |
| 3110 | 3106 | */ |
| 3111 | − page_remove_rmap(old_page, false); | |
| 3107 | + page_remove_rmap(old_page, vma, false); | |
| 3112 | 3108 | } |
| 3113 | 3109 | |
| 3114 | 3110 | /* Free the old page.. */ |
| @@ -3128,16 +3124,6 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf) · 13 unmodified lines | ||
| 3128 | 3124 | */ |
| 3129 | 3125 | mmu_notifier_invalidate_range_only_end(&range); |
| 3130 | 3126 | if (old_page) { |
| 3131 | − /* | |
| 3132 | − * Don't let another task, with possibly unlocked vma, | |
| 3133 | − * keep the mlocked page. | |
| 3134 | − */ | |
| 3135 | − if (page_copied && (vma->vm_flags & VM_LOCKED)) { | |
| 3136 | − lock_page(old_page); /* LRU manipulation */ | |
| 3137 | − if (PageMlocked(old_page)) | |
| 3138 | − munlock_vma_page(old_page); | |
| 3139 | − unlock_page(old_page); | |
| 3140 | − } | |
| 3141 | 3127 | if (page_copied) |
| 3142 | 3128 | free_swap_cache(old_page); |
| 3143 | 3129 | put_page(old_page); |
| @@ -3958,7 +3944,8 @@ vm_fault_t do_set_pmd(struct vm_fault *vmf, struct page *page) · 814 unmodified lines | ||
| 3958 | 3944 | entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma); |
| 3959 | 3945 | |
| 3960 | 3946 | add_mm_counter(vma->vm_mm, mm_counter_file(page), HPAGE_PMD_NR); |
| 3961 | − page_add_file_rmap(page, true); | |
| 3947 | + page_add_file_rmap(page, vma, true); | |
| 3948 | + | |
| 3962 | 3949 | /* |
| 3963 | 3950 | * deposit and withdraw with pmd lock held |
| 3964 | 3951 | */ |
| @@ -4007,7 +3994,7 @@ void do_set_pte(struct vm_fault *vmf, struct page *page, unsigned long addr) · 42 unmodified lines | ||
| 4007 | 3994 | lru_cache_add_inactive_or_unevictable(page, vma); |
| 4008 | 3995 | } else { |
| 4009 | 3996 | inc_mm_counter_fast(vma->vm_mm, mm_counter_file(page)); |
| 4010 | − page_add_file_rmap(page, false); | |
| 3997 | + page_add_file_rmap(page, vma, false); | |
| 4011 | 3998 | } |
| 4012 | 3999 | set_pte_at(vma->vm_mm, addr, vmf->pte, entry); |
| 4013 | 4000 | } |
| @@ -1617,10 +1617,13 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn) · 1616 unmodified lines | ||
| 1617 | 1617 | DEFAULT_RATELIMIT_BURST); |
| 1618 | 1618 | |
| 1619 | 1619 | for (pfn = start_pfn; pfn < end_pfn; pfn++) { |
| 1620 | + struct folio *folio; | |
| 1621 | + | |
| 1620 | 1622 | if (!pfn_valid(pfn)) |
| 1621 | 1623 | continue; |
| 1622 | 1624 | page = pfn_to_page(pfn); |
| 1623 | − head = compound_head(page); | |
| 1625 | + folio = page_folio(page); | |
| 1626 | + head = &folio->page; | |
| 1624 | 1627 | |
| 1625 | 1628 | if (PageHuge(page)) { |
| 1626 | 1629 | pfn = page_to_pfn(head) + compound_nr(head) - 1; |
| @@ -1637,10 +1640,10 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn) · 10 unmodified lines | ||
| 1637 | 1640 | * the unmap as the catch all safety net). |
| 1638 | 1641 | */ |
| 1639 | 1642 | if (PageHWPoison(page)) { |
| 1640 | − if (WARN_ON(PageLRU(page))) | |
| 1641 | − isolate_lru_page(page); | |
| 1642 | − if (page_mapped(page)) | |
| 1643 | − try_to_unmap(page, TTU_IGNORE_MLOCK); | |
| 1643 | + if (WARN_ON(folio_test_lru(folio))) | |
| 1644 | + folio_isolate_lru(folio); | |
| 1645 | + if (folio_mapped(folio)) | |
| 1646 | + try_to_unmap(folio, TTU_IGNORE_MLOCK); | |
| 1644 | 1647 | continue; |
| 1645 | 1648 | } |
| 1646 | 1649 | |
| @@ -4,7 +4,7 @@ · 3 unmodified lines | ||
| 4 | 4 | #include <linux/io.h> |
| 5 | 5 | #include <linux/kasan.h> |
| 6 | 6 | #include <linux/memory_hotplug.h> |
| 7 | −#include <linux/mm.h> | |
| 7 | +#include <linux/memremap.h> | |
| 8 | 8 | #include <linux/pfn_t.h> |
| 9 | 9 | #include <linux/swap.h> |
| 10 | 10 | #include <linux/mmzone.h> |
| @@ -12,6 +12,7 @@ · 1 unmodified line | ||
| 12 | 12 | #include <linux/types.h> |
| 13 | 13 | #include <linux/wait_bit.h> |
| 14 | 14 | #include <linux/xarray.h> |
| 15 | +#include "internal.h" | |
| 15 | 16 | |
| 16 | 17 | static DEFINE_XARRAY(pgmap_array); |
| 17 | 18 | |
| @@ -37,21 +38,19 @@ unsigned long memremap_compat_align(void) · 19 unmodified lines | ||
| 37 | 38 | EXPORT_SYMBOL_GPL(memremap_compat_align); |
| 38 | 39 | #endif |
| 39 | 40 | |
| 40 | −#ifdef CONFIG_DEV_PAGEMAP_OPS | |
| 41 | +#ifdef CONFIG_FS_DAX | |
| 41 | 42 | DEFINE_STATIC_KEY_FALSE(devmap_managed_key); |
| 42 | 43 | EXPORT_SYMBOL(devmap_managed_key); |
| 43 | 44 | |
| 44 | 45 | static void devmap_managed_enable_put(struct dev_pagemap *pgmap) |
| 45 | 46 | { |
| 46 | − if (pgmap->type == MEMORY_DEVICE_PRIVATE || | |
| 47 | − pgmap->type == MEMORY_DEVICE_FS_DAX) | |
| 47 | + if (pgmap->type == MEMORY_DEVICE_FS_DAX) | |
| 48 | 48 | static_branch_dec(&devmap_managed_key); |
| 49 | 49 | } |
| 50 | 50 | |
| 51 | 51 | static void devmap_managed_enable_get(struct dev_pagemap *pgmap) |
| 52 | 52 | { |
| 53 | − if (pgmap->type == MEMORY_DEVICE_PRIVATE || | |
| 54 | − pgmap->type == MEMORY_DEVICE_FS_DAX) | |
| 53 | + if (pgmap->type == MEMORY_DEVICE_FS_DAX) | |
| 55 | 54 | static_branch_inc(&devmap_managed_key); |
| 56 | 55 | } |
| 57 | 56 | #else |
| @@ -61,7 +60,7 @@ static void devmap_managed_enable_get(struct dev_pagemap *pgmap) · 3 unmodified lines | ||
| 61 | 60 | static void devmap_managed_enable_put(struct dev_pagemap *pgmap) |
| 62 | 61 | { |
| 63 | 62 | } |
| 64 | −#endif /* CONFIG_DEV_PAGEMAP_OPS */ | |
| 63 | +#endif /* CONFIG_FS_DAX */ | |
| 65 | 64 | |
| 66 | 65 | static void pgmap_array_delete(struct range *range) |
| 67 | 66 | { |
| @@ -102,23 +101,12 @@ static unsigned long pfn_end(struct dev_pagemap *pgmap, int range_id) · 34 unmodified lines | ||
| 102 | 101 | return (range->start + range_len(range)) >> PAGE_SHIFT; |
| 103 | 102 | } |
| 104 | 103 | |
| 105 | −static unsigned long pfn_next(struct dev_pagemap *pgmap, unsigned long pfn) | |
| 106 | −{ | |
| 107 | − if (pfn % (1024 << pgmap->vmemmap_shift)) | |
| 108 | − cond_resched(); | |
| 109 | − return pfn + pgmap_vmemmap_nr(pgmap); | |
| 110 | −} | |
| 111 | − | |
| 112 | 104 | static unsigned long pfn_len(struct dev_pagemap *pgmap, unsigned long range_id) |
| 113 | 105 | { |
| 114 | 106 | return (pfn_end(pgmap, range_id) - |
| 115 | 107 | pfn_first(pgmap, range_id)) >> pgmap->vmemmap_shift; |
| 116 | 108 | } |
| 117 | 109 | |
| 118 | −#define for_each_device_pfn(pfn, map, i) \ | |
| 119 | − for (pfn = pfn_first(map, i); pfn < pfn_end(map, i); \ | |
| 120 | − pfn = pfn_next(map, pfn)) | |
| 121 | − | |
| 122 | 110 | static void pageunmap_range(struct dev_pagemap *pgmap, int range_id) |
| 123 | 111 | { |
| 124 | 112 | struct range *range = &pgmap->ranges[range_id]; |
| @@ -147,13 +135,11 @@ static void pageunmap_range(struct dev_pagemap *pgmap, int range_id) · 22 unmodified lines | ||
| 147 | 135 | |
| 148 | 136 | void memunmap_pages(struct dev_pagemap *pgmap) |
| 149 | 137 | { |
| 150 | − unsigned long pfn; | |
| 151 | 138 | int i; |
| 152 | 139 | |
| 153 | 140 | percpu_ref_kill(&pgmap->ref); |
| 154 | 141 | for (i = 0; i < pgmap->nr_range; i++) |
| 155 | − for_each_device_pfn(pfn, pgmap, i) | |
| 156 | − put_page(pfn_to_page(pfn)); | |
| 142 | + percpu_ref_put_many(&pgmap->ref, pfn_len(pgmap, i)); | |
| 157 | 143 | wait_for_completion(&pgmap->done); |
| 158 | 144 | percpu_ref_exit(&pgmap->ref); |
| 159 | 145 | |
| @@ -329,8 +315,7 @@ void *memremap_pages(struct dev_pagemap *pgmap, int nid) · 169 unmodified lines | ||
| 329 | 315 | } |
| 330 | 316 | break; |
| 331 | 317 | case MEMORY_DEVICE_FS_DAX: |
| 332 | − if (!IS_ENABLED(CONFIG_ZONE_DEVICE) || | |
| 333 | − IS_ENABLED(CONFIG_FS_DAX_LIMITED)) { | |
| 318 | + if (IS_ENABLED(CONFIG_FS_DAX_LIMITED)) { | |
| 334 | 319 | WARN(1, "File system DAX not supported\n"); |
| 335 | 320 | return ERR_PTR(-EINVAL); |
| 336 | 321 | } |
| @@ -466,21 +451,17 @@ struct dev_pagemap *get_dev_pagemap(unsigned long pfn, · 129 unmodified lines | ||
| 466 | 451 | } |
| 467 | 452 | EXPORT_SYMBOL_GPL(get_dev_pagemap); |
| 468 | 453 | |
| 469 | −#ifdef CONFIG_DEV_PAGEMAP_OPS | |
| 470 | −void free_devmap_managed_page(struct page *page) | |
| 454 | +void free_zone_device_page(struct page *page) | |
| 471 | 455 | { |
| 472 | − /* notify page idle for dax */ | |
| 473 | − if (!is_device_private_page(page)) { | |
| 474 | − wake_up_var(&page->_refcount); | |
| 456 | + if (WARN_ON_ONCE(!page->pgmap->ops || !page->pgmap->ops->page_free)) | |
| 475 | 457 | return; |
| 476 | − } | |
| 477 | 458 | |
| 478 | 459 | __ClearPageWaiters(page); |
| 479 | 460 | |
| 480 | 461 | mem_cgroup_uncharge(page_folio(page)); |
| 481 | 462 | |
| 482 | 463 | /* |
| 483 | − * When a device_private page is freed, the page->mapping field | |
| 464 | + * When a device managed page is freed, the page->mapping field | |
| 484 | 465 | * may still contain a (stale) mapping value. For example, the |
| 485 | 466 | * lower bits of page->mapping may still identify the page as an |
| 486 | 467 | * anonymous page. Ultimately, this entire field is just stale |
| @@ -502,5 +483,27 @@ void free_devmap_managed_page(struct page *page) · 15 unmodified lines | ||
| 502 | 483 | */ |
| 503 | 484 | page->mapping = NULL; |
| 504 | 485 | page->pgmap->ops->page_free(page); |
| 486 | + | |
| 487 | + /* | |
| 488 | + * Reset the page count to 1 to prepare for handing out the page again. | |
| 489 | + */ | |
| 490 | + set_page_count(page, 1); | |
| 491 | +} | |
| 492 | + | |
| 493 | +#ifdef CONFIG_FS_DAX | |
| 494 | +bool __put_devmap_managed_page(struct page *page) | |
| 495 | +{ | |
| 496 | + if (page->pgmap->type != MEMORY_DEVICE_FS_DAX) | |
| 497 | + return false; | |
| 498 | + | |
| 499 | + /* | |
| 500 | + * fsdax page refcounts are 1-based, rather than 0-based: if | |
| 501 | + * refcount is 1, then the page is free and the refcount is | |
| 502 | + * stable because nobody holds a reference on the page. | |
| 503 | + */ | |
| 504 | + if (page_ref_dec_return(page) == 1) | |
| 505 | + wake_up_var(&page->_refcount); | |
| 506 | + return true; | |
| 505 | 507 | } |
| 506 | −#endif /* CONFIG_DEV_PAGEMAP_OPS */ | |
| 508 | +EXPORT_SYMBOL(__put_devmap_managed_page); | |
| 509 | +#endif /* CONFIG_FS_DAX */ | |
| @@ -38,12 +38,10 @@ · 37 unmodified lines | ||
| 38 | 38 | #include <linux/hugetlb.h> |
| 39 | 39 | #include <linux/hugetlb_cgroup.h> |
| 40 | 40 | #include <linux/gfp.h> |
| 41 | −#include <linux/pagewalk.h> | |
| 42 | 41 | #include <linux/pfn_t.h> |
| 43 | 42 | #include <linux/memremap.h> |
| 44 | 43 | #include <linux/userfaultfd_k.h> |
| 45 | 44 | #include <linux/balloon_compaction.h> |
| 46 | −#include <linux/mmu_notifier.h> | |
| 47 | 45 | #include <linux/page_idle.h> |
| 48 | 46 | #include <linux/page_owner.h> |
| 49 | 47 | #include <linux/sched/mm.h> |
| @@ -174,37 +172,33 @@ void putback_movable_pages(struct list_head *l) · 124 unmodified lines | ||
| 174 | 172 | /* |
| 175 | 173 | * Restore a potential migration pte to a working pte entry |
| 176 | 174 | */ |
| 177 | −static bool remove_migration_pte(struct page *page, struct vm_area_struct *vma, | |
| 178 | − unsigned long addr, void *old) | |
| 175 | +static bool remove_migration_pte(struct folio *folio, | |
| 176 | + struct vm_area_struct *vma, unsigned long addr, void *old) | |
| 179 | 177 | { |
| 180 | − struct page_vma_mapped_walk pvmw = { | |
| 181 | − .page = old, | |
| 182 | − .vma = vma, | |
| 183 | − .address = addr, | |
| 184 | − .flags = PVMW_SYNC | PVMW_MIGRATION, | |
| 185 | − }; | |
| 186 | − struct page *new; | |
| 187 | − pte_t pte; | |
| 188 | − swp_entry_t entry; | |
| 178 | + DEFINE_FOLIO_VMA_WALK(pvmw, old, vma, addr, PVMW_SYNC | PVMW_MIGRATION); | |
| 189 | 179 | |
| 190 | − VM_BUG_ON_PAGE(PageTail(page), page); | |
| 191 | 180 | while (page_vma_mapped_walk(&pvmw)) { |
| 192 | − if (PageKsm(page)) | |
| 193 | − new = page; | |
| 194 | − else | |
| 195 | − new = page - pvmw.page->index + | |
| 196 | − linear_page_index(vma, pvmw.address); | |
| 181 | + pte_t pte; | |
| 182 | + swp_entry_t entry; | |
| 183 | + struct page *new; | |
| 184 | + unsigned long idx = 0; | |
| 185 | + | |
| 186 | + /* pgoff is invalid for ksm pages, but they are never large */ | |
| 187 | + if (folio_test_large(folio) && !folio_test_hugetlb(folio)) | |
| 188 | + idx = linear_page_index(vma, pvmw.address) - pvmw.pgoff; | |
| 189 | + new = folio_page(folio, idx); | |
| 197 | 190 | |
| 198 | 191 | #ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION |
| 199 | 192 | /* PMD-mapped THP migration entry */ |
| 200 | 193 | if (!pvmw.pte) { |
| 201 | − VM_BUG_ON_PAGE(PageHuge(page) || !PageTransCompound(page), page); | |
| 194 | + VM_BUG_ON_FOLIO(folio_test_hugetlb(folio) || | |
| 195 | + !folio_test_pmd_mappable(folio), folio); | |
| 202 | 196 | remove_migration_pmd(&pvmw, new); |
| 203 | 197 | continue; |
| 204 | 198 | } |
| 205 | 199 | #endif |
| 206 | 200 | |
| 207 | − get_page(new); | |
| 201 | + folio_get(folio); | |
| 208 | 202 | pte = pte_mkold(mk_pte(new, READ_ONCE(vma->vm_page_prot))); |
| 209 | 203 | if (pte_swp_soft_dirty(*pvmw.pte)) |
| 210 | 204 | pte = pte_mksoft_dirty(pte); |
| @@ -233,12 +227,12 @@ static bool remove_migration_pte(struct page *page, struct vm_area_struct *vma, · 22 unmodified lines | ||
| 233 | 227 | } |
| 234 | 228 | |
| 235 | 229 | #ifdef CONFIG_HUGETLB_PAGE |
| 236 | − if (PageHuge(new)) { | |
| 230 | + if (folio_test_hugetlb(folio)) { | |
| 237 | 231 | unsigned int shift = huge_page_shift(hstate_vma(vma)); |
| 238 | 232 | |
| 239 | 233 | pte = pte_mkhuge(pte); |
| 240 | 234 | pte = arch_make_huge_pte(pte, shift, vma->vm_flags); |
| 241 | − if (PageAnon(new)) | |
| 235 | + if (folio_test_anon(folio)) | |
| 242 | 236 | hugepage_add_anon_rmap(new, vma, pvmw.address); |
| 243 | 237 | else |
| 244 | 238 | page_dup_rmap(new, true); |
| @@ -246,17 +240,14 @@ static bool remove_migration_pte(struct page *page, struct vm_area_struct *vma, · 1 unmodified line | ||
| 246 | 240 | } else |
| 247 | 241 | #endif |
| 248 | 242 | { |
| 249 | − if (PageAnon(new)) | |
| 243 | + if (folio_test_anon(folio)) | |
| 250 | 244 | page_add_anon_rmap(new, vma, pvmw.address, false); |
| 251 | 245 | else |
| 252 | − page_add_file_rmap(new, false); | |
| 246 | + page_add_file_rmap(new, vma, false); | |
| 253 | 247 | set_pte_at(vma->vm_mm, pvmw.address, pvmw.pte, pte); |
| 254 | 248 | } |
| 255 | − if (vma->vm_flags & VM_LOCKED && !PageTransCompound(new)) | |
| 256 | − mlock_vma_page(new); | |
| 257 | − | |
| 258 | − if (PageTransHuge(page) && PageMlocked(page)) | |
| 259 | − clear_page_mlock(page); | |
| 249 | + if (vma->vm_flags & VM_LOCKED) | |
| 250 | + mlock_page_drain(smp_processor_id()); | |
| 260 | 251 | |
| 261 | 252 | /* No need to invalidate - it was non-present before */ |
| 262 | 253 | update_mmu_cache(vma, pvmw.address, pvmw.pte); |
| @@ -269,17 +260,17 @@ static bool remove_migration_pte(struct page *page, struct vm_area_struct *vma, · 6 unmodified lines | ||
| 269 | 260 | * Get rid of all migration entries and replace them by |
| 270 | 261 | * references to the indicated page. |
| 271 | 262 | */ |
| 272 | −void remove_migration_ptes(struct page *old, struct page *new, bool locked) | |
| 263 | +void remove_migration_ptes(struct folio *src, struct folio *dst, bool locked) | |
| 273 | 264 | { |
| 274 | 265 | struct rmap_walk_control rwc = { |
| 275 | 266 | .rmap_one = remove_migration_pte, |
| 276 | − .arg = old, | |
| 267 | + .arg = src, | |
| 277 | 268 | }; |
| 278 | 269 | |
| 279 | 270 | if (locked) |
| 280 | − rmap_walk_locked(new, &rwc); | |
| 271 | + rmap_walk_locked(dst, &rwc); | |
| 281 | 272 | else |
| 282 | − rmap_walk(new, &rwc); | |
| 273 | + rmap_walk(dst, &rwc); | |
| 283 | 274 | } |
| 284 | 275 | |
| 285 | 276 | /* |
| @@ -342,14 +333,8 @@ static int expected_page_refs(struct address_space *mapping, struct page *page) · 56 unmodified lines | ||
| 342 | 333 | { |
| 343 | 334 | int expected_count = 1; |
| 344 | 335 | |
| 345 | − /* | |
| 346 | − * Device private pages have an extra refcount as they are | |
| 347 | − * ZONE_DEVICE pages. | |
| 348 | − */ | |
| 349 | − expected_count += is_device_private_page(page); | |
| 350 | 336 | if (mapping) |
| 351 | 337 | expected_count += compound_nr(page) + page_has_private(page); |
| 352 | − | |
| 353 | 338 | return expected_count; |
| 354 | 339 | } |
| 355 | 340 | |
| @@ -772,6 +757,7 @@ int buffer_migrate_page_norefs(struct address_space *mapping, · 416 unmodified lines | ||
| 772 | 757 | */ |
| 773 | 758 | static int writeout(struct address_space *mapping, struct page *page) |
| 774 | 759 | { |
| 760 | + struct folio *folio = page_folio(page); | |
| 775 | 761 | struct writeback_control wbc = { |
| 776 | 762 | .sync_mode = WB_SYNC_NONE, |
| 777 | 763 | .nr_to_write = 1, |
| @@ -797,7 +783,7 @@ static int writeout(struct address_space *mapping, struct page *page) · 19 unmodified lines | ||
| 797 | 783 | * At this point we know that the migration attempt cannot |
| 798 | 784 | * be successful. |
| 799 | 785 | */ |
| 800 | − remove_migration_ptes(page, page, false); | |
| 786 | + remove_migration_ptes(folio, folio, false); | |
| 801 | 787 | |
| 802 | 788 | rc = mapping->a_ops->writepage(page, &wbc); |
| 803 | 789 | |
| @@ -927,6 +913,8 @@ out: · 123 unmodified lines | ||
| 927 | 913 | static int __unmap_and_move(struct page *page, struct page *newpage, |
| 928 | 914 | int force, enum migrate_mode mode) |
| 929 | 915 | { |
| 916 | + struct folio *folio = page_folio(page); | |
| 917 | + struct folio *dst = page_folio(newpage); | |
| 930 | 918 | int rc = -EAGAIN; |
| 931 | 919 | bool page_was_mapped = false; |
| 932 | 920 | struct anon_vma *anon_vma = NULL; |
| @@ -1030,16 +1018,31 @@ static int __unmap_and_move(struct page *page, struct page *newpage, · 97 unmodified lines | ||
| 1030 | 1018 | /* Establish migration ptes */ |
| 1031 | 1019 | VM_BUG_ON_PAGE(PageAnon(page) && !PageKsm(page) && !anon_vma, |
| 1032 | 1020 | page); |
| 1033 | − try_to_migrate(page, 0); | |
| 1021 | + try_to_migrate(folio, 0); | |
| 1034 | 1022 | page_was_mapped = true; |
| 1035 | 1023 | } |
| 1036 | 1024 | |
| 1037 | 1025 | if (!page_mapped(page)) |
| 1038 | 1026 | rc = move_to_new_page(newpage, page, mode); |
| 1039 | 1027 | |
| 1028 | + /* | |
| 1029 | + * When successful, push newpage to LRU immediately: so that if it | |
| 1030 | + * turns out to be an mlocked page, remove_migration_ptes() will | |
| 1031 | + * automatically build up the correct newpage->mlock_count for it. | |
| 1032 | + * | |
| 1033 | + * We would like to do something similar for the old page, when | |
| 1034 | + * unsuccessful, and other cases when a page has been temporarily | |
| 1035 | + * isolated from the unevictable LRU: but this case is the easiest. | |
| 1036 | + */ | |
| 1037 | + if (rc == MIGRATEPAGE_SUCCESS) { | |
| 1038 | + lru_cache_add(newpage); | |
| 1039 | + if (page_was_mapped) | |
| 1040 | + lru_add_drain(); | |
| 1041 | + } | |
| 1042 | + | |
| 1040 | 1043 | if (page_was_mapped) |
| 1041 | − remove_migration_ptes(page, | |
| 1042 | − rc == MIGRATEPAGE_SUCCESS ? newpage : page, false); | |
| 1044 | + remove_migration_ptes(folio, | |
| 1045 | + rc == MIGRATEPAGE_SUCCESS ? dst : folio, false); | |
| 1043 | 1046 | |
| 1044 | 1047 | out_unlock_both: |
| 1045 | 1048 | unlock_page(newpage); |
| @@ -1050,20 +1053,12 @@ out_unlock: · 4 unmodified lines | ||
| 1050 | 1053 | unlock_page(page); |
| 1051 | 1054 | out: |
| 1052 | 1055 | /* |
| 1053 | − * If migration is successful, decrease refcount of the newpage | |
| 1056 | + * If migration is successful, decrease refcount of the newpage, | |
| 1054 | 1057 | * which will not free the page because new page owner increased |
| 1055 | − * refcounter. As well, if it is LRU page, add the page to LRU | |
| 1056 | − * list in here. Use the old state of the isolated source page to | |
| 1057 | − * determine if we migrated a LRU page. newpage was already unlocked | |
| 1058 | − * and possibly modified by its owner - don't rely on the page | |
| 1059 | − * state. | |
| 1058 | + * refcounter. | |
| 1060 | 1059 | */ |
| 1061 | − if (rc == MIGRATEPAGE_SUCCESS) { | |
| 1062 | − if (unlikely(!is_lru)) | |
| 1063 | − put_page(newpage); | |
| 1064 | − else | |
| 1065 | − putback_lru_page(newpage); | |
| 1066 | − } | |
| 1060 | + if (rc == MIGRATEPAGE_SUCCESS) | |
| 1061 | + put_page(newpage); | |
| 1067 | 1062 | |
| 1068 | 1063 | return rc; |
| 1069 | 1064 | } |
| @@ -1173,6 +1168,7 @@ static int unmap_and_move_huge_page(new_page_t get_new_page, · 103 unmodified lines | ||
| 1173 | 1168 | enum migrate_mode mode, int reason, |
| 1174 | 1169 | struct list_head *ret) |
| 1175 | 1170 | { |
| 1171 | + struct folio *dst, *src = page_folio(hpage); | |
| 1176 | 1172 | int rc = -EAGAIN; |
| 1177 | 1173 | int page_was_mapped = 0; |
| 1178 | 1174 | struct page *new_hpage; |
| @@ -1200,6 +1196,7 @@ static int unmap_and_move_huge_page(new_page_t get_new_page, · 21 unmodified lines | ||
| 1200 | 1196 | new_hpage = get_new_page(hpage, private); |
| 1201 | 1197 | if (!new_hpage) |
| 1202 | 1198 | return -ENOMEM; |
| 1199 | + dst = page_folio(new_hpage); | |
| 1203 | 1200 | |
| 1204 | 1201 | if (!trylock_page(hpage)) { |
| 1205 | 1202 | if (!force) |
| @@ -1249,7 +1246,7 @@ static int unmap_and_move_huge_page(new_page_t get_new_page, · 43 unmodified lines | ||
| 1249 | 1246 | ttu |= TTU_RMAP_LOCKED; |
| 1250 | 1247 | } |
| 1251 | 1248 | |
| 1252 | − try_to_migrate(hpage, ttu); | |
| 1249 | + try_to_migrate(src, ttu); | |
| 1253 | 1250 | page_was_mapped = 1; |
| 1254 | 1251 | |
| 1255 | 1252 | if (mapping_locked) |
| @@ -1260,8 +1257,8 @@ static int unmap_and_move_huge_page(new_page_t get_new_page, · 4 unmodified lines | ||
| 1260 | 1257 | rc = move_to_new_page(new_hpage, hpage, mode); |
| 1261 | 1258 | |
| 1262 | 1259 | if (page_was_mapped) |
| 1263 | − remove_migration_ptes(hpage, | |
| 1264 | − rc == MIGRATEPAGE_SUCCESS ? new_hpage : hpage, false); | |
| 1260 | + remove_migration_ptes(src, | |
| 1261 | + rc == MIGRATEPAGE_SUCCESS ? dst : src, false); | |
| 1265 | 1262 | |
| 1266 | 1263 | unlock_put_anon: |
| 1267 | 1264 | unlock_page(new_hpage); |
| @@ -2147,761 +2144,6 @@ out: · 879 unmodified lines | ||
| 2147 | 2144 | #endif /* CONFIG_NUMA_BALANCING */ |
| 2148 | 2145 | #endif /* CONFIG_NUMA */ |
| 2149 | 2146 | |
| 2150 | −#ifdef CONFIG_DEVICE_PRIVATE | |
| 2151 | −static int migrate_vma_collect_skip(unsigned long start, | |
| 2152 | − unsigned long end, | |
| 2153 | − struct mm_walk *walk) | |
| 2154 | −{ | |
| 2155 | − struct migrate_vma *migrate = walk->private; | |
| 2156 | − unsigned long addr; | |
| 2157 | − | |
| 2158 | − for (addr = start; addr < end; addr += PAGE_SIZE) { | |
| 2159 | − migrate->dst[migrate->npages] = 0; | |
| 2160 | − migrate->src[migrate->npages++] = 0; | |
| 2161 | − } | |
| 2162 | − | |
| 2163 | − return 0; | |
| 2164 | −} | |
| 2165 | − | |
| 2166 | −static int migrate_vma_collect_hole(unsigned long start, | |
| 2167 | − unsigned long end, | |
| 2168 | − __always_unused int depth, | |
| 2169 | − struct mm_walk *walk) | |
| 2170 | −{ | |
| 2171 | − struct migrate_vma *migrate = walk->private; | |
| 2172 | − unsigned long addr; | |
| 2173 | − | |
| 2174 | − /* Only allow populating anonymous memory. */ | |
| 2175 | − if (!vma_is_anonymous(walk->vma)) | |
| 2176 | − return migrate_vma_collect_skip(start, end, walk); | |
| 2177 | − | |
| 2178 | − for (addr = start; addr < end; addr += PAGE_SIZE) { | |
| 2179 | − migrate->src[migrate->npages] = MIGRATE_PFN_MIGRATE; | |
| 2180 | − migrate->dst[migrate->npages] = 0; | |
| 2181 | − migrate->npages++; | |
| 2182 | − migrate->cpages++; | |
| 2183 | − } | |
| 2184 | − | |
| 2185 | − return 0; | |
| 2186 | −} | |
| 2187 | − | |
| 2188 | −static int migrate_vma_collect_pmd(pmd_t *pmdp, | |
| 2189 | − unsigned long start, | |
| 2190 | − unsigned long end, | |
| 2191 | − struct mm_walk *walk) | |
| 2192 | −{ | |
| 2193 | − struct migrate_vma *migrate = walk->private; | |
| 2194 | − struct vm_area_struct *vma = walk->vma; | |
| 2195 | − struct mm_struct *mm = vma->vm_mm; | |
| 2196 | − unsigned long addr = start, unmapped = 0; | |
| 2197 | − spinlock_t *ptl; | |
| 2198 | − pte_t *ptep; | |
| 2199 | − | |
| 2200 | −again: | |
| 2201 | − if (pmd_none(*pmdp)) | |
| 2202 | − return migrate_vma_collect_hole(start, end, -1, walk); | |
| 2203 | − | |
| 2204 | − if (pmd_trans_huge(*pmdp)) { | |
| 2205 | − struct page *page; | |
| 2206 | − | |
| 2207 | − ptl = pmd_lock(mm, pmdp); | |
| 2208 | − if (unlikely(!pmd_trans_huge(*pmdp))) { | |
| 2209 | − spin_unlock(ptl); | |
| 2210 | − goto again; | |
| 2211 | − } | |
| 2212 | − | |
| 2213 | − page = pmd_page(*pmdp); | |
| 2214 | − if (is_huge_zero_page(page)) { | |
| 2215 | − spin_unlock(ptl); | |
| 2216 | − split_huge_pmd(vma, pmdp, addr); | |
| 2217 | − if (pmd_trans_unstable(pmdp)) | |
| 2218 | − return migrate_vma_collect_skip(start, end, | |
| 2219 | − walk); | |
| 2220 | − } else { | |
| 2221 | − int ret; | |
| 2222 | − | |
| 2223 | − get_page(page); | |
| 2224 | − spin_unlock(ptl); | |
| 2225 | − if (unlikely(!trylock_page(page))) | |
| 2226 | − return migrate_vma_collect_skip(start, end, | |
| 2227 | − walk); | |
| 2228 | − ret = split_huge_page(page); | |
| 2229 | − unlock_page(page); | |
| 2230 | − put_page(page); | |
| 2231 | − if (ret) | |
| 2232 | − return migrate_vma_collect_skip(start, end, | |
| 2233 | − walk); | |
| 2234 | − if (pmd_none(*pmdp)) | |
| 2235 | − return migrate_vma_collect_hole(start, end, -1, | |
| 2236 | − walk); | |
| 2237 | − } | |
| 2238 | − } | |
| 2239 | − | |
| 2240 | − if (unlikely(pmd_bad(*pmdp))) | |
| 2241 | − return migrate_vma_collect_skip(start, end, walk); | |
| 2242 | − | |
| 2243 | − ptep = pte_offset_map_lock(mm, pmdp, addr, &ptl); | |
| 2244 | − arch_enter_lazy_mmu_mode(); | |
| 2245 | − | |
| 2246 | − for (; addr < end; addr += PAGE_SIZE, ptep++) { | |
| 2247 | − unsigned long mpfn = 0, pfn; | |
| 2248 | − struct page *page; | |
| 2249 | − swp_entry_t entry; | |
| 2250 | − pte_t pte; | |
| 2251 | − | |
| 2252 | − pte = *ptep; | |
| 2253 | − | |
| 2254 | − if (pte_none(pte)) { | |
| 2255 | − if (vma_is_anonymous(vma)) { | |
| 2256 | − mpfn = MIGRATE_PFN_MIGRATE; | |
| 2257 | − migrate->cpages++; | |
| 2258 | − } | |
| 2259 | − goto next; | |
| 2260 | − } | |
| 2261 | − | |
| 2262 | − if (!pte_present(pte)) { | |
| 2263 | − /* | |
| 2264 | − * Only care about unaddressable device page special | |
| 2265 | − * page table entry. Other special swap entries are not | |
| 2266 | − * migratable, and we ignore regular swapped page. | |
| 2267 | − */ | |
| 2268 | − entry = pte_to_swp_entry(pte); | |
| 2269 | − if (!is_device_private_entry(entry)) | |
| 2270 | − goto next; | |
| 2271 | − | |
| 2272 | − page = pfn_swap_entry_to_page(entry); | |
| 2273 | − if (!(migrate->flags & | |
| 2274 | − MIGRATE_VMA_SELECT_DEVICE_PRIVATE) || | |
| 2275 | − page->pgmap->owner != migrate->pgmap_owner) | |
| 2276 | − goto next; | |
| 2277 | − | |
| 2278 | − mpfn = migrate_pfn(page_to_pfn(page)) | | |
| 2279 | − MIGRATE_PFN_MIGRATE; | |
| 2280 | − if (is_writable_device_private_entry(entry)) | |
| 2281 | − mpfn |= MIGRATE_PFN_WRITE; | |
| 2282 | − } else { | |
| 2283 | − if (!(migrate->flags & MIGRATE_VMA_SELECT_SYSTEM)) | |
| 2284 | − goto next; | |
| 2285 | − pfn = pte_pfn(pte); | |
| 2286 | − if (is_zero_pfn(pfn)) { | |
| 2287 | − mpfn = MIGRATE_PFN_MIGRATE; | |
| 2288 | − migrate->cpages++; | |
| 2289 | − goto next; | |
| 2290 | − } | |
| 2291 | − page = vm_normal_page(migrate->vma, addr, pte); | |
| 2292 | − mpfn = migrate_pfn(pfn) | MIGRATE_PFN_MIGRATE; | |
| 2293 | − mpfn |= pte_write(pte) ? MIGRATE_PFN_WRITE : 0; | |
| 2294 | − } | |
| 2295 | − | |
| 2296 | − /* FIXME support THP */ | |
| 2297 | − if (!page || !page->mapping || PageTransCompound(page)) { | |
| 2298 | − mpfn = 0; | |
| 2299 | − goto next; | |
| 2300 | − } | |
| 2301 | − | |
| 2302 | − /* | |
| 2303 | − * By getting a reference on the page we pin it and that blocks | |
| 2304 | − * any kind of migration. Side effect is that it "freezes" the | |
| 2305 | − * pte. | |
| 2306 | − * | |
| 2307 | − * We drop this reference after isolating the page from the lru | |
| 2308 | − * for non device page (device page are not on the lru and thus | |
| 2309 | − * can't be dropped from it). | |
| 2310 | − */ | |
| 2311 | − get_page(page); | |
| 2312 | − | |
| 2313 | − /* | |
| 2314 | − * Optimize for the common case where page is only mapped once | |
| 2315 | − * in one process. If we can lock the page, then we can safely | |
| 2316 | − * set up a special migration page table entry now. | |
| 2317 | − */ | |
| 2318 | − if (trylock_page(page)) { | |
| 2319 | − pte_t swp_pte; | |
| 2320 | − | |
| 2321 | − migrate->cpages++; | |
| 2322 | − ptep_get_and_clear(mm, addr, ptep); | |
| 2323 | − | |
| 2324 | − /* Setup special migration page table entry */ | |
| 2325 | − if (mpfn & MIGRATE_PFN_WRITE) | |
| 2326 | − entry = make_writable_migration_entry( | |
| 2327 | − page_to_pfn(page)); | |
| 2328 | − else | |
| 2329 | − entry = make_readable_migration_entry( | |
| 2330 | − page_to_pfn(page)); | |
| 2331 | − swp_pte = swp_entry_to_pte(entry); | |
| 2332 | − if (pte_present(pte)) { | |
| 2333 | − if (pte_soft_dirty(pte)) | |
| 2334 | − swp_pte = pte_swp_mksoft_dirty(swp_pte); | |
| 2335 | − if (pte_uffd_wp(pte)) | |
| 2336 | − swp_pte = pte_swp_mkuffd_wp(swp_pte); | |
| 2337 | − } else { | |
| 2338 | − if (pte_swp_soft_dirty(pte)) | |
| 2339 | − swp_pte = pte_swp_mksoft_dirty(swp_pte); | |
| 2340 | − if (pte_swp_uffd_wp(pte)) | |
| 2341 | − swp_pte = pte_swp_mkuffd_wp(swp_pte); | |
| 2342 | − } | |
| 2343 | − set_pte_at(mm, addr, ptep, swp_pte); | |
| 2344 | − | |
| 2345 | − /* | |
| 2346 | − * This is like regular unmap: we remove the rmap and | |
| 2347 | − * drop page refcount. Page won't be freed, as we took | |
| 2348 | − * a reference just above. | |
| 2349 | − */ | |
| 2350 | − page_remove_rmap(page, false); | |
| 2351 | − put_page(page); | |
| 2352 | − | |
| 2353 | − if (pte_present(pte)) | |
| 2354 | − unmapped++; | |
| 2355 | − } else { | |
| 2356 | − put_page(page); | |
| 2357 | − mpfn = 0; | |
| 2358 | − } | |
| 2359 | − | |
| 2360 | −next: | |
| 2361 | − migrate->dst[migrate->npages] = 0; | |
| 2362 | − migrate->src[migrate->npages++] = mpfn; | |
| 2363 | − } | |
| 2364 | − arch_leave_lazy_mmu_mode(); | |
| 2365 | − pte_unmap_unlock(ptep - 1, ptl); | |
| 2366 | − | |
| 2367 | − /* Only flush the TLB if we actually modified any entries */ | |
| 2368 | − if (unmapped) | |
| 2369 | − flush_tlb_range(walk->vma, start, end); | |
| 2370 | − | |
| 2371 | − return 0; | |
| 2372 | −} | |
| 2373 | − | |
| 2374 | −static const struct mm_walk_ops migrate_vma_walk_ops = { | |
| 2375 | − .pmd_entry = migrate_vma_collect_pmd, | |
| 2376 | − .pte_hole = migrate_vma_collect_hole, | |
| 2377 | −}; | |
| 2378 | − | |
| 2379 | −/* | |
| 2380 | − * migrate_vma_collect() - collect pages over a range of virtual addresses | |
| 2381 | − * @migrate: migrate struct containing all migration information | |
| 2382 | − * | |
| 2383 | − * This will walk the CPU page table. For each virtual address backed by a | |
| 2384 | − * valid page, it updates the src array and takes a reference on the page, in | |
| 2385 | − * order to pin the page until we lock it and unmap it. | |
| 2386 | − */ | |
| 2387 | −static void migrate_vma_collect(struct migrate_vma *migrate) | |
| 2388 | −{ | |
| 2389 | − struct mmu_notifier_range range; | |
| 2390 | − | |
| 2391 | − /* | |
| 2392 | − * Note that the pgmap_owner is passed to the mmu notifier callback so | |
| 2393 | − * that the registered device driver can skip invalidating device | |
| 2394 | − * private page mappings that won't be migrated. | |
| 2395 | − */ | |
| 2396 | − mmu_notifier_range_init_owner(&range, MMU_NOTIFY_MIGRATE, 0, | |
| 2397 | − migrate->vma, migrate->vma->vm_mm, migrate->start, migrate->end, | |
| 2398 | − migrate->pgmap_owner); | |
| 2399 | − mmu_notifier_invalidate_range_start(&range); | |
| 2400 | − | |
| 2401 | − walk_page_range(migrate->vma->vm_mm, migrate->start, migrate->end, | |
| 2402 | − &migrate_vma_walk_ops, migrate); | |
| 2403 | − | |
| 2404 | − mmu_notifier_invalidate_range_end(&range); | |
| 2405 | − migrate->end = migrate->start + (migrate->npages << PAGE_SHIFT); | |
| 2406 | −} | |
| 2407 | − | |
| 2408 | −/* | |
| 2409 | − * migrate_vma_check_page() - check if page is pinned or not | |
| 2410 | − * @page: struct page to check | |
| 2411 | − * | |
| 2412 | − * Pinned pages cannot be migrated. This is the same test as in | |
| 2413 | − * folio_migrate_mapping(), except that here we allow migration of a | |
| 2414 | − * ZONE_DEVICE page. | |
| 2415 | − */ | |
| 2416 | −static bool migrate_vma_check_page(struct page *page) | |
| 2417 | −{ | |
| 2418 | − /* | |
| 2419 | − * One extra ref because caller holds an extra reference, either from | |
| 2420 | − * isolate_lru_page() for a regular page, or migrate_vma_collect() for | |
| 2421 | − * a device page. | |
| 2422 | − */ | |
| 2423 | − int extra = 1; | |
| 2424 | − | |
| 2425 | − /* | |
| 2426 | − * FIXME support THP (transparent huge page), it is bit more complex to | |
| 2427 | − * check them than regular pages, because they can be mapped with a pmd | |
| 2428 | − * or with a pte (split pte mapping). | |
| 2429 | − */ | |
| 2430 | − if (PageCompound(page)) | |
| 2431 | − return false; | |
| 2432 | − | |
| 2433 | − /* Page from ZONE_DEVICE have one extra reference */ | |
| 2434 | − if (is_zone_device_page(page)) | |
| 2435 | − extra++; | |
| 2436 | − | |
| 2437 | − /* For file back page */ | |
| 2438 | − if (page_mapping(page)) | |
| 2439 | − extra += 1 + page_has_private(page); | |
| 2440 | − | |
| 2441 | − if ((page_count(page) - extra) > page_mapcount(page)) | |
| 2442 | − return false; | |
| 2443 | − | |
| 2444 | − return true; | |
| 2445 | −} | |
| 2446 | − | |
| 2447 | −/* | |
| 2448 | − * migrate_vma_unmap() - replace page mapping with special migration pte entry | |
| 2449 | − * @migrate: migrate struct containing all migration information | |
| 2450 | − * | |
| 2451 | − * Isolate pages from the LRU and replace mappings (CPU page table pte) with a | |
| 2452 | − * special migration pte entry and check if it has been pinned. Pinned pages are | |
| 2453 | − * restored because we cannot migrate them. | |
| 2454 | − * | |
| 2455 | − * This is the last step before we call the device driver callback to allocate | |
| 2456 | − * destination memory and copy contents of original page over to new page. | |
| 2457 | − */ | |
| 2458 | −static void migrate_vma_unmap(struct migrate_vma *migrate) | |
| 2459 | −{ | |
| 2460 | − const unsigned long npages = migrate->npages; | |
| 2461 | − unsigned long i, restore = 0; | |
| 2462 | − bool allow_drain = true; | |
| 2463 | − | |
| 2464 | − lru_add_drain(); | |
| 2465 | − | |
| 2466 | − for (i = 0; i < npages; i++) { | |
| 2467 | − struct page *page = migrate_pfn_to_page(migrate->src[i]); | |
| 2468 | − | |
| 2469 | − if (!page) | |
| 2470 | − continue; | |
| 2471 | − | |
| 2472 | − /* ZONE_DEVICE pages are not on LRU */ | |
| 2473 | − if (!is_zone_device_page(page)) { | |
| 2474 | − if (!PageLRU(page) && allow_drain) { | |
| 2475 | − /* Drain CPU's pagevec */ | |
| 2476 | − lru_add_drain_all(); | |
| 2477 | − allow_drain = false; | |
| 2478 | − } | |
| 2479 | − | |
| 2480 | − if (isolate_lru_page(page)) { | |
| 2481 | − migrate->src[i] &= ~MIGRATE_PFN_MIGRATE; | |
| 2482 | − migrate->cpages--; | |
| 2483 | − restore++; | |
| 2484 | − continue; | |
| 2485 | − } | |
| 2486 | − | |
| 2487 | − /* Drop the reference we took in collect */ | |
| 2488 | − put_page(page); | |
| 2489 | − } | |
| 2490 | − | |
| 2491 | − if (page_mapped(page)) | |
| 2492 | − try_to_migrate(page, 0); | |
| 2493 | − | |
| 2494 | − if (page_mapped(page) || !migrate_vma_check_page(page)) { | |
| 2495 | − if (!is_zone_device_page(page)) { | |
| 2496 | − get_page(page); | |
| 2497 | − putback_lru_page(page); | |
| 2498 | − } | |
| 2499 | − | |
| 2500 | − migrate->src[i] &= ~MIGRATE_PFN_MIGRATE; | |
| 2501 | − migrate->cpages--; | |
| 2502 | − restore++; | |
| 2503 | − continue; | |
| 2504 | − } | |
| 2505 | − } | |
| 2506 | − | |
| 2507 | − for (i = 0; i < npages && restore; i++) { | |
| 2508 | − struct page *page = migrate_pfn_to_page(migrate->src[i]); | |
| 2509 | − | |
| 2510 | − if (!page || (migrate->src[i] & MIGRATE_PFN_MIGRATE)) | |
| 2511 | − continue; | |
| 2512 | − | |
| 2513 | − remove_migration_ptes(page, page, false); | |
| 2514 | − | |
| 2515 | − migrate->src[i] = 0; | |
| 2516 | − unlock_page(page); | |
| 2517 | − put_page(page); | |
| 2518 | − restore--; | |
| 2519 | − } | |
| 2520 | −} | |
| 2521 | − | |
| 2522 | −/** | |
| 2523 | − * migrate_vma_setup() - prepare to migrate a range of memory | |
| 2524 | − * @args: contains the vma, start, and pfns arrays for the migration | |
| 2525 | − * | |
| 2526 | − * Returns: negative errno on failures, 0 when 0 or more pages were migrated | |
| 2527 | − * without an error. | |
| 2528 | − * | |
| 2529 | − * Prepare to migrate a range of memory virtual address range by collecting all | |
| 2530 | − * the pages backing each virtual address in the range, saving them inside the | |
| 2531 | − * src array. Then lock those pages and unmap them. Once the pages are locked | |
| 2532 | − * and unmapped, check whether each page is pinned or not. Pages that aren't | |
| 2533 | − * pinned have the MIGRATE_PFN_MIGRATE flag set (by this function) in the | |
| 2534 | − * corresponding src array entry. Then restores any pages that are pinned, by | |
| 2535 | − * remapping and unlocking those pages. | |
| 2536 | − * | |
| 2537 | − * The caller should then allocate destination memory and copy source memory to | |
| 2538 | − * it for all those entries (ie with MIGRATE_PFN_VALID and MIGRATE_PFN_MIGRATE | |
| 2539 | − * flag set). Once these are allocated and copied, the caller must update each | |
| 2540 | − * corresponding entry in the dst array with the pfn value of the destination | |
| 2541 | − * page and with MIGRATE_PFN_VALID. Destination pages must be locked via | |
| 2542 | − * lock_page(). | |
| 2543 | − * | |
| 2544 | − * Note that the caller does not have to migrate all the pages that are marked | |
| 2545 | − * with MIGRATE_PFN_MIGRATE flag in src array unless this is a migration from | |
| 2546 | − * device memory to system memory. If the caller cannot migrate a device page | |
| 2547 | − * back to system memory, then it must return VM_FAULT_SIGBUS, which has severe | |
| 2548 | − * consequences for the userspace process, so it must be avoided if at all | |
| 2549 | − * possible. | |
| 2550 | − * | |
| 2551 | − * For empty entries inside CPU page table (pte_none() or pmd_none() is true) we | |
| 2552 | − * do set MIGRATE_PFN_MIGRATE flag inside the corresponding source array thus | |
| 2553 | − * allowing the caller to allocate device memory for those unbacked virtual | |
| 2554 | − * addresses. For this the caller simply has to allocate device memory and | |
| 2555 | − * properly set the destination entry like for regular migration. Note that | |
| 2556 | − * this can still fail, and thus inside the device driver you must check if the | |
| 2557 | − * migration was successful for those entries after calling migrate_vma_pages(), | |
| 2558 | − * just like for regular migration. | |
| 2559 | − * | |
| 2560 | − * After that, the callers must call migrate_vma_pages() to go over each entry | |
| 2561 | − * in the src array that has the MIGRATE_PFN_VALID and MIGRATE_PFN_MIGRATE flag | |
| 2562 | − * set. If the corresponding entry in dst array has MIGRATE_PFN_VALID flag set, | |
| 2563 | − * then migrate_vma_pages() to migrate struct page information from the source | |
| 2564 | − * struct page to the destination struct page. If it fails to migrate the | |
| 2565 | − * struct page information, then it clears the MIGRATE_PFN_MIGRATE flag in the | |
| 2566 | − * src array. | |
| 2567 | − * | |
| 2568 | − * At this point all successfully migrated pages have an entry in the src | |
| 2569 | − * array with MIGRATE_PFN_VALID and MIGRATE_PFN_MIGRATE flag set and the dst | |
| 2570 | − * array entry with MIGRATE_PFN_VALID flag set. | |
| 2571 | − * | |
| 2572 | − * Once migrate_vma_pages() returns the caller may inspect which pages were | |
| 2573 | − * successfully migrated, and which were not. Successfully migrated pages will | |
| 2574 | − * have the MIGRATE_PFN_MIGRATE flag set for their src array entry. | |
| 2575 | − * | |
| 2576 | − * It is safe to update device page table after migrate_vma_pages() because | |
| 2577 | − * both destination and source page are still locked, and the mmap_lock is held | |
| 2578 | − * in read mode (hence no one can unmap the range being migrated). | |
| 2579 | − * | |
| 2580 | − * Once the caller is done cleaning up things and updating its page table (if it | |
| 2581 | − * chose to do so, this is not an obligation) it finally calls | |
| 2582 | − * migrate_vma_finalize() to update the CPU page table to point to new pages | |
| 2583 | − * for successfully migrated pages or otherwise restore the CPU page table to | |
| 2584 | − * point to the original source pages. | |
| 2585 | − */ | |
| 2586 | −int migrate_vma_setup(struct migrate_vma *args) | |
| 2587 | −{ | |
| 2588 | − long nr_pages = (args->end - args->start) >> PAGE_SHIFT; | |
| 2589 | − | |
| 2590 | − args->start &= PAGE_MASK; | |
| 2591 | − args->end &= PAGE_MASK; | |
| 2592 | − if (!args->vma || is_vm_hugetlb_page(args->vma) || | |
| 2593 | − (args->vma->vm_flags & VM_SPECIAL) || vma_is_dax(args->vma)) | |
| 2594 | − return -EINVAL; | |
| 2595 | − if (nr_pages <= 0) | |
| 2596 | − return -EINVAL; | |
| 2597 | − if (args->start < args->vma->vm_start || | |
| 2598 | − args->start >= args->vma->vm_end) | |
| 2599 | − return -EINVAL; | |
| 2600 | − if (args->end <= args->vma->vm_start || args->end > args->vma->vm_end) | |
| 2601 | − return -EINVAL; | |
| 2602 | − if (!args->src || !args->dst) | |
| 2603 | − return -EINVAL; | |
| 2604 | − | |
| 2605 | − memset(args->src, 0, sizeof(*args->src) * nr_pages); | |
| 2606 | − args->cpages = 0; | |
| 2607 | − args->npages = 0; | |
| 2608 | − | |
| 2609 | − migrate_vma_collect(args); | |
| 2610 | − | |
| 2611 | − if (args->cpages) | |
| 2612 | − migrate_vma_unmap(args); | |
| 2613 | − | |
| 2614 | − /* | |
| 2615 | − * At this point pages are locked and unmapped, and thus they have | |
| 2616 | − * stable content and can safely be copied to destination memory that | |
| 2617 | − * is allocated by the drivers. | |
| 2618 | − */ | |
| 2619 | − return 0; | |
| 2620 | − | |
| 2621 | −} | |
| 2622 | −EXPORT_SYMBOL(migrate_vma_setup); | |
| 2623 | − | |
| 2624 | −/* | |
| 2625 | − * This code closely matches the code in: | |
| 2626 | − * __handle_mm_fault() | |
| 2627 | − * handle_pte_fault() | |
| 2628 | − * do_anonymous_page() | |
| 2629 | − * to map in an anonymous zero page but the struct page will be a ZONE_DEVICE | |
| 2630 | − * private page. | |
| 2631 | − */ | |
| 2632 | −static void migrate_vma_insert_page(struct migrate_vma *migrate, | |
| 2633 | − unsigned long addr, | |
| 2634 | − struct page *page, | |
| 2635 | − unsigned long *src) | |
| 2636 | −{ | |
| 2637 | − struct vm_area_struct *vma = migrate->vma; | |
| 2638 | − struct mm_struct *mm = vma->vm_mm; | |
| 2639 | − bool flush = false; | |
| 2640 | − spinlock_t *ptl; | |
| 2641 | − pte_t entry; | |
| 2642 | − pgd_t *pgdp; | |
| 2643 | − p4d_t *p4dp; | |
| 2644 | − pud_t *pudp; | |
| 2645 | − pmd_t *pmdp; | |
| 2646 | − pte_t *ptep; | |
| 2647 | − | |
| 2648 | − /* Only allow populating anonymous memory */ | |
| 2649 | − if (!vma_is_anonymous(vma)) | |
| 2650 | − goto abort; | |
| 2651 | − | |
| 2652 | − pgdp = pgd_offset(mm, addr); | |
| 2653 | − p4dp = p4d_alloc(mm, pgdp, addr); | |
| 2654 | − if (!p4dp) | |
| 2655 | − goto abort; | |
| 2656 | − pudp = pud_alloc(mm, p4dp, addr); | |
| 2657 | − if (!pudp) | |
| 2658 | − goto abort; | |
| 2659 | − pmdp = pmd_alloc(mm, pudp, addr); | |
| 2660 | − if (!pmdp) | |
| 2661 | − goto abort; | |
| 2662 | − | |
| 2663 | − if (pmd_trans_huge(*pmdp) || pmd_devmap(*pmdp)) | |
| 2664 | − goto abort; | |
| 2665 | − | |
| 2666 | − /* | |
| 2667 | − * Use pte_alloc() instead of pte_alloc_map(). We can't run | |
| 2668 | − * pte_offset_map() on pmds where a huge pmd might be created | |
| 2669 | − * from a different thread. | |
| 2670 | − * | |
| 2671 | − * pte_alloc_map() is safe to use under mmap_write_lock(mm) or when | |
| 2672 | − * parallel threads are excluded by other means. | |
| 2673 | − * | |
| 2674 | − * Here we only have mmap_read_lock(mm). | |
| 2675 | − */ | |
| 2676 | − if (pte_alloc(mm, pmdp)) | |
| 2677 | − goto abort; | |
| 2678 | − | |
| 2679 | − /* See the comment in pte_alloc_one_map() */ | |
| 2680 | − if (unlikely(pmd_trans_unstable(pmdp))) | |
| 2681 | − goto abort; | |
| 2682 | − | |
| 2683 | − if (unlikely(anon_vma_prepare(vma))) | |
| 2684 | − goto abort; | |
| 2685 | − if (mem_cgroup_charge(page_folio(page), vma->vm_mm, GFP_KERNEL)) | |
| 2686 | − goto abort; | |
| 2687 | − | |
| 2688 | − /* | |
| 2689 | − * The memory barrier inside __SetPageUptodate makes sure that | |
| 2690 | − * preceding stores to the page contents become visible before | |
| 2691 | − * the set_pte_at() write. | |
| 2692 | − */ | |
| 2693 | − __SetPageUptodate(page); | |
| 2694 | − | |
| 2695 | − if (is_zone_device_page(page)) { | |
| 2696 | − if (is_device_private_page(page)) { | |
| 2697 | − swp_entry_t swp_entry; | |
| 2698 | − | |
| 2699 | − if (vma->vm_flags & VM_WRITE) | |
| 2700 | − swp_entry = make_writable_device_private_entry( | |
| 2701 | − page_to_pfn(page)); | |
| 2702 | − else | |
| 2703 | − swp_entry = make_readable_device_private_entry( | |
| 2704 | − page_to_pfn(page)); | |
| 2705 | − entry = swp_entry_to_pte(swp_entry); | |
| 2706 | − } else { | |
| 2707 | − /* | |
| 2708 | − * For now we only support migrating to un-addressable | |
| 2709 | − * device memory. | |
| 2710 | − */ | |
| 2711 | − pr_warn_once("Unsupported ZONE_DEVICE page type.\n"); | |
| 2712 | − goto abort; | |
| 2713 | − } | |
| 2714 | − } else { | |
| 2715 | − entry = mk_pte(page, vma->vm_page_prot); | |
| 2716 | − if (vma->vm_flags & VM_WRITE) | |
| 2717 | − entry = pte_mkwrite(pte_mkdirty(entry)); | |
| 2718 | − } | |
| 2719 | − | |
| 2720 | − ptep = pte_offset_map_lock(mm, pmdp, addr, &ptl); | |
| 2721 | − | |
| 2722 | − if (check_stable_address_space(mm)) | |
| 2723 | − goto unlock_abort; | |
| 2724 | − | |
| 2725 | − if (pte_present(*ptep)) { | |
| 2726 | − unsigned long pfn = pte_pfn(*ptep); | |
| 2727 | − | |
| 2728 | − if (!is_zero_pfn(pfn)) | |
| 2729 | − goto unlock_abort; | |
| 2730 | − flush = true; | |
| 2731 | − } else if (!pte_none(*ptep)) | |
| 2732 | − goto unlock_abort; | |
| 2733 | − | |
| 2734 | − /* | |
| 2735 | − * Check for userfaultfd but do not deliver the fault. Instead, | |
| 2736 | − * just back off. | |
| 2737 | − */ | |
| 2738 | − if (userfaultfd_missing(vma)) | |
| 2739 | − goto unlock_abort; | |
| 2740 | − | |
| 2741 | − inc_mm_counter(mm, MM_ANONPAGES); | |
| 2742 | − page_add_new_anon_rmap(page, vma, addr, false); | |
| 2743 | − if (!is_zone_device_page(page)) | |
| 2744 | − lru_cache_add_inactive_or_unevictable(page, vma); | |
| 2745 | − get_page(page); | |
| 2746 | − | |
| 2747 | − if (flush) { | |
| 2748 | − flush_cache_page(vma, addr, pte_pfn(*ptep)); | |
| 2749 | − ptep_clear_flush_notify(vma, addr, ptep); | |
| 2750 | − set_pte_at_notify(mm, addr, ptep, entry); | |
| 2751 | − update_mmu_cache(vma, addr, ptep); | |
| 2752 | − } else { | |
| 2753 | − /* No need to invalidate - it was non-present before */ | |
| 2754 | − set_pte_at(mm, addr, ptep, entry); | |
| 2755 | − update_mmu_cache(vma, addr, ptep); | |
| 2756 | − } | |
| 2757 | − | |
| 2758 | − pte_unmap_unlock(ptep, ptl); | |
| 2759 | − *src = MIGRATE_PFN_MIGRATE; | |
| 2760 | − return; | |
| 2761 | − | |
| 2762 | −unlock_abort: | |
| 2763 | − pte_unmap_unlock(ptep, ptl); | |
| 2764 | −abort: | |
| 2765 | − *src &= ~MIGRATE_PFN_MIGRATE; | |
| 2766 | −} | |
| 2767 | − | |
| 2768 | −/** | |
| 2769 | − * migrate_vma_pages() - migrate meta-data from src page to dst page | |
| 2770 | − * @migrate: migrate struct containing all migration information | |
| 2771 | − * | |
| 2772 | − * This migrates struct page meta-data from source struct page to destination | |
| 2773 | − * struct page. This effectively finishes the migration from source page to the | |
| 2774 | − * destination page. | |
| 2775 | − */ | |
| 2776 | −void migrate_vma_pages(struct migrate_vma *migrate) | |
| 2777 | −{ | |
| 2778 | − const unsigned long npages = migrate->npages; | |
| 2779 | − const unsigned long start = migrate->start; | |
| 2780 | − struct mmu_notifier_range range; | |
| 2781 | − unsigned long addr, i; | |
| 2782 | − bool notified = false; | |
| 2783 | − | |
| 2784 | − for (i = 0, addr = start; i < npages; addr += PAGE_SIZE, i++) { | |
| 2785 | − struct page *newpage = migrate_pfn_to_page(migrate->dst[i]); | |
| 2786 | − struct page *page = migrate_pfn_to_page(migrate->src[i]); | |
| 2787 | − struct address_space *mapping; | |
| 2788 | − int r; | |
| 2789 | − | |
| 2790 | − if (!newpage) { | |
| 2791 | − migrate->src[i] &= ~MIGRATE_PFN_MIGRATE; | |
| 2792 | − continue; | |
| 2793 | − } | |
| 2794 | − | |
| 2795 | − if (!page) { | |
| 2796 | − if (!(migrate->src[i] & MIGRATE_PFN_MIGRATE)) | |
| 2797 | − continue; | |
| 2798 | − if (!notified) { | |
| 2799 | − notified = true; | |
| 2800 | − | |
| 2801 | − mmu_notifier_range_init_owner(&range, | |
| 2802 | − MMU_NOTIFY_MIGRATE, 0, migrate->vma, | |
| 2803 | − migrate->vma->vm_mm, addr, migrate->end, | |
| 2804 | − migrate->pgmap_owner); | |
| 2805 | − mmu_notifier_invalidate_range_start(&range); | |
| 2806 | − } | |
| 2807 | − migrate_vma_insert_page(migrate, addr, newpage, | |
| 2808 | − &migrate->src[i]); | |
| 2809 | − continue; | |
| 2810 | − } | |
| 2811 | − | |
| 2812 | − mapping = page_mapping(page); | |
| 2813 | − | |
| 2814 | − if (is_zone_device_page(newpage)) { | |
| 2815 | − if (is_device_private_page(newpage)) { | |
| 2816 | − /* | |
| 2817 | − * For now only support private anonymous when | |
| 2818 | − * migrating to un-addressable device memory. | |
| 2819 | − */ | |
| 2820 | − if (mapping) { | |
| 2821 | − migrate->src[i] &= ~MIGRATE_PFN_MIGRATE; | |
| 2822 | − continue; | |
| 2823 | − } | |
| 2824 | − } else { | |
| 2825 | − /* | |
| 2826 | − * Other types of ZONE_DEVICE page are not | |
| 2827 | − * supported. | |
| 2828 | − */ | |
| 2829 | − migrate->src[i] &= ~MIGRATE_PFN_MIGRATE; | |
| 2830 | − continue; | |
| 2831 | − } | |
| 2832 | − } | |
| 2833 | − | |
| 2834 | − r = migrate_page(mapping, newpage, page, MIGRATE_SYNC_NO_COPY); | |
| 2835 | − if (r != MIGRATEPAGE_SUCCESS) | |
| 2836 | − migrate->src[i] &= ~MIGRATE_PFN_MIGRATE; | |
| 2837 | − } | |
| 2838 | − | |
| 2839 | − /* | |
| 2840 | − * No need to double call mmu_notifier->invalidate_range() callback as | |
| 2841 | − * the above ptep_clear_flush_notify() inside migrate_vma_insert_page() | |
| 2842 | − * did already call it. | |
| 2843 | − */ | |
| 2844 | − if (notified) | |
| 2845 | − mmu_notifier_invalidate_range_only_end(&range); | |
| 2846 | −} | |
| 2847 | −EXPORT_SYMBOL(migrate_vma_pages); | |
| 2848 | − | |
| 2849 | −/** | |
| 2850 | − * migrate_vma_finalize() - restore CPU page table entry | |
| 2851 | − * @migrate: migrate struct containing all migration information | |
| 2852 | − * | |
| 2853 | − * This replaces the special migration pte entry with either a mapping to the | |
| 2854 | − * new page if migration was successful for that page, or to the original page | |
| 2855 | − * otherwise. | |
| 2856 | − * | |
| 2857 | − * This also unlocks the pages and puts them back on the lru, or drops the extra | |
| 2858 | − * refcount, for device pages. | |
| 2859 | − */ | |
| 2860 | −void migrate_vma_finalize(struct migrate_vma *migrate) | |
| 2861 | −{ | |
| 2862 | − const unsigned long npages = migrate->npages; | |
| 2863 | − unsigned long i; | |
| 2864 | − | |
| 2865 | − for (i = 0; i < npages; i++) { | |
| 2866 | − struct page *newpage = migrate_pfn_to_page(migrate->dst[i]); | |
| 2867 | − struct page *page = migrate_pfn_to_page(migrate->src[i]); | |
| 2868 | − | |
| 2869 | − if (!page) { | |
| 2870 | − if (newpage) { | |
| 2871 | − unlock_page(newpage); | |
| 2872 | − put_page(newpage); | |
| 2873 | − } | |
| 2874 | − continue; | |
| 2875 | − } | |
| 2876 | − | |
| 2877 | − if (!(migrate->src[i] & MIGRATE_PFN_MIGRATE) || !newpage) { | |
| 2878 | − if (newpage) { | |
| 2879 | − unlock_page(newpage); | |
| 2880 | − put_page(newpage); | |
| 2881 | − } | |
| 2882 | − newpage = page; | |
| 2883 | − } | |
| 2884 | − | |
| 2885 | − remove_migration_ptes(page, newpage, false); | |
| 2886 | − unlock_page(page); | |
| 2887 | − | |
| 2888 | − if (is_zone_device_page(page)) | |
| 2889 | − put_page(page); | |
| 2890 | − else | |
| 2891 | − putback_lru_page(page); | |
| 2892 | − | |
| 2893 | − if (newpage != page) { | |
| 2894 | − unlock_page(newpage); | |
| 2895 | − if (is_zone_device_page(newpage)) | |
| 2896 | − put_page(newpage); | |
| 2897 | − else | |
| 2898 | − putback_lru_page(newpage); | |
| 2899 | − } | |
| 2900 | − } | |
| 2901 | −} | |
| 2902 | −EXPORT_SYMBOL(migrate_vma_finalize); | |
| 2903 | −#endif /* CONFIG_DEVICE_PRIVATE */ | |
| 2904 | − | |
| 2905 | 2147 | /* |
| 2906 | 2148 | * node_demotion[] example: |
| 2907 | 2149 | * |
| @@ -0,0 +1,773 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0 | |
| 2 | +/* | |
| 3 | + * Device Memory Migration functionality. | |
| 4 | + * | |
| 5 | + * Originally written by Jérôme Glisse. | |
| 6 | + */ | |
| 7 | +#include <linux/export.h> | |
| 8 | +#include <linux/memremap.h> | |
| 9 | +#include <linux/migrate.h> | |
| 10 | +#include <linux/mm_inline.h> | |
| 11 | +#include <linux/mmu_notifier.h> | |
| 12 | +#include <linux/oom.h> | |
| 13 | +#include <linux/pagewalk.h> | |
| 14 | +#include <linux/rmap.h> | |
| 15 | +#include <linux/swapops.h> | |
| 16 | +#include <asm/tlbflush.h> | |
| 17 | +#include "internal.h" | |
| 18 | + | |
| 19 | +static int migrate_vma_collect_skip(unsigned long start, | |
| 20 | + unsigned long end, | |
| 21 | + struct mm_walk *walk) | |
| 22 | +{ | |
| 23 | + struct migrate_vma *migrate = walk->private; | |
| 24 | + unsigned long addr; | |
| 25 | + | |
| 26 | + for (addr = start; addr < end; addr += PAGE_SIZE) { | |
| 27 | + migrate->dst[migrate->npages] = 0; | |
| 28 | + migrate->src[migrate->npages++] = 0; | |
| 29 | + } | |
| 30 | + | |
| 31 | + return 0; | |
| 32 | +} | |
| 33 | + | |
| 34 | +static int migrate_vma_collect_hole(unsigned long start, | |
| 35 | + unsigned long end, | |
| 36 | + __always_unused int depth, | |
| 37 | + struct mm_walk *walk) | |
| 38 | +{ | |
| 39 | + struct migrate_vma *migrate = walk->private; | |
| 40 | + unsigned long addr; | |
| 41 | + | |
| 42 | + /* Only allow populating anonymous memory. */ | |
| 43 | + if (!vma_is_anonymous(walk->vma)) | |
| 44 | + return migrate_vma_collect_skip(start, end, walk); | |
| 45 | + | |
| 46 | + for (addr = start; addr < end; addr += PAGE_SIZE) { | |
| 47 | + migrate->src[migrate->npages] = MIGRATE_PFN_MIGRATE; | |
| 48 | + migrate->dst[migrate->npages] = 0; | |
| 49 | + migrate->npages++; | |
| 50 | + migrate->cpages++; | |
| 51 | + } | |
| 52 | + | |
| 53 | + return 0; | |
| 54 | +} | |
| 55 | + | |
| 56 | +static int migrate_vma_collect_pmd(pmd_t *pmdp, | |
| 57 | + unsigned long start, | |
| 58 | + unsigned long end, | |
| 59 | + struct mm_walk *walk) | |
| 60 | +{ | |
| 61 | + struct migrate_vma *migrate = walk->private; | |
| 62 | + struct vm_area_struct *vma = walk->vma; | |
| 63 | + struct mm_struct *mm = vma->vm_mm; | |
| 64 | + unsigned long addr = start, unmapped = 0; | |
| 65 | + spinlock_t *ptl; | |
| 66 | + pte_t *ptep; | |
| 67 | + | |
| 68 | +again: | |
| 69 | + if (pmd_none(*pmdp)) | |
| 70 | + return migrate_vma_collect_hole(start, end, -1, walk); | |
| 71 | + | |
| 72 | + if (pmd_trans_huge(*pmdp)) { | |
| 73 | + struct page *page; | |
| 74 | + | |
| 75 | + ptl = pmd_lock(mm, pmdp); | |
| 76 | + if (unlikely(!pmd_trans_huge(*pmdp))) { | |
| 77 | + spin_unlock(ptl); | |
| 78 | + goto again; | |
| 79 | + } | |
| 80 | + | |
| 81 | + page = pmd_page(*pmdp); | |
| 82 | + if (is_huge_zero_page(page)) { | |
| 83 | + spin_unlock(ptl); | |
| 84 | + split_huge_pmd(vma, pmdp, addr); | |
| 85 | + if (pmd_trans_unstable(pmdp)) | |
| 86 | + return migrate_vma_collect_skip(start, end, | |
| 87 | + walk); | |
| 88 | + } else { | |
| 89 | + int ret; | |
| 90 | + | |
| 91 | + get_page(page); | |
| 92 | + spin_unlock(ptl); | |
| 93 | + if (unlikely(!trylock_page(page))) | |
| 94 | + return migrate_vma_collect_skip(start, end, | |
| 95 | + walk); | |
| 96 | + ret = split_huge_page(page); | |
| 97 | + unlock_page(page); | |
| 98 | + put_page(page); | |
| 99 | + if (ret) | |
| 100 | + return migrate_vma_collect_skip(start, end, | |
| 101 | + walk); | |
| 102 | + if (pmd_none(*pmdp)) | |
| 103 | + return migrate_vma_collect_hole(start, end, -1, | |
| 104 | + walk); | |
| 105 | + } | |
| 106 | + } | |
| 107 | + | |
| 108 | + if (unlikely(pmd_bad(*pmdp))) | |
| 109 | + return migrate_vma_collect_skip(start, end, walk); | |
| 110 | + | |
| 111 | + ptep = pte_offset_map_lock(mm, pmdp, addr, &ptl); | |
| 112 | + arch_enter_lazy_mmu_mode(); | |
| 113 | + | |
| 114 | + for (; addr < end; addr += PAGE_SIZE, ptep++) { | |
| 115 | + unsigned long mpfn = 0, pfn; | |
| 116 | + struct page *page; | |
| 117 | + swp_entry_t entry; | |
| 118 | + pte_t pte; | |
| 119 | + | |
| 120 | + pte = *ptep; | |
| 121 | + | |
| 122 | + if (pte_none(pte)) { | |
| 123 | + if (vma_is_anonymous(vma)) { | |
| 124 | + mpfn = MIGRATE_PFN_MIGRATE; | |
| 125 | + migrate->cpages++; | |
| 126 | + } | |
| 127 | + goto next; | |
| 128 | + } | |
| 129 | + | |
| 130 | + if (!pte_present(pte)) { | |
| 131 | + /* | |
| 132 | + * Only care about unaddressable device page special | |
| 133 | + * page table entry. Other special swap entries are not | |
| 134 | + * migratable, and we ignore regular swapped page. | |
| 135 | + */ | |
| 136 | + entry = pte_to_swp_entry(pte); | |
| 137 | + if (!is_device_private_entry(entry)) | |
| 138 | + goto next; | |
| 139 | + | |
| 140 | + page = pfn_swap_entry_to_page(entry); | |
| 141 | + if (!(migrate->flags & | |
| 142 | + MIGRATE_VMA_SELECT_DEVICE_PRIVATE) || | |
| 143 | + page->pgmap->owner != migrate->pgmap_owner) | |
| 144 | + goto next; | |
| 145 | + | |
| 146 | + mpfn = migrate_pfn(page_to_pfn(page)) | | |
| 147 | + MIGRATE_PFN_MIGRATE; | |
| 148 | + if (is_writable_device_private_entry(entry)) | |
| 149 | + mpfn |= MIGRATE_PFN_WRITE; | |
| 150 | + } else { | |
| 151 | + if (!(migrate->flags & MIGRATE_VMA_SELECT_SYSTEM)) | |
| 152 | + goto next; | |
| 153 | + pfn = pte_pfn(pte); | |
| 154 | + if (is_zero_pfn(pfn)) { | |
| 155 | + mpfn = MIGRATE_PFN_MIGRATE; | |
| 156 | + migrate->cpages++; | |
| 157 | + goto next; | |
| 158 | + } | |
| 159 | + page = vm_normal_page(migrate->vma, addr, pte); | |
| 160 | + mpfn = migrate_pfn(pfn) | MIGRATE_PFN_MIGRATE; | |
| 161 | + mpfn |= pte_write(pte) ? MIGRATE_PFN_WRITE : 0; | |
| 162 | + } | |
| 163 | + | |
| 164 | + /* FIXME support THP */ | |
| 165 | + if (!page || !page->mapping || PageTransCompound(page)) { | |
| 166 | + mpfn = 0; | |
| 167 | + goto next; | |
| 168 | + } | |
| 169 | + | |
| 170 | + /* | |
| 171 | + * By getting a reference on the page we pin it and that blocks | |
| 172 | + * any kind of migration. Side effect is that it "freezes" the | |
| 173 | + * pte. | |
| 174 | + * | |
| 175 | + * We drop this reference after isolating the page from the lru | |
| 176 | + * for non device page (device page are not on the lru and thus | |
| 177 | + * can't be dropped from it). | |
| 178 | + */ | |
| 179 | + get_page(page); | |
| 180 | + | |
| 181 | + /* | |
| 182 | + * Optimize for the common case where page is only mapped once | |
| 183 | + * in one process. If we can lock the page, then we can safely | |
| 184 | + * set up a special migration page table entry now. | |
| 185 | + */ | |
| 186 | + if (trylock_page(page)) { | |
| 187 | + pte_t swp_pte; | |
| 188 | + | |
| 189 | + migrate->cpages++; | |
| 190 | + ptep_get_and_clear(mm, addr, ptep); | |
| 191 | + | |
| 192 | + /* Setup special migration page table entry */ | |
| 193 | + if (mpfn & MIGRATE_PFN_WRITE) | |
| 194 | + entry = make_writable_migration_entry( | |
| 195 | + page_to_pfn(page)); | |
| 196 | + else | |
| 197 | + entry = make_readable_migration_entry( | |
| 198 | + page_to_pfn(page)); | |
| 199 | + swp_pte = swp_entry_to_pte(entry); | |
| 200 | + if (pte_present(pte)) { | |
| 201 | + if (pte_soft_dirty(pte)) | |
| 202 | + swp_pte = pte_swp_mksoft_dirty(swp_pte); | |
| 203 | + if (pte_uffd_wp(pte)) | |
| 204 | + swp_pte = pte_swp_mkuffd_wp(swp_pte); | |
| 205 | + } else { | |
| 206 | + if (pte_swp_soft_dirty(pte)) | |
| 207 | + swp_pte = pte_swp_mksoft_dirty(swp_pte); | |
| 208 | + if (pte_swp_uffd_wp(pte)) | |
| 209 | + swp_pte = pte_swp_mkuffd_wp(swp_pte); | |
| 210 | + } | |
| 211 | + set_pte_at(mm, addr, ptep, swp_pte); | |
| 212 | + | |
| 213 | + /* | |
| 214 | + * This is like regular unmap: we remove the rmap and | |
| 215 | + * drop page refcount. Page won't be freed, as we took | |
| 216 | + * a reference just above. | |
| 217 | + */ | |
| 218 | + page_remove_rmap(page, vma, false); | |
| 219 | + put_page(page); | |
| 220 | + | |
| 221 | + if (pte_present(pte)) | |
| 222 | + unmapped++; | |
| 223 | + } else { | |
| 224 | + put_page(page); | |
| 225 | + mpfn = 0; | |
| 226 | + } | |
| 227 | + | |
| 228 | +next: | |
| 229 | + migrate->dst[migrate->npages] = 0; | |
| 230 | + migrate->src[migrate->npages++] = mpfn; | |
| 231 | + } | |
| 232 | + arch_leave_lazy_mmu_mode(); | |
| 233 | + pte_unmap_unlock(ptep - 1, ptl); | |
| 234 | + | |
| 235 | + /* Only flush the TLB if we actually modified any entries */ | |
| 236 | + if (unmapped) | |
| 237 | + flush_tlb_range(walk->vma, start, end); | |
| 238 | + | |
| 239 | + return 0; | |
| 240 | +} | |
| 241 | + | |
| 242 | +static const struct mm_walk_ops migrate_vma_walk_ops = { | |
| 243 | + .pmd_entry = migrate_vma_collect_pmd, | |
| 244 | + .pte_hole = migrate_vma_collect_hole, | |
| 245 | +}; | |
| 246 | + | |
| 247 | +/* | |
| 248 | + * migrate_vma_collect() - collect pages over a range of virtual addresses | |
| 249 | + * @migrate: migrate struct containing all migration information | |
| 250 | + * | |
| 251 | + * This will walk the CPU page table. For each virtual address backed by a | |
| 252 | + * valid page, it updates the src array and takes a reference on the page, in | |
| 253 | + * order to pin the page until we lock it and unmap it. | |
| 254 | + */ | |
| 255 | +static void migrate_vma_collect(struct migrate_vma *migrate) | |
| 256 | +{ | |
| 257 | + struct mmu_notifier_range range; | |
| 258 | + | |
| 259 | + /* | |
| 260 | + * Note that the pgmap_owner is passed to the mmu notifier callback so | |
| 261 | + * that the registered device driver can skip invalidating device | |
| 262 | + * private page mappings that won't be migrated. | |
| 263 | + */ | |
| 264 | + mmu_notifier_range_init_owner(&range, MMU_NOTIFY_MIGRATE, 0, | |
| 265 | + migrate->vma, migrate->vma->vm_mm, migrate->start, migrate->end, | |
| 266 | + migrate->pgmap_owner); | |
| 267 | + mmu_notifier_invalidate_range_start(&range); | |
| 268 | + | |
| 269 | + walk_page_range(migrate->vma->vm_mm, migrate->start, migrate->end, | |
| 270 | + &migrate_vma_walk_ops, migrate); | |
| 271 | + | |
| 272 | + mmu_notifier_invalidate_range_end(&range); | |
| 273 | + migrate->end = migrate->start + (migrate->npages << PAGE_SHIFT); | |
| 274 | +} | |
| 275 | + | |
| 276 | +/* | |
| 277 | + * migrate_vma_check_page() - check if page is pinned or not | |
| 278 | + * @page: struct page to check | |
| 279 | + * | |
| 280 | + * Pinned pages cannot be migrated. This is the same test as in | |
| 281 | + * folio_migrate_mapping(), except that here we allow migration of a | |
| 282 | + * ZONE_DEVICE page. | |
| 283 | + */ | |
| 284 | +static bool migrate_vma_check_page(struct page *page) | |
| 285 | +{ | |
| 286 | + /* | |
| 287 | + * One extra ref because caller holds an extra reference, either from | |
| 288 | + * isolate_lru_page() for a regular page, or migrate_vma_collect() for | |
| 289 | + * a device page. | |
| 290 | + */ | |
| 291 | + int extra = 1; | |
| 292 | + | |
| 293 | + /* | |
| 294 | + * FIXME support THP (transparent huge page), it is bit more complex to | |
| 295 | + * check them than regular pages, because they can be mapped with a pmd | |
| 296 | + * or with a pte (split pte mapping). | |
| 297 | + */ | |
| 298 | + if (PageCompound(page)) | |
| 299 | + return false; | |
| 300 | + | |
| 301 | + /* Page from ZONE_DEVICE have one extra reference */ | |
| 302 | + if (is_zone_device_page(page)) | |
| 303 | + extra++; | |
| 304 | + | |
| 305 | + /* For file back page */ | |
| 306 | + if (page_mapping(page)) | |
| 307 | + extra += 1 + page_has_private(page); | |
| 308 | + | |
| 309 | + if ((page_count(page) - extra) > page_mapcount(page)) | |
| 310 | + return false; | |
| 311 | + | |
| 312 | + return true; | |
| 313 | +} | |
| 314 | + | |
| 315 | +/* | |
| 316 | + * migrate_vma_unmap() - replace page mapping with special migration pte entry | |
| 317 | + * @migrate: migrate struct containing all migration information | |
| 318 | + * | |
| 319 | + * Isolate pages from the LRU and replace mappings (CPU page table pte) with a | |
| 320 | + * special migration pte entry and check if it has been pinned. Pinned pages are | |
| 321 | + * restored because we cannot migrate them. | |
| 322 | + * | |
| 323 | + * This is the last step before we call the device driver callback to allocate | |
| 324 | + * destination memory and copy contents of original page over to new page. | |
| 325 | + */ | |
| 326 | +static void migrate_vma_unmap(struct migrate_vma *migrate) | |
| 327 | +{ | |
| 328 | + const unsigned long npages = migrate->npages; | |
| 329 | + unsigned long i, restore = 0; | |
| 330 | + bool allow_drain = true; | |
| 331 | + | |
| 332 | + lru_add_drain(); | |
| 333 | + | |
| 334 | + for (i = 0; i < npages; i++) { | |
| 335 | + struct page *page = migrate_pfn_to_page(migrate->src[i]); | |
| 336 | + struct folio *folio; | |
| 337 | + | |
| 338 | + if (!page) | |
| 339 | + continue; | |
| 340 | + | |
| 341 | + /* ZONE_DEVICE pages are not on LRU */ | |
| 342 | + if (!is_zone_device_page(page)) { | |
| 343 | + if (!PageLRU(page) && allow_drain) { | |
| 344 | + /* Drain CPU's pagevec */ | |
| 345 | + lru_add_drain_all(); | |
| 346 | + allow_drain = false; | |
| 347 | + } | |
| 348 | + | |
| 349 | + if (isolate_lru_page(page)) { | |
| 350 | + migrate->src[i] &= ~MIGRATE_PFN_MIGRATE; | |
| 351 | + migrate->cpages--; | |
| 352 | + restore++; | |
| 353 | + continue; | |
| 354 | + } | |
| 355 | + | |
| 356 | + /* Drop the reference we took in collect */ | |
| 357 | + put_page(page); | |
| 358 | + } | |
| 359 | + | |
| 360 | + folio = page_folio(page); | |
| 361 | + if (folio_mapped(folio)) | |
| 362 | + try_to_migrate(folio, 0); | |
| 363 | + | |
| 364 | + if (page_mapped(page) || !migrate_vma_check_page(page)) { | |
| 365 | + if (!is_zone_device_page(page)) { | |
| 366 | + get_page(page); | |
| 367 | + putback_lru_page(page); | |
| 368 | + } | |
| 369 | + | |
| 370 | + migrate->src[i] &= ~MIGRATE_PFN_MIGRATE; | |
| 371 | + migrate->cpages--; | |
| 372 | + restore++; | |
| 373 | + continue; | |
| 374 | + } | |
| 375 | + } | |
| 376 | + | |
| 377 | + for (i = 0; i < npages && restore; i++) { | |
| 378 | + struct page *page = migrate_pfn_to_page(migrate->src[i]); | |
| 379 | + struct folio *folio; | |
| 380 | + | |
| 381 | + if (!page || (migrate->src[i] & MIGRATE_PFN_MIGRATE)) | |
| 382 | + continue; | |
| 383 | + | |
| 384 | + folio = page_folio(page); | |
| 385 | + remove_migration_ptes(folio, folio, false); | |
| 386 | + | |
| 387 | + migrate->src[i] = 0; | |
| 388 | + folio_unlock(folio); | |
| 389 | + folio_put(folio); | |
| 390 | + restore--; | |
| 391 | + } | |
| 392 | +} | |
| 393 | + | |
| 394 | +/** | |
| 395 | + * migrate_vma_setup() - prepare to migrate a range of memory | |
| 396 | + * @args: contains the vma, start, and pfns arrays for the migration | |
| 397 | + * | |
| 398 | + * Returns: negative errno on failures, 0 when 0 or more pages were migrated | |
| 399 | + * without an error. | |
| 400 | + * | |
| 401 | + * Prepare to migrate a range of memory virtual address range by collecting all | |
| 402 | + * the pages backing each virtual address in the range, saving them inside the | |
| 403 | + * src array. Then lock those pages and unmap them. Once the pages are locked | |
| 404 | + * and unmapped, check whether each page is pinned or not. Pages that aren't | |
| 405 | + * pinned have the MIGRATE_PFN_MIGRATE flag set (by this function) in the | |
| 406 | + * corresponding src array entry. Then restores any pages that are pinned, by | |
| 407 | + * remapping and unlocking those pages. | |
| 408 | + * | |
| 409 | + * The caller should then allocate destination memory and copy source memory to | |
| 410 | + * it for all those entries (ie with MIGRATE_PFN_VALID and MIGRATE_PFN_MIGRATE | |
| 411 | + * flag set). Once these are allocated and copied, the caller must update each | |
| 412 | + * corresponding entry in the dst array with the pfn value of the destination | |
| 413 | + * page and with MIGRATE_PFN_VALID. Destination pages must be locked via | |
| 414 | + * lock_page(). | |
| 415 | + * | |
| 416 | + * Note that the caller does not have to migrate all the pages that are marked | |
| 417 | + * with MIGRATE_PFN_MIGRATE flag in src array unless this is a migration from | |
| 418 | + * device memory to system memory. If the caller cannot migrate a device page | |
| 419 | + * back to system memory, then it must return VM_FAULT_SIGBUS, which has severe | |
| 420 | + * consequences for the userspace process, so it must be avoided if at all | |
| 421 | + * possible. | |
| 422 | + * | |
| 423 | + * For empty entries inside CPU page table (pte_none() or pmd_none() is true) we | |
| 424 | + * do set MIGRATE_PFN_MIGRATE flag inside the corresponding source array thus | |
| 425 | + * allowing the caller to allocate device memory for those unbacked virtual | |
| 426 | + * addresses. For this the caller simply has to allocate device memory and | |
| 427 | + * properly set the destination entry like for regular migration. Note that | |
| 428 | + * this can still fail, and thus inside the device driver you must check if the | |
| 429 | + * migration was successful for those entries after calling migrate_vma_pages(), | |
| 430 | + * just like for regular migration. | |
| 431 | + * | |
| 432 | + * After that, the callers must call migrate_vma_pages() to go over each entry | |
| 433 | + * in the src array that has the MIGRATE_PFN_VALID and MIGRATE_PFN_MIGRATE flag | |
| 434 | + * set. If the corresponding entry in dst array has MIGRATE_PFN_VALID flag set, | |
| 435 | + * then migrate_vma_pages() to migrate struct page information from the source | |
| 436 | + * struct page to the destination struct page. If it fails to migrate the | |
| 437 | + * struct page information, then it clears the MIGRATE_PFN_MIGRATE flag in the | |
| 438 | + * src array. | |
| 439 | + * | |
| 440 | + * At this point all successfully migrated pages have an entry in the src | |
| 441 | + * array with MIGRATE_PFN_VALID and MIGRATE_PFN_MIGRATE flag set and the dst | |
| 442 | + * array entry with MIGRATE_PFN_VALID flag set. | |
| 443 | + * | |
| 444 | + * Once migrate_vma_pages() returns the caller may inspect which pages were | |
| 445 | + * successfully migrated, and which were not. Successfully migrated pages will | |
| 446 | + * have the MIGRATE_PFN_MIGRATE flag set for their src array entry. | |
| 447 | + * | |
| 448 | + * It is safe to update device page table after migrate_vma_pages() because | |
| 449 | + * both destination and source page are still locked, and the mmap_lock is held | |
| 450 | + * in read mode (hence no one can unmap the range being migrated). | |
| 451 | + * | |
| 452 | + * Once the caller is done cleaning up things and updating its page table (if it | |
| 453 | + * chose to do so, this is not an obligation) it finally calls | |
| 454 | + * migrate_vma_finalize() to update the CPU page table to point to new pages | |
| 455 | + * for successfully migrated pages or otherwise restore the CPU page table to | |
| 456 | + * point to the original source pages. | |
| 457 | + */ | |
| 458 | +int migrate_vma_setup(struct migrate_vma *args) | |
| 459 | +{ | |
| 460 | + long nr_pages = (args->end - args->start) >> PAGE_SHIFT; | |
| 461 | + | |
| 462 | + args->start &= PAGE_MASK; | |
| 463 | + args->end &= PAGE_MASK; | |
| 464 | + if (!args->vma || is_vm_hugetlb_page(args->vma) || | |
| 465 | + (args->vma->vm_flags & VM_SPECIAL) || vma_is_dax(args->vma)) | |
| 466 | + return -EINVAL; | |
| 467 | + if (nr_pages <= 0) | |
| 468 | + return -EINVAL; | |
| 469 | + if (args->start < args->vma->vm_start || | |
| 470 | + args->start >= args->vma->vm_end) | |
| 471 | + return -EINVAL; | |
| 472 | + if (args->end <= args->vma->vm_start || args->end > args->vma->vm_end) | |
| 473 | + return -EINVAL; | |
| 474 | + if (!args->src || !args->dst) | |
| 475 | + return -EINVAL; | |
| 476 | + | |
| 477 | + memset(args->src, 0, sizeof(*args->src) * nr_pages); | |
| 478 | + args->cpages = 0; | |
| 479 | + args->npages = 0; | |
| 480 | + | |
| 481 | + migrate_vma_collect(args); | |
| 482 | + | |
| 483 | + if (args->cpages) | |
| 484 | + migrate_vma_unmap(args); | |
| 485 | + | |
| 486 | + /* | |
| 487 | + * At this point pages are locked and unmapped, and thus they have | |
| 488 | + * stable content and can safely be copied to destination memory that | |
| 489 | + * is allocated by the drivers. | |
| 490 | + */ | |
| 491 | + return 0; | |
| 492 | + | |
| 493 | +} | |
| 494 | +EXPORT_SYMBOL(migrate_vma_setup); | |
| 495 | + | |
| 496 | +/* | |
| 497 | + * This code closely matches the code in: | |
| 498 | + * __handle_mm_fault() | |
| 499 | + * handle_pte_fault() | |
| 500 | + * do_anonymous_page() | |
| 501 | + * to map in an anonymous zero page but the struct page will be a ZONE_DEVICE | |
| 502 | + * private page. | |
| 503 | + */ | |
| 504 | +static void migrate_vma_insert_page(struct migrate_vma *migrate, | |
| 505 | + unsigned long addr, | |
| 506 | + struct page *page, | |
| 507 | + unsigned long *src) | |
| 508 | +{ | |
| 509 | + struct vm_area_struct *vma = migrate->vma; | |
| 510 | + struct mm_struct *mm = vma->vm_mm; | |
| 511 | + bool flush = false; | |
| 512 | + spinlock_t *ptl; | |
| 513 | + pte_t entry; | |
| 514 | + pgd_t *pgdp; | |
| 515 | + p4d_t *p4dp; | |
| 516 | + pud_t *pudp; | |
| 517 | + pmd_t *pmdp; | |
| 518 | + pte_t *ptep; | |
| 519 | + | |
| 520 | + /* Only allow populating anonymous memory */ | |
| 521 | + if (!vma_is_anonymous(vma)) | |
| 522 | + goto abort; | |
| 523 | + | |
| 524 | + pgdp = pgd_offset(mm, addr); | |
| 525 | + p4dp = p4d_alloc(mm, pgdp, addr); | |
| 526 | + if (!p4dp) | |
| 527 | + goto abort; | |
| 528 | + pudp = pud_alloc(mm, p4dp, addr); | |
| 529 | + if (!pudp) | |
| 530 | + goto abort; | |
| 531 | + pmdp = pmd_alloc(mm, pudp, addr); | |
| 532 | + if (!pmdp) | |
| 533 | + goto abort; | |
| 534 | + | |
| 535 | + if (pmd_trans_huge(*pmdp) || pmd_devmap(*pmdp)) | |
| 536 | + goto abort; | |
| 537 | + | |
| 538 | + /* | |
| 539 | + * Use pte_alloc() instead of pte_alloc_map(). We can't run | |
| 540 | + * pte_offset_map() on pmds where a huge pmd might be created | |
| 541 | + * from a different thread. | |
| 542 | + * | |
| 543 | + * pte_alloc_map() is safe to use under mmap_write_lock(mm) or when | |
| 544 | + * parallel threads are excluded by other means. | |
| 545 | + * | |
| 546 | + * Here we only have mmap_read_lock(mm). | |
| 547 | + */ | |
| 548 | + if (pte_alloc(mm, pmdp)) | |
| 549 | + goto abort; | |
| 550 | + | |
| 551 | + /* See the comment in pte_alloc_one_map() */ | |
| 552 | + if (unlikely(pmd_trans_unstable(pmdp))) | |
| 553 | + goto abort; | |
| 554 | + | |
| 555 | + if (unlikely(anon_vma_prepare(vma))) | |
| 556 | + goto abort; | |
| 557 | + if (mem_cgroup_charge(page_folio(page), vma->vm_mm, GFP_KERNEL)) | |
| 558 | + goto abort; | |
| 559 | + | |
| 560 | + /* | |
| 561 | + * The memory barrier inside __SetPageUptodate makes sure that | |
| 562 | + * preceding stores to the page contents become visible before | |
| 563 | + * the set_pte_at() write. | |
| 564 | + */ | |
| 565 | + __SetPageUptodate(page); | |
| 566 | + | |
| 567 | + if (is_device_private_page(page)) { | |
| 568 | + swp_entry_t swp_entry; | |
| 569 | + | |
| 570 | + if (vma->vm_flags & VM_WRITE) | |
| 571 | + swp_entry = make_writable_device_private_entry( | |
| 572 | + page_to_pfn(page)); | |
| 573 | + else | |
| 574 | + swp_entry = make_readable_device_private_entry( | |
| 575 | + page_to_pfn(page)); | |
| 576 | + entry = swp_entry_to_pte(swp_entry); | |
| 577 | + } else { | |
| 578 | + /* | |
| 579 | + * For now we only support migrating to un-addressable device | |
| 580 | + * memory. | |
| 581 | + */ | |
| 582 | + if (is_zone_device_page(page)) { | |
| 583 | + pr_warn_once("Unsupported ZONE_DEVICE page type.\n"); | |
| 584 | + goto abort; | |
| 585 | + } | |
| 586 | + entry = mk_pte(page, vma->vm_page_prot); | |
| 587 | + if (vma->vm_flags & VM_WRITE) | |
| 588 | + entry = pte_mkwrite(pte_mkdirty(entry)); | |
| 589 | + } | |
| 590 | + | |
| 591 | + ptep = pte_offset_map_lock(mm, pmdp, addr, &ptl); | |
| 592 | + | |
| 593 | + if (check_stable_address_space(mm)) | |
| 594 | + goto unlock_abort; | |
| 595 | + | |
| 596 | + if (pte_present(*ptep)) { | |
| 597 | + unsigned long pfn = pte_pfn(*ptep); | |
| 598 | + | |
| 599 | + if (!is_zero_pfn(pfn)) | |
| 600 | + goto unlock_abort; | |
| 601 | + flush = true; | |
| 602 | + } else if (!pte_none(*ptep)) | |
| 603 | + goto unlock_abort; | |
| 604 | + | |
| 605 | + /* | |
| 606 | + * Check for userfaultfd but do not deliver the fault. Instead, | |
| 607 | + * just back off. | |
| 608 | + */ | |
| 609 | + if (userfaultfd_missing(vma)) | |
| 610 | + goto unlock_abort; | |
| 611 | + | |
| 612 | + inc_mm_counter(mm, MM_ANONPAGES); | |
| 613 | + page_add_new_anon_rmap(page, vma, addr, false); | |
| 614 | + if (!is_zone_device_page(page)) | |
| 615 | + lru_cache_add_inactive_or_unevictable(page, vma); | |
| 616 | + get_page(page); | |
| 617 | + | |
| 618 | + if (flush) { | |
| 619 | + flush_cache_page(vma, addr, pte_pfn(*ptep)); | |
| 620 | + ptep_clear_flush_notify(vma, addr, ptep); | |
| 621 | + set_pte_at_notify(mm, addr, ptep, entry); | |
| 622 | + update_mmu_cache(vma, addr, ptep); | |
| 623 | + } else { | |
| 624 | + /* No need to invalidate - it was non-present before */ | |
| 625 | + set_pte_at(mm, addr, ptep, entry); | |
| 626 | + update_mmu_cache(vma, addr, ptep); | |
| 627 | + } | |
| 628 | + | |
| 629 | + pte_unmap_unlock(ptep, ptl); | |
| 630 | + *src = MIGRATE_PFN_MIGRATE; | |
| 631 | + return; | |
| 632 | + | |
| 633 | +unlock_abort: | |
| 634 | + pte_unmap_unlock(ptep, ptl); | |
| 635 | +abort: | |
| 636 | + *src &= ~MIGRATE_PFN_MIGRATE; | |
| 637 | +} | |
| 638 | + | |
| 639 | +/** | |
| 640 | + * migrate_vma_pages() - migrate meta-data from src page to dst page | |
| 641 | + * @migrate: migrate struct containing all migration information | |
| 642 | + * | |
| 643 | + * This migrates struct page meta-data from source struct page to destination | |
| 644 | + * struct page. This effectively finishes the migration from source page to the | |
| 645 | + * destination page. | |
| 646 | + */ | |
| 647 | +void migrate_vma_pages(struct migrate_vma *migrate) | |
| 648 | +{ | |
| 649 | + const unsigned long npages = migrate->npages; | |
| 650 | + const unsigned long start = migrate->start; | |
| 651 | + struct mmu_notifier_range range; | |
| 652 | + unsigned long addr, i; | |
| 653 | + bool notified = false; | |
| 654 | + | |
| 655 | + for (i = 0, addr = start; i < npages; addr += PAGE_SIZE, i++) { | |
| 656 | + struct page *newpage = migrate_pfn_to_page(migrate->dst[i]); | |
| 657 | + struct page *page = migrate_pfn_to_page(migrate->src[i]); | |
| 658 | + struct address_space *mapping; | |
| 659 | + int r; | |
| 660 | + | |
| 661 | + if (!newpage) { | |
| 662 | + migrate->src[i] &= ~MIGRATE_PFN_MIGRATE; | |
| 663 | + continue; | |
| 664 | + } | |
| 665 | + | |
| 666 | + if (!page) { | |
| 667 | + if (!(migrate->src[i] & MIGRATE_PFN_MIGRATE)) | |
| 668 | + continue; | |
| 669 | + if (!notified) { | |
| 670 | + notified = true; | |
| 671 | + | |
| 672 | + mmu_notifier_range_init_owner(&range, | |
| 673 | + MMU_NOTIFY_MIGRATE, 0, migrate->vma, | |
| 674 | + migrate->vma->vm_mm, addr, migrate->end, | |
| 675 | + migrate->pgmap_owner); | |
| 676 | + mmu_notifier_invalidate_range_start(&range); | |
| 677 | + } | |
| 678 | + migrate_vma_insert_page(migrate, addr, newpage, | |
| 679 | + &migrate->src[i]); | |
| 680 | + continue; | |
| 681 | + } | |
| 682 | + | |
| 683 | + mapping = page_mapping(page); | |
| 684 | + | |
| 685 | + if (is_device_private_page(newpage)) { | |
| 686 | + /* | |
| 687 | + * For now only support private anonymous when migrating | |
| 688 | + * to un-addressable device memory. | |
| 689 | + */ | |
| 690 | + if (mapping) { | |
| 691 | + migrate->src[i] &= ~MIGRATE_PFN_MIGRATE; | |
| 692 | + continue; | |
| 693 | + } | |
| 694 | + } else if (is_zone_device_page(newpage)) { | |
| 695 | + /* | |
| 696 | + * Other types of ZONE_DEVICE page are not supported. | |
| 697 | + */ | |
| 698 | + migrate->src[i] &= ~MIGRATE_PFN_MIGRATE; | |
| 699 | + continue; | |
| 700 | + } | |
| 701 | + | |
| 702 | + r = migrate_page(mapping, newpage, page, MIGRATE_SYNC_NO_COPY); | |
| 703 | + if (r != MIGRATEPAGE_SUCCESS) | |
| 704 | + migrate->src[i] &= ~MIGRATE_PFN_MIGRATE; | |
| 705 | + } | |
| 706 | + | |
| 707 | + /* | |
| 708 | + * No need to double call mmu_notifier->invalidate_range() callback as | |
| 709 | + * the above ptep_clear_flush_notify() inside migrate_vma_insert_page() | |
| 710 | + * did already call it. | |
| 711 | + */ | |
| 712 | + if (notified) | |
| 713 | + mmu_notifier_invalidate_range_only_end(&range); | |
| 714 | +} | |
| 715 | +EXPORT_SYMBOL(migrate_vma_pages); | |
| 716 | + | |
| 717 | +/** | |
| 718 | + * migrate_vma_finalize() - restore CPU page table entry | |
| 719 | + * @migrate: migrate struct containing all migration information | |
| 720 | + * | |
| 721 | + * This replaces the special migration pte entry with either a mapping to the | |
| 722 | + * new page if migration was successful for that page, or to the original page | |
| 723 | + * otherwise. | |
| 724 | + * | |
| 725 | + * This also unlocks the pages and puts them back on the lru, or drops the extra | |
| 726 | + * refcount, for device pages. | |
| 727 | + */ | |
| 728 | +void migrate_vma_finalize(struct migrate_vma *migrate) | |
| 729 | +{ | |
| 730 | + const unsigned long npages = migrate->npages; | |
| 731 | + unsigned long i; | |
| 732 | + | |
| 733 | + for (i = 0; i < npages; i++) { | |
| 734 | + struct folio *dst, *src; | |
| 735 | + struct page *newpage = migrate_pfn_to_page(migrate->dst[i]); | |
| 736 | + struct page *page = migrate_pfn_to_page(migrate->src[i]); | |
| 737 | + | |
| 738 | + if (!page) { | |
| 739 | + if (newpage) { | |
| 740 | + unlock_page(newpage); | |
| 741 | + put_page(newpage); | |
| 742 | + } | |
| 743 | + continue; | |
| 744 | + } | |
| 745 | + | |
| 746 | + if (!(migrate->src[i] & MIGRATE_PFN_MIGRATE) || !newpage) { | |
| 747 | + if (newpage) { | |
| 748 | + unlock_page(newpage); | |
| 749 | + put_page(newpage); | |
| 750 | + } | |
| 751 | + newpage = page; | |
| 752 | + } | |
| 753 | + | |
| 754 | + src = page_folio(page); | |
| 755 | + dst = page_folio(newpage); | |
| 756 | + remove_migration_ptes(src, dst, false); | |
| 757 | + folio_unlock(src); | |
| 758 | + | |
| 759 | + if (is_zone_device_page(page)) | |
| 760 | + put_page(page); | |
| 761 | + else | |
| 762 | + putback_lru_page(page); | |
| 763 | + | |
| 764 | + if (newpage != page) { | |
| 765 | + unlock_page(newpage); | |
| 766 | + if (is_zone_device_page(newpage)) | |
| 767 | + put_page(newpage); | |
| 768 | + else | |
| 769 | + putback_lru_page(newpage); | |
| 770 | + } | |
| 771 | + } | |
| 772 | +} | |
| 773 | +EXPORT_SYMBOL(migrate_vma_finalize); | |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/swapops.h> |
| 15 | 15 | #include <linux/pagemap.h> |
| 16 | 16 | #include <linux/pagevec.h> |
| 17 | +#include <linux/pagewalk.h> | |
| 17 | 18 | #include <linux/mempolicy.h> |
| 18 | 19 | #include <linux/syscalls.h> |
| 19 | 20 | #include <linux/sched.h> |
| @@ -27,6 +28,8 @@ · 7 unmodified lines | ||
| 27 | 28 | |
| 28 | 29 | #include "internal.h" |
| 29 | 30 | |
| 31 | +static DEFINE_PER_CPU(struct pagevec, mlock_pvec); | |
| 32 | + | |
| 30 | 33 | bool can_do_mlock(void) |
| 31 | 34 | { |
| 32 | 35 | if (rlimit(RLIMIT_MEMLOCK) != 0) |
| @@ -46,441 +49,320 @@ EXPORT_SYMBOL(can_do_mlock); · 13 unmodified lines | ||
| 46 | 49 | * be placed on the LRU "unevictable" list, rather than the [in]active lists. |
| 47 | 50 | * The unevictable list is an LRU sibling list to the [in]active lists. |
| 48 | 51 | * PageUnevictable is set to indicate the unevictable state. |
| 49 | − * | |
| 50 | − * When lazy mlocking via vmscan, it is important to ensure that the | |
| 51 | − * vma's VM_LOCKED status is not concurrently being modified, otherwise we | |
| 52 | − * may have mlocked a page that is being munlocked. So lazy mlock must take | |
| 53 | − * the mmap_lock for read, and verify that the vma really is locked | |
| 54 | − * (see mm/rmap.c). | |
| 55 | 52 | */ |
| 56 | 53 | |
| 57 | −/* | |
| 58 | − * LRU accounting for clear_page_mlock() | |
| 59 | − */ | |
| 60 | −void clear_page_mlock(struct page *page) | |
| 54 | +static struct lruvec *__mlock_page(struct page *page, struct lruvec *lruvec) | |
| 61 | 55 | { |
| 62 | − int nr_pages; | |
| 56 | + /* There is nothing more we can do while it's off LRU */ | |
| 57 | + if (!TestClearPageLRU(page)) | |
| 58 | + return lruvec; | |
| 63 | 59 | |
| 64 | − if (!TestClearPageMlocked(page)) | |
| 65 | − return; | |
| 60 | + lruvec = folio_lruvec_relock_irq(page_folio(page), lruvec); | |
| 66 | 61 | |
| 67 | − nr_pages = thp_nr_pages(page); | |
| 68 | − mod_zone_page_state(page_zone(page), NR_MLOCK, -nr_pages); | |
| 69 | − count_vm_events(UNEVICTABLE_PGCLEARED, nr_pages); | |
| 70 | − /* | |
| 71 | − * The previous TestClearPageMlocked() corresponds to the smp_mb() | |
| 72 | − * in __pagevec_lru_add_fn(). | |
| 73 | − * | |
| 74 | − * See __pagevec_lru_add_fn for more explanation. | |
| 75 | − */ | |
| 76 | − if (!isolate_lru_page(page)) { | |
| 77 | − putback_lru_page(page); | |
| 78 | − } else { | |
| 62 | + if (unlikely(page_evictable(page))) { | |
| 79 | 63 | /* |
| 80 | − * We lost the race. the page already moved to evictable list. | |
| 64 | + * This is a little surprising, but quite possible: | |
| 65 | + * PageMlocked must have got cleared already by another CPU. | |
| 66 | + * Could this page be on the Unevictable LRU? I'm not sure, | |
| 67 | + * but move it now if so. | |
| 81 | 68 | */ |
| 82 | − if (PageUnevictable(page)) | |
| 83 | − count_vm_events(UNEVICTABLE_PGSTRANDED, nr_pages); | |
| 69 | + if (PageUnevictable(page)) { | |
| 70 | + del_page_from_lru_list(page, lruvec); | |
| 71 | + ClearPageUnevictable(page); | |
| 72 | + add_page_to_lru_list(page, lruvec); | |
| 73 | + __count_vm_events(UNEVICTABLE_PGRESCUED, | |
| 74 | + thp_nr_pages(page)); | |
| 75 | + } | |
| 76 | + goto out; | |
| 84 | 77 | } |
| 78 | + | |
| 79 | + if (PageUnevictable(page)) { | |
| 80 | + if (PageMlocked(page)) | |
| 81 | + page->mlock_count++; | |
| 82 | + goto out; | |
| 83 | + } | |
| 84 | + | |
| 85 | + del_page_from_lru_list(page, lruvec); | |
| 86 | + ClearPageActive(page); | |
| 87 | + SetPageUnevictable(page); | |
| 88 | + page->mlock_count = !!PageMlocked(page); | |
| 89 | + add_page_to_lru_list(page, lruvec); | |
| 90 | + __count_vm_events(UNEVICTABLE_PGCULLED, thp_nr_pages(page)); | |
| 91 | +out: | |
| 92 | + SetPageLRU(page); | |
| 93 | + return lruvec; | |
| 85 | 94 | } |
| 86 | 95 | |
| 87 | −/* | |
| 88 | − * Mark page as mlocked if not already. | |
| 89 | − * If page on LRU, isolate and putback to move to unevictable list. | |
| 90 | − */ | |
| 91 | −void mlock_vma_page(struct page *page) | |
| 96 | +static struct lruvec *__mlock_new_page(struct page *page, struct lruvec *lruvec) | |
| 92 | 97 | { |
| 93 | − /* Serialize with page migration */ | |
| 94 | − BUG_ON(!PageLocked(page)); | |
| 98 | + VM_BUG_ON_PAGE(PageLRU(page), page); | |
| 95 | 99 | |
| 96 | − VM_BUG_ON_PAGE(PageTail(page), page); | |
| 97 | − VM_BUG_ON_PAGE(PageCompound(page) && PageDoubleMap(page), page); | |
| 100 | + lruvec = folio_lruvec_relock_irq(page_folio(page), lruvec); | |
| 98 | 101 | |
| 99 | − if (!TestSetPageMlocked(page)) { | |
| 100 | − int nr_pages = thp_nr_pages(page); | |
| 102 | + /* As above, this is a little surprising, but possible */ | |
| 103 | + if (unlikely(page_evictable(page))) | |
| 104 | + goto out; | |
| 101 | 105 | |
| 102 | − mod_zone_page_state(page_zone(page), NR_MLOCK, nr_pages); | |
| 103 | − count_vm_events(UNEVICTABLE_PGMLOCKED, nr_pages); | |
| 104 | − if (!isolate_lru_page(page)) | |
| 105 | − putback_lru_page(page); | |
| 106 | − } | |
| 106 | + SetPageUnevictable(page); | |
| 107 | + page->mlock_count = !!PageMlocked(page); | |
| 108 | + __count_vm_events(UNEVICTABLE_PGCULLED, thp_nr_pages(page)); | |
| 109 | +out: | |
| 110 | + add_page_to_lru_list(page, lruvec); | |
| 111 | + SetPageLRU(page); | |
| 112 | + return lruvec; | |
| 107 | 113 | } |
| 108 | 114 | |
| 109 | −/* | |
| 110 | − * Finish munlock after successful page isolation | |
| 111 | − * | |
| 112 | − * Page must be locked. This is a wrapper for page_mlock() | |
| 113 | − * and putback_lru_page() with munlock accounting. | |
| 114 | − */ | |
| 115 | −static void __munlock_isolated_page(struct page *page) | |
| 115 | +static struct lruvec *__munlock_page(struct page *page, struct lruvec *lruvec) | |
| 116 | 116 | { |
| 117 | − /* | |
| 118 | − * Optimization: if the page was mapped just once, that's our mapping | |
| 119 | − * and we don't need to check all the other vmas. | |
| 120 | − */ | |
| 121 | − if (page_mapcount(page) > 1) | |
| 122 | − page_mlock(page); | |
| 117 | + int nr_pages = thp_nr_pages(page); | |
| 118 | + bool isolated = false; | |
| 119 | + | |
| 120 | + if (!TestClearPageLRU(page)) | |
| 121 | + goto munlock; | |
| 123 | 122 | |
| 124 | − /* Did try_to_unlock() succeed or punt? */ | |
| 125 | − if (!PageMlocked(page)) | |
| 126 | − count_vm_events(UNEVICTABLE_PGMUNLOCKED, thp_nr_pages(page)); | |
| 123 | + isolated = true; | |
| 124 | + lruvec = folio_lruvec_relock_irq(page_folio(page), lruvec); | |
| 127 | 125 | |
| 128 | − putback_lru_page(page); | |
| 126 | + if (PageUnevictable(page)) { | |
| 127 | + /* Then mlock_count is maintained, but might undercount */ | |
| 128 | + if (page->mlock_count) | |
| 129 | + page->mlock_count--; | |
| 130 | + if (page->mlock_count) | |
| 131 | + goto out; | |
| 132 | + } | |
| 133 | + /* else assume that was the last mlock: reclaim will fix it if not */ | |
| 134 | + | |
| 135 | +munlock: | |
| 136 | + if (TestClearPageMlocked(page)) { | |
| 137 | + __mod_zone_page_state(page_zone(page), NR_MLOCK, -nr_pages); | |
| 138 | + if (isolated || !PageUnevictable(page)) | |
| 139 | + __count_vm_events(UNEVICTABLE_PGMUNLOCKED, nr_pages); | |
| 140 | + else | |
| 141 | + __count_vm_events(UNEVICTABLE_PGSTRANDED, nr_pages); | |
| 142 | + } | |
| 143 | + | |
| 144 | + /* page_evictable() has to be checked *after* clearing Mlocked */ | |
| 145 | + if (isolated && PageUnevictable(page) && page_evictable(page)) { | |
| 146 | + del_page_from_lru_list(page, lruvec); | |
| 147 | + ClearPageUnevictable(page); | |
| 148 | + add_page_to_lru_list(page, lruvec); | |
| 149 | + __count_vm_events(UNEVICTABLE_PGRESCUED, nr_pages); | |
| 150 | + } | |
| 151 | +out: | |
| 152 | + if (isolated) | |
| 153 | + SetPageLRU(page); | |
| 154 | + return lruvec; | |
| 129 | 155 | } |
| 130 | 156 | |
| 131 | 157 | /* |
| 132 | − * Accounting for page isolation fail during munlock | |
| 133 | − * | |
| 134 | − * Performs accounting when page isolation fails in munlock. There is nothing | |
| 135 | − * else to do because it means some other task has already removed the page | |
| 136 | − * from the LRU. putback_lru_page() will take care of removing the page from | |
| 137 | − * the unevictable list, if necessary. vmscan [page_referenced()] will move | |
| 138 | − * the page back to the unevictable list if some other vma has it mlocked. | |
| 158 | + * Flags held in the low bits of a struct page pointer on the mlock_pvec. | |
| 139 | 159 | */ |
| 140 | −static void __munlock_isolation_failed(struct page *page) | |
| 160 | +#define LRU_PAGE 0x1 | |
| 161 | +#define NEW_PAGE 0x2 | |
| 162 | +static inline struct page *mlock_lru(struct page *page) | |
| 141 | 163 | { |
| 142 | − int nr_pages = thp_nr_pages(page); | |
| 164 | + return (struct page *)((unsigned long)page + LRU_PAGE); | |
| 165 | +} | |
| 143 | 166 | |
| 144 | − if (PageUnevictable(page)) | |
| 145 | − __count_vm_events(UNEVICTABLE_PGSTRANDED, nr_pages); | |
| 146 | − else | |
| 147 | − __count_vm_events(UNEVICTABLE_PGMUNLOCKED, nr_pages); | |
| 167 | +static inline struct page *mlock_new(struct page *page) | |
| 168 | +{ | |
| 169 | + return (struct page *)((unsigned long)page + NEW_PAGE); | |
| 148 | 170 | } |
| 149 | 171 | |
| 150 | −/** | |
| 151 | − * munlock_vma_page - munlock a vma page | |
| 152 | − * @page: page to be unlocked, either a normal page or THP page head | |
| 153 | − * | |
| 154 | − * returns the size of the page as a page mask (0 for normal page, | |
| 155 | − * HPAGE_PMD_NR - 1 for THP head page) | |
| 156 | − * | |
| 157 | − * called from munlock()/munmap() path with page supposedly on the LRU. | |
| 158 | − * When we munlock a page, because the vma where we found the page is being | |
| 159 | − * munlock()ed or munmap()ed, we want to check whether other vmas hold the | |
| 160 | − * page locked so that we can leave it on the unevictable lru list and not | |
| 161 | − * bother vmscan with it. However, to walk the page's rmap list in | |
| 162 | − * page_mlock() we must isolate the page from the LRU. If some other | |
| 163 | − * task has removed the page from the LRU, we won't be able to do that. | |
| 164 | − * So we clear the PageMlocked as we might not get another chance. If we | |
| 165 | − * can't isolate the page, we leave it for putback_lru_page() and vmscan | |
| 166 | − * [page_referenced()/try_to_unmap()] to deal with. | |
| 172 | +/* | |
| 173 | + * mlock_pagevec() is derived from pagevec_lru_move_fn(): | |
| 174 | + * perhaps that can make use of such page pointer flags in future, | |
| 175 | + * but for now just keep it for mlock. We could use three separate | |
| 176 | + * pagevecs instead, but one feels better (munlocking a full pagevec | |
| 177 | + * does not need to drain mlocking pagevecs first). | |
| 167 | 178 | */ |
| 168 | −unsigned int munlock_vma_page(struct page *page) | |
| 179 | +static void mlock_pagevec(struct pagevec *pvec) | |
| 169 | 180 | { |
| 170 | − int nr_pages; | |
| 171 | − | |
| 172 | − /* For page_mlock() and to serialize with page migration */ | |
| 173 | − BUG_ON(!PageLocked(page)); | |
| 174 | − VM_BUG_ON_PAGE(PageTail(page), page); | |
| 181 | + struct lruvec *lruvec = NULL; | |
| 182 | + unsigned long mlock; | |
| 183 | + struct page *page; | |
| 184 | + int i; | |
| 175 | 185 | |
| 176 | − if (!TestClearPageMlocked(page)) { | |
| 177 | − /* Potentially, PTE-mapped THP: do not skip the rest PTEs */ | |
| 178 | − return 0; | |
| 186 | + for (i = 0; i < pagevec_count(pvec); i++) { | |
| 187 | + page = pvec->pages[i]; | |
| 188 | + mlock = (unsigned long)page & (LRU_PAGE | NEW_PAGE); | |
| 189 | + page = (struct page *)((unsigned long)page - mlock); | |
| 190 | + pvec->pages[i] = page; | |
| 191 | + | |
| 192 | + if (mlock & LRU_PAGE) | |
| 193 | + lruvec = __mlock_page(page, lruvec); | |
| 194 | + else if (mlock & NEW_PAGE) | |
| 195 | + lruvec = __mlock_new_page(page, lruvec); | |
| 196 | + else | |
| 197 | + lruvec = __munlock_page(page, lruvec); | |
| 179 | 198 | } |
| 180 | 199 | |
| 181 | − nr_pages = thp_nr_pages(page); | |
| 182 | − mod_zone_page_state(page_zone(page), NR_MLOCK, -nr_pages); | |
| 200 | + if (lruvec) | |
| 201 | + unlock_page_lruvec_irq(lruvec); | |
| 202 | + release_pages(pvec->pages, pvec->nr); | |
| 203 | + pagevec_reinit(pvec); | |
| 204 | +} | |
| 183 | 205 | |
| 184 | − if (!isolate_lru_page(page)) | |
| 185 | − __munlock_isolated_page(page); | |
| 186 | − else | |
| 187 | − __munlock_isolation_failed(page); | |
| 206 | +void mlock_page_drain(int cpu) | |
| 207 | +{ | |
| 208 | + struct pagevec *pvec; | |
| 188 | 209 | |
| 189 | − return nr_pages - 1; | |
| 210 | + pvec = &per_cpu(mlock_pvec, cpu); | |
| 211 | + if (pagevec_count(pvec)) | |
| 212 | + mlock_pagevec(pvec); | |
| 190 | 213 | } |
| 191 | 214 | |
| 192 | −/* | |
| 193 | − * convert get_user_pages() return value to posix mlock() error | |
| 194 | − */ | |
| 195 | −static int __mlock_posix_error_return(long retval) | |
| 215 | +bool need_mlock_page_drain(int cpu) | |
| 196 | 216 | { |
| 197 | − if (retval == -EFAULT) | |
| 198 | − retval = -ENOMEM; | |
| 199 | − else if (retval == -ENOMEM) | |
| 200 | − retval = -EAGAIN; | |
| 201 | − return retval; | |
| 217 | + return pagevec_count(&per_cpu(mlock_pvec, cpu)); | |
| 202 | 218 | } |
| 203 | 219 | |
| 204 | −/* | |
| 205 | − * Prepare page for fast batched LRU putback via putback_lru_evictable_pagevec() | |
| 206 | − * | |
| 207 | − * The fast path is available only for evictable pages with single mapping. | |
| 208 | − * Then we can bypass the per-cpu pvec and get better performance. | |
| 209 | − * when mapcount > 1 we need page_mlock() which can fail. | |
| 210 | − * when !page_evictable(), we need the full redo logic of putback_lru_page to | |
| 211 | − * avoid leaving evictable page in unevictable list. | |
| 212 | − * | |
| 213 | − * In case of success, @page is added to @pvec and @pgrescued is incremented | |
| 214 | − * in case that the page was previously unevictable. @page is also unlocked. | |
| 220 | +/** | |
| 221 | + * mlock_folio - mlock a folio already on (or temporarily off) LRU | |
| 222 | + * @folio: folio to be mlocked. | |
| 215 | 223 | */ |
| 216 | −static bool __putback_lru_fast_prepare(struct page *page, struct pagevec *pvec, | |
| 217 | − int *pgrescued) | |
| 224 | +void mlock_folio(struct folio *folio) | |
| 218 | 225 | { |
| 219 | − VM_BUG_ON_PAGE(PageLRU(page), page); | |
| 220 | − VM_BUG_ON_PAGE(!PageLocked(page), page); | |
| 226 | + struct pagevec *pvec = &get_cpu_var(mlock_pvec); | |
| 221 | 227 | |
| 222 | − if (page_mapcount(page) <= 1 && page_evictable(page)) { | |
| 223 | − pagevec_add(pvec, page); | |
| 224 | − if (TestClearPageUnevictable(page)) | |
| 225 | − (*pgrescued)++; | |
| 226 | − unlock_page(page); | |
| 227 | − return true; | |
| 228 | + if (!folio_test_set_mlocked(folio)) { | |
| 229 | + int nr_pages = folio_nr_pages(folio); | |
| 230 | + | |
| 231 | + zone_stat_mod_folio(folio, NR_MLOCK, nr_pages); | |
| 232 | + __count_vm_events(UNEVICTABLE_PGMLOCKED, nr_pages); | |
| 228 | 233 | } |
| 229 | 234 | |
| 230 | − return false; | |
| 235 | + folio_get(folio); | |
| 236 | + if (!pagevec_add(pvec, mlock_lru(&folio->page)) || | |
| 237 | + folio_test_large(folio) || lru_cache_disabled()) | |
| 238 | + mlock_pagevec(pvec); | |
| 239 | + put_cpu_var(mlock_pvec); | |
| 231 | 240 | } |
| 232 | 241 | |
| 233 | −/* | |
| 234 | − * Putback multiple evictable pages to the LRU | |
| 235 | − * | |
| 236 | − * Batched putback of evictable pages that bypasses the per-cpu pvec. Some of | |
| 237 | − * the pages might have meanwhile become unevictable but that is OK. | |
| 242 | +/** | |
| 243 | + * mlock_new_page - mlock a newly allocated page not yet on LRU | |
| 244 | + * @page: page to be mlocked, either a normal page or a THP head. | |
| 238 | 245 | */ |
| 239 | −static void __putback_lru_fast(struct pagevec *pvec, int pgrescued) | |
| 246 | +void mlock_new_page(struct page *page) | |
| 240 | 247 | { |
| 241 | − count_vm_events(UNEVICTABLE_PGMUNLOCKED, pagevec_count(pvec)); | |
| 242 | − /* | |
| 243 | − *__pagevec_lru_add() calls release_pages() so we don't call | |
| 244 | − * put_page() explicitly | |
| 245 | − */ | |
| 246 | − __pagevec_lru_add(pvec); | |
| 247 | − count_vm_events(UNEVICTABLE_PGRESCUED, pgrescued); | |
| 248 | + struct pagevec *pvec = &get_cpu_var(mlock_pvec); | |
| 249 | + int nr_pages = thp_nr_pages(page); | |
| 250 | + | |
| 251 | + SetPageMlocked(page); | |
| 252 | + mod_zone_page_state(page_zone(page), NR_MLOCK, nr_pages); | |
| 253 | + __count_vm_events(UNEVICTABLE_PGMLOCKED, nr_pages); | |
| 254 | + | |
| 255 | + get_page(page); | |
| 256 | + if (!pagevec_add(pvec, mlock_new(page)) || | |
| 257 | + PageHead(page) || lru_cache_disabled()) | |
| 258 | + mlock_pagevec(pvec); | |
| 259 | + put_cpu_var(mlock_pvec); | |
| 248 | 260 | } |
| 249 | 261 | |
| 250 | −/* | |
| 251 | − * Munlock a batch of pages from the same zone | |
| 252 | − * | |
| 253 | − * The work is split to two main phases. First phase clears the Mlocked flag | |
| 254 | − * and attempts to isolate the pages, all under a single zone lru lock. | |
| 255 | − * The second phase finishes the munlock only for pages where isolation | |
| 256 | − * succeeded. | |
| 257 | − * | |
| 258 | − * Note that the pagevec may be modified during the process. | |
| 262 | +/** | |
| 263 | + * munlock_page - munlock a page | |
| 264 | + * @page: page to be munlocked, either a normal page or a THP head. | |
| 259 | 265 | */ |
| 260 | −static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone) | |
| 266 | +void munlock_page(struct page *page) | |
| 261 | 267 | { |
| 262 | − int i; | |
| 263 | − int nr = pagevec_count(pvec); | |
| 264 | − int delta_munlocked = -nr; | |
| 265 | − struct pagevec pvec_putback; | |
| 266 | − struct lruvec *lruvec = NULL; | |
| 267 | − int pgrescued = 0; | |
| 268 | − | |
| 269 | − pagevec_init(&pvec_putback); | |
| 270 | − | |
| 271 | − /* Phase 1: page isolation */ | |
| 272 | − for (i = 0; i < nr; i++) { | |
| 273 | − struct page *page = pvec->pages[i]; | |
| 274 | − struct folio *folio = page_folio(page); | |
| 275 | − | |
| 276 | − if (TestClearPageMlocked(page)) { | |
| 277 | − /* | |
| 278 | − * We already have pin from follow_page_mask() | |
| 279 | − * so we can spare the get_page() here. | |
| 280 | − */ | |
| 281 | − if (TestClearPageLRU(page)) { | |
| 282 | − lruvec = folio_lruvec_relock_irq(folio, lruvec); | |
| 283 | − del_page_from_lru_list(page, lruvec); | |
| 284 | − continue; | |
| 285 | − } else | |
| 286 | − __munlock_isolation_failed(page); | |
| 287 | − } else { | |
| 288 | − delta_munlocked++; | |
| 289 | − } | |
| 290 | − | |
| 291 | − /* | |
| 292 | − * We won't be munlocking this page in the next phase | |
| 293 | − * but we still need to release the follow_page_mask() | |
| 294 | − * pin. We cannot do it under lru_lock however. If it's | |
| 295 | − * the last pin, __page_cache_release() would deadlock. | |
| 296 | − */ | |
| 297 | − pagevec_add(&pvec_putback, pvec->pages[i]); | |
| 298 | − pvec->pages[i] = NULL; | |
| 299 | − } | |
| 300 | − if (lruvec) { | |
| 301 | − __mod_zone_page_state(zone, NR_MLOCK, delta_munlocked); | |
| 302 | − unlock_page_lruvec_irq(lruvec); | |
| 303 | − } else if (delta_munlocked) { | |
| 304 | − mod_zone_page_state(zone, NR_MLOCK, delta_munlocked); | |
| 305 | − } | |
| 306 | − | |
| 307 | − /* Now we can release pins of pages that we are not munlocking */ | |
| 308 | − pagevec_release(&pvec_putback); | |
| 309 | − | |
| 310 | − /* Phase 2: page munlock */ | |
| 311 | − for (i = 0; i < nr; i++) { | |
| 312 | − struct page *page = pvec->pages[i]; | |
| 313 | − | |
| 314 | − if (page) { | |
| 315 | − lock_page(page); | |
| 316 | − if (!__putback_lru_fast_prepare(page, &pvec_putback, | |
| 317 | − &pgrescued)) { | |
| 318 | − /* | |
| 319 | − * Slow path. We don't want to lose the last | |
| 320 | − * pin before unlock_page() | |
| 321 | − */ | |
| 322 | − get_page(page); /* for putback_lru_page() */ | |
| 323 | − __munlock_isolated_page(page); | |
| 324 | − unlock_page(page); | |
| 325 | − put_page(page); /* from follow_page_mask() */ | |
| 326 | − } | |
| 327 | − } | |
| 328 | − } | |
| 268 | + struct pagevec *pvec = &get_cpu_var(mlock_pvec); | |
| 329 | 269 | |
| 330 | 270 | /* |
| 331 | − * Phase 3: page putback for pages that qualified for the fast path | |
| 332 | − * This will also call put_page() to return pin from follow_page_mask() | |
| 271 | + * TestClearPageMlocked(page) must be left to __munlock_page(), | |
| 272 | + * which will check whether the page is multiply mlocked. | |
| 333 | 273 | */ |
| 334 | − if (pagevec_count(&pvec_putback)) | |
| 335 | − __putback_lru_fast(&pvec_putback, pgrescued); | |
| 274 | + | |
| 275 | + get_page(page); | |
| 276 | + if (!pagevec_add(pvec, page) || | |
| 277 | + PageHead(page) || lru_cache_disabled()) | |
| 278 | + mlock_pagevec(pvec); | |
| 279 | + put_cpu_var(mlock_pvec); | |
| 336 | 280 | } |
| 337 | 281 | |
| 338 | −/* | |
| 339 | − * Fill up pagevec for __munlock_pagevec using pte walk | |
| 340 | − * | |
| 341 | − * The function expects that the struct page corresponding to @start address is | |
| 342 | − * a non-TPH page already pinned and in the @pvec, and that it belongs to @zone. | |
| 343 | − * | |
| 344 | − * The rest of @pvec is filled by subsequent pages within the same pmd and same | |
| 345 | − * zone, as long as the pte's are present and vm_normal_page() succeeds. These | |
| 346 | − * pages also get pinned. | |
| 347 | − * | |
| 348 | − * Returns the address of the next page that should be scanned. This equals | |
| 349 | − * @start + PAGE_SIZE when no page could be added by the pte walk. | |
| 350 | − */ | |
| 351 | −static unsigned long __munlock_pagevec_fill(struct pagevec *pvec, | |
| 352 | − struct vm_area_struct *vma, struct zone *zone, | |
| 353 | − unsigned long start, unsigned long end) | |
| 282 | +static int mlock_pte_range(pmd_t *pmd, unsigned long addr, | |
| 283 | + unsigned long end, struct mm_walk *walk) | |
| 284 | + | |
| 354 | 285 | { |
| 355 | − pte_t *pte; | |
| 286 | + struct vm_area_struct *vma = walk->vma; | |
| 356 | 287 | spinlock_t *ptl; |
| 288 | + pte_t *start_pte, *pte; | |
| 289 | + struct page *page; | |
| 357 | 290 | |
| 358 | − /* | |
| 359 | − * Initialize pte walk starting at the already pinned page where we | |
| 360 | − * are sure that there is a pte, as it was pinned under the same | |
| 361 | − * mmap_lock write op. | |
| 362 | − */ | |
| 363 | − pte = get_locked_pte(vma->vm_mm, start, &ptl); | |
| 364 | − /* Make sure we do not cross the page table boundary */ | |
| 365 | − end = pgd_addr_end(start, end); | |
| 366 | − end = p4d_addr_end(start, end); | |
| 367 | − end = pud_addr_end(start, end); | |
| 368 | − end = pmd_addr_end(start, end); | |
| 369 | − | |
| 370 | − /* The page next to the pinned page is the first we will try to get */ | |
| 371 | − start += PAGE_SIZE; | |
| 372 | − while (start < end) { | |
| 373 | − struct page *page = NULL; | |
| 374 | − pte++; | |
| 375 | − if (pte_present(*pte)) | |
| 376 | − page = vm_normal_page(vma, start, *pte); | |
| 377 | − /* | |
| 378 | − * Break if page could not be obtained or the page's node+zone does not | |
| 379 | − * match | |
| 380 | − */ | |
| 381 | − if (!page || page_zone(page) != zone) | |
| 382 | − break; | |
| 291 | + ptl = pmd_trans_huge_lock(pmd, vma); | |
| 292 | + if (ptl) { | |
| 293 | + if (!pmd_present(*pmd)) | |
| 294 | + goto out; | |
| 295 | + if (is_huge_zero_pmd(*pmd)) | |
| 296 | + goto out; | |
| 297 | + page = pmd_page(*pmd); | |
| 298 | + if (vma->vm_flags & VM_LOCKED) | |
| 299 | + mlock_folio(page_folio(page)); | |
| 300 | + else | |
| 301 | + munlock_page(page); | |
| 302 | + goto out; | |
| 303 | + } | |
| 383 | 304 | |
| 384 | − /* | |
| 385 | − * Do not use pagevec for PTE-mapped THP, | |
| 386 | − * munlock_vma_pages_range() will handle them. | |
| 387 | − */ | |
| 305 | + start_pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); | |
| 306 | + for (pte = start_pte; addr != end; pte++, addr += PAGE_SIZE) { | |
| 307 | + if (!pte_present(*pte)) | |
| 308 | + continue; | |
| 309 | + page = vm_normal_page(vma, addr, *pte); | |
| 310 | + if (!page) | |
| 311 | + continue; | |
| 388 | 312 | if (PageTransCompound(page)) |
| 389 | − break; | |
| 390 | − | |
| 391 | − get_page(page); | |
| 392 | − /* | |
| 393 | − * Increase the address that will be returned *before* the | |
| 394 | − * eventual break due to pvec becoming full by adding the page | |
| 395 | − */ | |
| 396 | − start += PAGE_SIZE; | |
| 397 | − if (pagevec_add(pvec, page) == 0) | |
| 398 | − break; | |
| 313 | + continue; | |
| 314 | + if (vma->vm_flags & VM_LOCKED) | |
| 315 | + mlock_folio(page_folio(page)); | |
| 316 | + else | |
| 317 | + munlock_page(page); | |
| 399 | 318 | } |
| 400 | − pte_unmap_unlock(pte, ptl); | |
| 401 | − return start; | |
| 319 | + pte_unmap(start_pte); | |
| 320 | +out: | |
| 321 | + spin_unlock(ptl); | |
| 322 | + cond_resched(); | |
| 323 | + return 0; | |
| 402 | 324 | } |
| 403 | 325 | |
| 404 | 326 | /* |
| 405 | − * munlock_vma_pages_range() - munlock all pages in the vma range.' | |
| 406 | − * @vma - vma containing range to be munlock()ed. | |
| 327 | + * mlock_vma_pages_range() - mlock any pages already in the range, | |
| 328 | + * or munlock all pages in the range. | |
| 329 | + * @vma - vma containing range to be mlock()ed or munlock()ed | |
| 407 | 330 | * @start - start address in @vma of the range |
| 408 | − * @end - end of range in @vma. | |
| 331 | + * @end - end of range in @vma | |
| 332 | + * @newflags - the new set of flags for @vma. | |
| 409 | 333 | * |
| 410 | − * For mremap(), munmap() and exit(). | |
| 411 | − * | |
| 412 | − * Called with @vma VM_LOCKED. | |
| 413 | − * | |
| 414 | − * Returns with VM_LOCKED cleared. Callers must be prepared to | |
| 415 | − * deal with this. | |
| 416 | − * | |
| 417 | − * We don't save and restore VM_LOCKED here because pages are | |
| 418 | − * still on lru. In unmap path, pages might be scanned by reclaim | |
| 419 | − * and re-mlocked by page_mlock/try_to_unmap before we unmap and | |
| 420 | − * free them. This will result in freeing mlocked pages. | |
| 334 | + * Called for mlock(), mlock2() and mlockall(), to set @vma VM_LOCKED; | |
| 335 | + * called for munlock() and munlockall(), to clear VM_LOCKED from @vma. | |
| 421 | 336 | */ |
| 422 | −void munlock_vma_pages_range(struct vm_area_struct *vma, | |
| 423 | − unsigned long start, unsigned long end) | |
| 337 | +static void mlock_vma_pages_range(struct vm_area_struct *vma, | |
| 338 | + unsigned long start, unsigned long end, vm_flags_t newflags) | |
| 424 | 339 | { |
| 425 | − vma->vm_flags &= VM_LOCKED_CLEAR_MASK; | |
| 340 | + static const struct mm_walk_ops mlock_walk_ops = { | |
| 341 | + .pmd_entry = mlock_pte_range, | |
| 342 | + }; | |
| 426 | 343 | |
| 427 | − while (start < end) { | |
| 428 | − struct page *page; | |
| 429 | − unsigned int page_mask = 0; | |
| 430 | − unsigned long page_increm; | |
| 431 | − struct pagevec pvec; | |
| 432 | − struct zone *zone; | |
| 344 | + /* | |
| 345 | + * There is a slight chance that concurrent page migration, | |
| 346 | + * or page reclaim finding a page of this now-VM_LOCKED vma, | |
| 347 | + * will call mlock_vma_page() and raise page's mlock_count: | |
| 348 | + * double counting, leaving the page unevictable indefinitely. | |
| 349 | + * Communicate this danger to mlock_vma_page() with VM_IO, | |
| 350 | + * which is a VM_SPECIAL flag not allowed on VM_LOCKED vmas. | |
| 351 | + * mmap_lock is held in write mode here, so this weird | |
| 352 | + * combination should not be visible to other mmap_lock users; | |
| 353 | + * but WRITE_ONCE so rmap walkers must see VM_IO if VM_LOCKED. | |
| 354 | + */ | |
| 355 | + if (newflags & VM_LOCKED) | |
| 356 | + newflags |= VM_IO; | |
| 357 | + WRITE_ONCE(vma->vm_flags, newflags); | |
| 433 | 358 | |
| 434 | − pagevec_init(&pvec); | |
| 435 | − /* | |
| 436 | − * Although FOLL_DUMP is intended for get_dump_page(), | |
| 437 | − * it just so happens that its special treatment of the | |
| 438 | − * ZERO_PAGE (returning an error instead of doing get_page) | |
| 439 | − * suits munlock very well (and if somehow an abnormal page | |
| 440 | − * has sneaked into the range, we won't oops here: great). | |
| 441 | − */ | |
| 442 | − page = follow_page(vma, start, FOLL_GET | FOLL_DUMP); | |
| 443 | − | |
| 444 | − if (page && !IS_ERR(page)) { | |
| 445 | − if (PageTransTail(page)) { | |
| 446 | − VM_BUG_ON_PAGE(PageMlocked(page), page); | |
| 447 | − put_page(page); /* follow_page_mask() */ | |
| 448 | − } else if (PageTransHuge(page)) { | |
| 449 | − lock_page(page); | |
| 450 | − /* | |
| 451 | − * Any THP page found by follow_page_mask() may | |
| 452 | − * have gotten split before reaching | |
| 453 | − * munlock_vma_page(), so we need to compute | |
| 454 | − * the page_mask here instead. | |
| 455 | − */ | |
| 456 | − page_mask = munlock_vma_page(page); | |
| 457 | − unlock_page(page); | |
| 458 | − put_page(page); /* follow_page_mask() */ | |
| 459 | − } else { | |
| 460 | − /* | |
| 461 | − * Non-huge pages are handled in batches via | |
| 462 | − * pagevec. The pin from follow_page_mask() | |
| 463 | − * prevents them from collapsing by THP. | |
| 464 | − */ | |
| 465 | − pagevec_add(&pvec, page); | |
| 466 | − zone = page_zone(page); | |
| 467 | − | |
| 468 | − /* | |
| 469 | − * Try to fill the rest of pagevec using fast | |
| 470 | − * pte walk. This will also update start to | |
| 471 | − * the next page to process. Then munlock the | |
| 472 | − * pagevec. | |
| 473 | − */ | |
| 474 | − start = __munlock_pagevec_fill(&pvec, vma, | |
| 475 | − zone, start, end); | |
| 476 | − __munlock_pagevec(&pvec, zone); | |
| 477 | − goto next; | |
| 478 | − } | |
| 479 | − } | |
| 480 | − page_increm = 1 + page_mask; | |
| 481 | − start += page_increm * PAGE_SIZE; | |
| 482 | −next: | |
| 483 | − cond_resched(); | |
| 359 | + lru_add_drain(); | |
| 360 | + walk_page_range(vma->vm_mm, start, end, &mlock_walk_ops, NULL); | |
| 361 | + lru_add_drain(); | |
| 362 | + | |
| 363 | + if (newflags & VM_IO) { | |
| 364 | + newflags &= ~VM_IO; | |
| 365 | + WRITE_ONCE(vma->vm_flags, newflags); | |
| 484 | 366 | } |
| 485 | 367 | } |
| 486 | 368 | |
| @@ -500,10 +382,9 @@ static int mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev, · 13 unmodified lines | ||
| 500 | 382 | pgoff_t pgoff; |
| 501 | 383 | int nr_pages; |
| 502 | 384 | int ret = 0; |
| 503 | − int lock = !!(newflags & VM_LOCKED); | |
| 504 | − vm_flags_t old_flags = vma->vm_flags; | |
| 385 | + vm_flags_t oldflags = vma->vm_flags; | |
| 505 | 386 | |
| 506 | − if (newflags == vma->vm_flags || (vma->vm_flags & VM_SPECIAL) || | |
| 387 | + if (newflags == oldflags || (oldflags & VM_SPECIAL) || | |
| 507 | 388 | is_vm_hugetlb_page(vma) || vma == get_gate_vma(current->mm) || |
| 508 | 389 | vma_is_dax(vma) || vma_is_secretmem(vma)) |
| 509 | 390 | /* don't set VM_LOCKED or VM_LOCKONFAULT and don't count */ |
| @@ -535,9 +416,9 @@ success: · 25 unmodified lines | ||
| 535 | 416 | * Keep track of amount of locked VM. |
| 536 | 417 | */ |
| 537 | 418 | nr_pages = (end - start) >> PAGE_SHIFT; |
| 538 | − if (!lock) | |
| 419 | + if (!(newflags & VM_LOCKED)) | |
| 539 | 420 | nr_pages = -nr_pages; |
| 540 | − else if (old_flags & VM_LOCKED) | |
| 421 | + else if (oldflags & VM_LOCKED) | |
| 541 | 422 | nr_pages = 0; |
| 542 | 423 | mm->locked_vm += nr_pages; |
| 543 | 424 | |
| @@ -547,11 +428,12 @@ success: · 3 unmodified lines | ||
| 547 | 428 | * set VM_LOCKED, populate_vma_page_range will bring it back. |
| 548 | 429 | */ |
| 549 | 430 | |
| 550 | − if (lock) | |
| 431 | + if ((newflags & VM_LOCKED) && (oldflags & VM_LOCKED)) { | |
| 432 | + /* No work to do, and mlocking twice would be wrong */ | |
| 551 | 433 | vma->vm_flags = newflags; |
| 552 | − else | |
| 553 | − munlock_vma_pages_range(vma, start, end); | |
| 554 | − | |
| 434 | + } else { | |
| 435 | + mlock_vma_pages_range(vma, start, end, newflags); | |
| 436 | + } | |
| 555 | 437 | out: |
| 556 | 438 | *prev = vma; |
| 557 | 439 | return ret; |
| @@ -645,6 +527,18 @@ static unsigned long count_mm_mlocked_page_nr(struct mm_struct *mm, · 87 unmodified lines | ||
| 645 | 527 | return count >> PAGE_SHIFT; |
| 646 | 528 | } |
| 647 | 529 | |
| 530 | +/* | |
| 531 | + * convert get_user_pages() return value to posix mlock() error | |
| 532 | + */ | |
| 533 | +static int __mlock_posix_error_return(long retval) | |
| 534 | +{ | |
| 535 | + if (retval == -EFAULT) | |
| 536 | + retval = -ENOMEM; | |
| 537 | + else if (retval == -ENOMEM) | |
| 538 | + retval = -EAGAIN; | |
| 539 | + return retval; | |
| 540 | +} | |
| 541 | + | |
| 648 | 542 | static __must_check int do_mlock(unsigned long start, size_t len, vm_flags_t flags) |
| 649 | 543 | { |
| 650 | 544 | unsigned long locked; |
| @@ -2672,6 +2672,8 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma, · 2671 unmodified lines | ||
| 2672 | 2672 | vma->vm_prev = NULL; |
| 2673 | 2673 | do { |
| 2674 | 2674 | vma_rb_erase(vma, &mm->mm_rb); |
| 2675 | + if (vma->vm_flags & VM_LOCKED) | |
| 2676 | + mm->locked_vm -= vma_pages(vma); | |
| 2675 | 2677 | mm->map_count--; |
| 2676 | 2678 | tail_vma = vma; |
| 2677 | 2679 | vma = vma->vm_next; |
| @@ -2776,22 +2778,6 @@ int split_vma(struct mm_struct *mm, struct vm_area_struct *vma, · 98 unmodified lines | ||
| 2776 | 2778 | return __split_vma(mm, vma, addr, new_below); |
| 2777 | 2779 | } |
| 2778 | 2780 | |
| 2779 | −static inline void | |
| 2780 | −unlock_range(struct vm_area_struct *start, unsigned long limit) | |
| 2781 | −{ | |
| 2782 | − struct mm_struct *mm = start->vm_mm; | |
| 2783 | − struct vm_area_struct *tmp = start; | |
| 2784 | − | |
| 2785 | − while (tmp && tmp->vm_start < limit) { | |
| 2786 | − if (tmp->vm_flags & VM_LOCKED) { | |
| 2787 | − mm->locked_vm -= vma_pages(tmp); | |
| 2788 | − munlock_vma_pages_all(tmp); | |
| 2789 | − } | |
| 2790 | − | |
| 2791 | − tmp = tmp->vm_next; | |
| 2792 | − } | |
| 2793 | −} | |
| 2794 | − | |
| 2795 | 2781 | /* Munmap is split into 2 main parts -- this part which finds |
| 2796 | 2782 | * what needs doing, and the areas themselves, which do the |
| 2797 | 2783 | * work. This now handles partial unmappings. |
| @@ -2872,12 +2858,6 @@ int __do_munmap(struct mm_struct *mm, unsigned long start, size_t len, · 74 unmodified lines | ||
| 2872 | 2858 | return error; |
| 2873 | 2859 | } |
| 2874 | 2860 | |
| 2875 | − /* | |
| 2876 | − * unlock any mlock()ed ranges before detaching vmas | |
| 2877 | − */ | |
| 2878 | − if (mm->locked_vm) | |
| 2879 | − unlock_range(vma, end); | |
| 2880 | − | |
| 2881 | 2861 | /* Detach vmas from rbtree */ |
| 2882 | 2862 | if (!detach_vmas_to_be_unmapped(mm, vma, prev, end)) |
| 2883 | 2863 | downgrade = false; |
| @@ -3145,20 +3125,12 @@ void exit_mmap(struct mm_struct *mm) · 261 unmodified lines | ||
| 3145 | 3125 | * Nothing can be holding mm->mmap_lock here and the above call |
| 3146 | 3126 | * to mmu_notifier_release(mm) ensures mmu notifier callbacks in |
| 3147 | 3127 | * __oom_reap_task_mm() will not block. |
| 3148 | − * | |
| 3149 | − * This needs to be done before calling unlock_range(), | |
| 3150 | − * which clears VM_LOCKED, otherwise the oom reaper cannot | |
| 3151 | − * reliably test it. | |
| 3152 | 3128 | */ |
| 3153 | 3129 | (void)__oom_reap_task_mm(mm); |
| 3154 | − | |
| 3155 | 3130 | set_bit(MMF_OOM_SKIP, &mm->flags); |
| 3156 | 3131 | } |
| 3157 | 3132 | |
| 3158 | 3133 | mmap_write_lock(mm); |
| 3159 | − if (mm->locked_vm) | |
| 3160 | − unlock_range(mm->mmap, ULONG_MAX); | |
| 3161 | − | |
| 3162 | 3134 | arch_exit_mmap(mm); |
| 3163 | 3135 | |
| 3164 | 3136 | vma = mm->mmap; |
| @@ -81,6 +81,13 @@ void lruvec_init(struct lruvec *lruvec) · 80 unmodified lines | ||
| 81 | 81 | |
| 82 | 82 | for_each_lru(lru) |
| 83 | 83 | INIT_LIST_HEAD(&lruvec->lists[lru]); |
| 84 | + /* | |
| 85 | + * The "Unevictable LRU" is imaginary: though its size is maintained, | |
| 86 | + * it is never scanned, and unevictable pages are not threaded on it | |
| 87 | + * (so that their lru fields can be reused to hold mlock_count). | |
| 88 | + * Poison its list head, so that any operations on it would crash. | |
| 89 | + */ | |
| 90 | + list_del(&lruvec->lists[LRU_UNEVICTABLE]); | |
| 84 | 91 | } |
| 85 | 92 | |
| 86 | 93 | #if defined(CONFIG_NUMA_BALANCING) && !defined(LAST_CPUPID_NOT_IN_PAGE_FLAGS) |
| @@ -523,7 +523,7 @@ bool __oom_reap_task_mm(struct mm_struct *mm) · 522 unmodified lines | ||
| 523 | 523 | set_bit(MMF_UNSTABLE, &mm->flags); |
| 524 | 524 | |
| 525 | 525 | for (vma = mm->mmap ; vma; vma = vma->vm_next) { |
| 526 | − if (!can_madv_lru_vma(vma)) | |
| 526 | + if (vma->vm_flags & (VM_HUGETLB|VM_PFNMAP)) | |
| 527 | 527 | continue; |
| 528 | 528 | |
| 529 | 529 | /* |
| @@ -734,8 +734,7 @@ static void prep_compound_head(struct page *page, unsigned int order) · 733 unmodified lines | ||
| 734 | 734 | set_compound_page_dtor(page, COMPOUND_PAGE_DTOR); |
| 735 | 735 | set_compound_order(page, order); |
| 736 | 736 | atomic_set(compound_mapcount_ptr(page), -1); |
| 737 | − if (hpage_pincount_available(page)) | |
| 738 | − atomic_set(compound_pincount_ptr(page), 0); | |
| 737 | + atomic_set(compound_pincount_ptr(page), 0); | |
| 739 | 738 | } |
| 740 | 739 | |
| 741 | 740 | static void prep_compound_tail(struct page *head, int tail_idx) |
| @@ -13,6 +13,8 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/page_ext.h> |
| 14 | 14 | #include <linux/page_idle.h> |
| 15 | 15 | |
| 16 | +#include "internal.h" | |
| 17 | + | |
| 16 | 18 | #define BITMAP_CHUNK_SIZE sizeof(u64) |
| 17 | 19 | #define BITMAP_CHUNK_BITS (BITMAP_CHUNK_SIZE * BITS_PER_BYTE) |
| 18 | 20 | |
| @@ -44,15 +46,11 @@ static struct page *page_idle_get_page(unsigned long pfn) · 25 unmodified lines | ||
| 44 | 46 | return page; |
| 45 | 47 | } |
| 46 | 48 | |
| 47 | −static bool page_idle_clear_pte_refs_one(struct page *page, | |
| 49 | +static bool page_idle_clear_pte_refs_one(struct folio *folio, | |
| 48 | 50 | struct vm_area_struct *vma, |
| 49 | 51 | unsigned long addr, void *arg) |
| 50 | 52 | { |
| 51 | − struct page_vma_mapped_walk pvmw = { | |
| 52 | − .page = page, | |
| 53 | − .vma = vma, | |
| 54 | − .address = addr, | |
| 55 | − }; | |
| 53 | + DEFINE_FOLIO_VMA_WALK(pvmw, folio, vma, addr, 0); | |
| 56 | 54 | bool referenced = false; |
| 57 | 55 | |
| 58 | 56 | while (page_vma_mapped_walk(&pvmw)) { |
| @@ -74,41 +72,41 @@ static bool page_idle_clear_pte_refs_one(struct page *page, · 15 unmodified lines | ||
| 74 | 72 | } |
| 75 | 73 | |
| 76 | 74 | if (referenced) { |
| 77 | − clear_page_idle(page); | |
| 75 | + folio_clear_idle(folio); | |
| 78 | 76 | /* |
| 79 | 77 | * We cleared the referenced bit in a mapping to this page. To |
| 80 | 78 | * avoid interference with page reclaim, mark it young so that |
| 81 | − * page_referenced() will return > 0. | |
| 79 | + * folio_referenced() will return > 0. | |
| 82 | 80 | */ |
| 83 | − set_page_young(page); | |
| 81 | + folio_set_young(folio); | |
| 84 | 82 | } |
| 85 | 83 | return true; |
| 86 | 84 | } |
| 87 | 85 | |
| 88 | 86 | static void page_idle_clear_pte_refs(struct page *page) |
| 89 | 87 | { |
| 88 | + struct folio *folio = page_folio(page); | |
| 90 | 89 | /* |
| 91 | 90 | * Since rwc.arg is unused, rwc is effectively immutable, so we |
| 92 | 91 | * can make it static const to save some cycles and stack. |
| 93 | 92 | */ |
| 94 | 93 | static const struct rmap_walk_control rwc = { |
| 95 | 94 | .rmap_one = page_idle_clear_pte_refs_one, |
| 96 | − .anon_lock = page_lock_anon_vma_read, | |
| 95 | + .anon_lock = folio_lock_anon_vma_read, | |
| 97 | 96 | }; |
| 98 | 97 | bool need_lock; |
| 99 | 98 | |
| 100 | − if (!page_mapped(page) || | |
| 101 | − !page_rmapping(page)) | |
| 99 | + if (!folio_mapped(folio) || !folio_raw_mapping(folio)) | |
| 102 | 100 | return; |
| 103 | 101 | |
| 104 | − need_lock = !PageAnon(page) || PageKsm(page); | |
| 105 | − if (need_lock && !trylock_page(page)) | |
| 102 | + need_lock = !folio_test_anon(folio) || folio_test_ksm(folio); | |
| 103 | + if (need_lock && !folio_trylock(folio)) | |
| 106 | 104 | return; |
| 107 | 105 | |
| 108 | − rmap_walk(page, (struct rmap_walk_control *)&rwc); | |
| 106 | + rmap_walk(folio, &rwc); | |
| 109 | 107 | |
| 110 | 108 | if (need_lock) |
| 111 | − unlock_page(page); | |
| 109 | + folio_unlock(folio); | |
| 112 | 110 | } |
| 113 | 111 | |
| 114 | 112 | static ssize_t page_idle_bitmap_read(struct file *file, struct kobject *kobj, |
| @@ -53,18 +53,6 @@ static bool map_pte(struct page_vma_mapped_walk *pvmw) · 52 unmodified lines | ||
| 53 | 53 | return true; |
| 54 | 54 | } |
| 55 | 55 | |
| 56 | −static inline bool pfn_is_match(struct page *page, unsigned long pfn) | |
| 57 | −{ | |
| 58 | − unsigned long page_pfn = page_to_pfn(page); | |
| 59 | − | |
| 60 | − /* normal page and hugetlbfs page */ | |
| 61 | − if (!PageTransCompound(page) || PageHuge(page)) | |
| 62 | − return page_pfn == pfn; | |
| 63 | − | |
| 64 | − /* THP can be referenced by any subpage */ | |
| 65 | − return pfn >= page_pfn && pfn - page_pfn < thp_nr_pages(page); | |
| 66 | −} | |
| 67 | − | |
| 68 | 56 | /** |
| 69 | 57 | * check_pte - check if @pvmw->page is mapped at the @pvmw->pte |
| 70 | 58 | * @pvmw: page_vma_mapped_walk struct, includes a pair pte and page for checking |
| @@ -116,7 +104,17 @@ static bool check_pte(struct page_vma_mapped_walk *pvmw) · 45 unmodified lines | ||
| 116 | 104 | pfn = pte_pfn(*pvmw->pte); |
| 117 | 105 | } |
| 118 | 106 | |
| 119 | − return pfn_is_match(pvmw->page, pfn); | |
| 107 | + return (pfn - pvmw->pfn) < pvmw->nr_pages; | |
| 108 | +} | |
| 109 | + | |
| 110 | +/* Returns true if the two ranges overlap. Careful to not overflow. */ | |
| 111 | +static bool check_pmd(unsigned long pfn, struct page_vma_mapped_walk *pvmw) | |
| 112 | +{ | |
| 113 | + if ((pfn + HPAGE_PMD_NR - 1) < pvmw->pfn) | |
| 114 | + return false; | |
| 115 | + if (pfn > pvmw->pfn + pvmw->nr_pages - 1) | |
| 116 | + return false; | |
| 117 | + return true; | |
| 120 | 118 | } |
| 121 | 119 | |
| 122 | 120 | static void step_forward(struct page_vma_mapped_walk *pvmw, unsigned long size) |
| @@ -127,7 +125,7 @@ static void step_forward(struct page_vma_mapped_walk *pvmw, unsigned long size) · 4 unmodified lines | ||
| 127 | 125 | } |
| 128 | 126 | |
| 129 | 127 | /** |
| 130 | − * page_vma_mapped_walk - check if @pvmw->page is mapped in @pvmw->vma at | |
| 128 | + * page_vma_mapped_walk - check if @pvmw->pfn is mapped in @pvmw->vma at | |
| 131 | 129 | * @pvmw->address |
| 132 | 130 | * @pvmw: pointer to struct page_vma_mapped_walk. page, vma, address and flags |
| 133 | 131 | * must be set. pmd, pte and ptl must be NULL. |
| @@ -152,8 +150,8 @@ static void step_forward(struct page_vma_mapped_walk *pvmw, unsigned long size) · 18 unmodified lines | ||
| 152 | 150 | */ |
| 153 | 151 | bool page_vma_mapped_walk(struct page_vma_mapped_walk *pvmw) |
| 154 | 152 | { |
| 155 | − struct mm_struct *mm = pvmw->vma->vm_mm; | |
| 156 | − struct page *page = pvmw->page; | |
| 153 | + struct vm_area_struct *vma = pvmw->vma; | |
| 154 | + struct mm_struct *mm = vma->vm_mm; | |
| 157 | 155 | unsigned long end; |
| 158 | 156 | pgd_t *pgd; |
| 159 | 157 | p4d_t *p4d; |
| @@ -164,32 +162,26 @@ bool page_vma_mapped_walk(struct page_vma_mapped_walk *pvmw) · 4 unmodified lines | ||
| 164 | 162 | if (pvmw->pmd && !pvmw->pte) |
| 165 | 163 | return not_found(pvmw); |
| 166 | 164 | |
| 167 | − if (unlikely(PageHuge(page))) { | |
| 165 | + if (unlikely(is_vm_hugetlb_page(vma))) { | |
| 166 | + unsigned long size = pvmw->nr_pages * PAGE_SIZE; | |
| 168 | 167 | /* The only possible mapping was handled on last iteration */ |
| 169 | 168 | if (pvmw->pte) |
| 170 | 169 | return not_found(pvmw); |
| 171 | 170 | |
| 172 | 171 | /* when pud is not present, pte will be NULL */ |
| 173 | − pvmw->pte = huge_pte_offset(mm, pvmw->address, page_size(page)); | |
| 172 | + pvmw->pte = huge_pte_offset(mm, pvmw->address, size); | |
| 174 | 173 | if (!pvmw->pte) |
| 175 | 174 | return false; |
| 176 | 175 | |
| 177 | − pvmw->ptl = huge_pte_lockptr(page_hstate(page), mm, pvmw->pte); | |
| 176 | + pvmw->ptl = huge_pte_lockptr(size_to_hstate(size), mm, | |
| 177 | + pvmw->pte); | |
| 178 | 178 | spin_lock(pvmw->ptl); |
| 179 | 179 | if (!check_pte(pvmw)) |
| 180 | 180 | return not_found(pvmw); |
| 181 | 181 | return true; |
| 182 | 182 | } |
| 183 | 183 | |
| 184 | − /* | |
| 185 | − * Seek to next pte only makes sense for THP. | |
| 186 | − * But more important than that optimization, is to filter out | |
| 187 | − * any PageKsm page: whose page->index misleads vma_address() | |
| 188 | − * and vma_address_end() to disaster. | |
| 189 | − */ | |
| 190 | − end = PageTransCompound(page) ? | |
| 191 | − vma_address_end(page, pvmw->vma) : | |
| 192 | − pvmw->address + PAGE_SIZE; | |
| 184 | + end = vma_address_end(pvmw); | |
| 193 | 185 | if (pvmw->pte) |
| 194 | 186 | goto next_pte; |
| 195 | 187 | restart: |
| @@ -224,7 +216,7 @@ restart: · 28 unmodified lines | ||
| 224 | 216 | if (likely(pmd_trans_huge(pmde))) { |
| 225 | 217 | if (pvmw->flags & PVMW_MIGRATION) |
| 226 | 218 | return not_found(pvmw); |
| 227 | − if (pmd_page(pmde) != page) | |
| 219 | + if (!check_pmd(pmd_pfn(pmde), pvmw)) | |
| 228 | 220 | return not_found(pvmw); |
| 229 | 221 | return true; |
| 230 | 222 | } |
| @@ -236,7 +228,7 @@ restart: · 5 unmodified lines | ||
| 236 | 228 | return not_found(pvmw); |
| 237 | 229 | entry = pmd_to_swp_entry(pmde); |
| 238 | 230 | if (!is_migration_entry(entry) || |
| 239 | − pfn_swap_entry_to_page(entry) != page) | |
| 231 | + !check_pmd(swp_offset(entry), pvmw)) | |
| 240 | 232 | return not_found(pvmw); |
| 241 | 233 | return true; |
| 242 | 234 | } |
| @@ -250,7 +242,8 @@ restart: · 7 unmodified lines | ||
| 250 | 242 | * cleared *pmd but not decremented compound_mapcount(). |
| 251 | 243 | */ |
| 252 | 244 | if ((pvmw->flags & PVMW_SYNC) && |
| 253 | − PageTransCompound(page)) { | |
| 245 | + transparent_hugepage_active(vma) && | |
| 246 | + (pvmw->nr_pages >= HPAGE_PMD_NR)) { | |
| 254 | 247 | spinlock_t *ptl = pmd_lock(mm, pvmw->pmd); |
| 255 | 248 | |
| 256 | 249 | spin_unlock(ptl); |
| @@ -307,7 +300,8 @@ next_pte: · 50 unmodified lines | ||
| 307 | 300 | int page_mapped_in_vma(struct page *page, struct vm_area_struct *vma) |
| 308 | 301 | { |
| 309 | 302 | struct page_vma_mapped_walk pvmw = { |
| 310 | − .page = page, | |
| 303 | + .pfn = page_to_pfn(page), | |
| 304 | + .nr_pages = 1, | |
| 311 | 305 | .vma = vma, |
| 312 | 306 | .flags = PVMW_SYNC, |
| 313 | 307 | }; |
| @@ -262,7 +262,7 @@ static void read_pages(struct readahead_control *rac, struct list_head *pages, · 261 unmodified lines | ||
| 262 | 262 | |
| 263 | 263 | blk_finish_plug(&plug); |
| 264 | 264 | |
| 265 | − BUG_ON(!list_empty(pages)); | |
| 265 | + BUG_ON(pages && !list_empty(pages)); | |
| 266 | 266 | BUG_ON(readahead_count(rac)); |
| 267 | 267 | |
| 268 | 268 | out: |
| @@ -361,7 +361,7 @@ EXPORT_SYMBOL_GPL(page_cache_ra_unbounded); · 92 unmodified lines | ||
| 361 | 361 | * behaviour which would occur if page allocations are causing VM writeback. |
| 362 | 362 | * We really don't want to intermingle reads and writes like that. |
| 363 | 363 | */ |
| 364 | −void do_page_cache_ra(struct readahead_control *ractl, | |
| 364 | +static void do_page_cache_ra(struct readahead_control *ractl, | |
| 365 | 365 | unsigned long nr_to_read, unsigned long lookahead_size) |
| 366 | 366 | { |
| 367 | 367 | struct inode *inode = ractl->mapping->host; |
| @@ -545,11 +545,103 @@ static int try_context_readahead(struct address_space *mapping, · 177 unmodified lines | ||
| 545 | 545 | return 1; |
| 546 | 546 | } |
| 547 | 547 | |
| 548 | +/* | |
| 549 | + * There are some parts of the kernel which assume that PMD entries | |
| 550 | + * are exactly HPAGE_PMD_ORDER. Those should be fixed, but until then, | |
| 551 | + * limit the maximum allocation order to PMD size. I'm not aware of any | |
| 552 | + * assumptions about maximum order if THP are disabled, but 8 seems like | |
| 553 | + * a good order (that's 1MB if you're using 4kB pages) | |
| 554 | + */ | |
| 555 | +#ifdef CONFIG_TRANSPARENT_HUGEPAGE | |
| 556 | +#define MAX_PAGECACHE_ORDER HPAGE_PMD_ORDER | |
| 557 | +#else | |
| 558 | +#define MAX_PAGECACHE_ORDER 8 | |
| 559 | +#endif | |
| 560 | + | |
| 561 | +static inline int ra_alloc_folio(struct readahead_control *ractl, pgoff_t index, | |
| 562 | + pgoff_t mark, unsigned int order, gfp_t gfp) | |
| 563 | +{ | |
| 564 | + int err; | |
| 565 | + struct folio *folio = filemap_alloc_folio(gfp, order); | |
| 566 | + | |
| 567 | + if (!folio) | |
| 568 | + return -ENOMEM; | |
| 569 | + if (mark - index < (1UL << order)) | |
| 570 | + folio_set_readahead(folio); | |
| 571 | + err = filemap_add_folio(ractl->mapping, folio, index, gfp); | |
| 572 | + if (err) | |
| 573 | + folio_put(folio); | |
| 574 | + else | |
| 575 | + ractl->_nr_pages += 1UL << order; | |
| 576 | + return err; | |
| 577 | +} | |
| 578 | + | |
| 579 | +void page_cache_ra_order(struct readahead_control *ractl, | |
| 580 | + struct file_ra_state *ra, unsigned int new_order) | |
| 581 | +{ | |
| 582 | + struct address_space *mapping = ractl->mapping; | |
| 583 | + pgoff_t index = readahead_index(ractl); | |
| 584 | + pgoff_t limit = (i_size_read(mapping->host) - 1) >> PAGE_SHIFT; | |
| 585 | + pgoff_t mark = index + ra->size - ra->async_size; | |
| 586 | + int err = 0; | |
| 587 | + gfp_t gfp = readahead_gfp_mask(mapping); | |
| 588 | + | |
| 589 | + if (!mapping_large_folio_support(mapping) || ra->size < 4) | |
| 590 | + goto fallback; | |
| 591 | + | |
| 592 | + limit = min(limit, index + ra->size - 1); | |
| 593 | + | |
| 594 | + if (new_order < MAX_PAGECACHE_ORDER) { | |
| 595 | + new_order += 2; | |
| 596 | + if (new_order > MAX_PAGECACHE_ORDER) | |
| 597 | + new_order = MAX_PAGECACHE_ORDER; | |
| 598 | + while ((1 << new_order) > ra->size) | |
| 599 | + new_order--; | |
| 600 | + } | |
| 601 | + | |
| 602 | + while (index <= limit) { | |
| 603 | + unsigned int order = new_order; | |
| 604 | + | |
| 605 | + /* Align with smaller pages if needed */ | |
| 606 | + if (index & ((1UL << order) - 1)) { | |
| 607 | + order = __ffs(index); | |
| 608 | + if (order == 1) | |
| 609 | + order = 0; | |
| 610 | + } | |
| 611 | + /* Don't allocate pages past EOF */ | |
| 612 | + while (index + (1UL << order) - 1 > limit) { | |
| 613 | + if (--order == 1) | |
| 614 | + order = 0; | |
| 615 | + } | |
| 616 | + err = ra_alloc_folio(ractl, index, mark, order, gfp); | |
| 617 | + if (err) | |
| 618 | + break; | |
| 619 | + index += 1UL << order; | |
| 620 | + } | |
| 621 | + | |
| 622 | + if (index > limit) { | |
| 623 | + ra->size += index - limit - 1; | |
| 624 | + ra->async_size += index - limit - 1; | |
| 625 | + } | |
| 626 | + | |
| 627 | + read_pages(ractl, NULL, false); | |
| 628 | + | |
| 629 | + /* | |
| 630 | + * If there were already pages in the page cache, then we may have | |
| 631 | + * left some gaps. Let the regular readahead code take care of this | |
| 632 | + * situation. | |
| 633 | + */ | |
| 634 | + if (!err) | |
| 635 | + return; | |
| 636 | +fallback: | |
| 637 | + do_page_cache_ra(ractl, ra->size, ra->async_size); | |
| 638 | +} | |
| 639 | + | |
| 548 | 640 | /* |
| 549 | 641 | * A minimal readahead algorithm for trivial sequential/random reads. |
| 550 | 642 | */ |
| 551 | 643 | static void ondemand_readahead(struct readahead_control *ractl, |
| 552 | − bool hit_readahead_marker, unsigned long req_size) | |
| 644 | + struct folio *folio, unsigned long req_size) | |
| 553 | 645 | { |
| 554 | 646 | struct backing_dev_info *bdi = inode_to_bdi(ractl->mapping->host); |
| 555 | 647 | struct file_ra_state *ra = ractl->ra; |
| @@ -584,12 +676,12 @@ static void ondemand_readahead(struct readahead_control *ractl, · 28 unmodified lines | ||
| 584 | 676 | } |
| 585 | 677 | |
| 586 | 678 | /* |
| 587 | − * Hit a marked page without valid readahead state. | |
| 679 | + * Hit a marked folio without valid readahead state. | |
| 588 | 680 | * E.g. interleaved reads. |
| 589 | 681 | * Query the pagecache for async_size, which normally equals to |
| 590 | 682 | * readahead size. Ramp it up and use it as the new readahead size. |
| 591 | 683 | */ |
| 592 | − if (hit_readahead_marker) { | |
| 684 | + if (folio) { | |
| 593 | 685 | pgoff_t start; |
| 594 | 686 | |
| 595 | 687 | rcu_read_lock(); |
| @@ -662,7 +754,7 @@ readit: · 66 unmodified lines | ||
| 662 | 754 | } |
| 663 | 755 | |
| 664 | 756 | ractl->_index = ra->start; |
| 665 | − do_page_cache_ra(ractl, ra->size, ra->async_size); | |
| 757 | + page_cache_ra_order(ractl, ra, folio ? folio_order(folio) : 0); | |
| 666 | 758 | } |
| 667 | 759 | |
| 668 | 760 | void page_cache_sync_ra(struct readahead_control *ractl, |
| @@ -690,7 +782,7 @@ void page_cache_sync_ra(struct readahead_control *ractl, · 21 unmodified lines | ||
| 690 | 782 | } |
| 691 | 783 | |
| 692 | 784 | /* do read-ahead */ |
| 693 | − ondemand_readahead(ractl, false, req_count); | |
| 785 | + ondemand_readahead(ractl, NULL, req_count); | |
| 694 | 786 | } |
| 695 | 787 | EXPORT_SYMBOL_GPL(page_cache_sync_ra); |
| 696 | 788 | |
| @@ -713,7 +805,7 @@ void page_cache_async_ra(struct readahead_control *ractl, · 16 unmodified lines | ||
| 713 | 805 | return; |
| 714 | 806 | |
| 715 | 807 | /* do read-ahead */ |
| 716 | − ondemand_readahead(ractl, true, req_count); | |
| 808 | + ondemand_readahead(ractl, folio, req_count); | |
| 717 | 809 | } |
| 718 | 810 | EXPORT_SYMBOL_GPL(page_cache_async_ra); |
| 719 | 811 | |
| @@ -107,15 +107,15 @@ static inline void anon_vma_free(struct anon_vma *anon_vma) · 106 unmodified lines | ||
| 107 | 107 | VM_BUG_ON(atomic_read(&anon_vma->refcount)); |
| 108 | 108 | |
| 109 | 109 | /* |
| 110 | − * Synchronize against page_lock_anon_vma_read() such that | |
| 110 | + * Synchronize against folio_lock_anon_vma_read() such that | |
| 111 | 111 | * we can safely hold the lock without the anon_vma getting |
| 112 | 112 | * freed. |
| 113 | 113 | * |
| 114 | 114 | * Relies on the full mb implied by the atomic_dec_and_test() from |
| 115 | 115 | * put_anon_vma() against the acquire barrier implied by |
| 116 | − * down_read_trylock() from page_lock_anon_vma_read(). This orders: | |
| 116 | + * down_read_trylock() from folio_lock_anon_vma_read(). This orders: | |
| 117 | 117 | * |
| 118 | − * page_lock_anon_vma_read() VS put_anon_vma() | |
| 118 | + * folio_lock_anon_vma_read() VS put_anon_vma() | |
| 119 | 119 | * down_read_trylock() atomic_dec_and_test() |
| 120 | 120 | * LOCK MB |
| 121 | 121 | * atomic_read() rwsem_is_locked() |
| @@ -168,7 +168,7 @@ static void anon_vma_chain_link(struct vm_area_struct *vma, · 46 unmodified lines | ||
| 168 | 168 | * allocate a new one. |
| 169 | 169 | * |
| 170 | 170 | * Anon-vma allocations are very subtle, because we may have |
| 171 | − * optimistically looked up an anon_vma in page_lock_anon_vma_read() | |
| 171 | + * optimistically looked up an anon_vma in folio_lock_anon_vma_read() | |
| 172 | 172 | * and that may actually touch the rwsem even in the newly |
| 173 | 173 | * allocated vma (it depends on RCU to make sure that the |
| 174 | 174 | * anon_vma isn't actually destroyed). |
| @@ -526,28 +526,28 @@ out: · 351 unmodified lines | ||
| 526 | 526 | * atomic op -- the trylock. If we fail the trylock, we fall back to getting a |
| 527 | 527 | * reference like with page_get_anon_vma() and then block on the mutex. |
| 528 | 528 | */ |
| 529 | −struct anon_vma *page_lock_anon_vma_read(struct page *page) | |
| 529 | +struct anon_vma *folio_lock_anon_vma_read(struct folio *folio) | |
| 530 | 530 | { |
| 531 | 531 | struct anon_vma *anon_vma = NULL; |
| 532 | 532 | struct anon_vma *root_anon_vma; |
| 533 | 533 | unsigned long anon_mapping; |
| 534 | 534 | |
| 535 | 535 | rcu_read_lock(); |
| 536 | − anon_mapping = (unsigned long)READ_ONCE(page->mapping); | |
| 536 | + anon_mapping = (unsigned long)READ_ONCE(folio->mapping); | |
| 537 | 537 | if ((anon_mapping & PAGE_MAPPING_FLAGS) != PAGE_MAPPING_ANON) |
| 538 | 538 | goto out; |
| 539 | − if (!page_mapped(page)) | |
| 539 | + if (!folio_mapped(folio)) | |
| 540 | 540 | goto out; |
| 541 | 541 | |
| 542 | 542 | anon_vma = (struct anon_vma *) (anon_mapping - PAGE_MAPPING_ANON); |
| 543 | 543 | root_anon_vma = READ_ONCE(anon_vma->root); |
| 544 | 544 | if (down_read_trylock(&root_anon_vma->rwsem)) { |
| 545 | 545 | /* |
| 546 | − * If the page is still mapped, then this anon_vma is still | |
| 546 | + * If the folio is still mapped, then this anon_vma is still | |
| 547 | 547 | * its anon_vma, and holding the mutex ensures that it will |
| 548 | 548 | * not go away, see anon_vma_free(). |
| 549 | 549 | */ |
| 550 | − if (!page_mapped(page)) { | |
| 550 | + if (!folio_mapped(folio)) { | |
| 551 | 551 | up_read(&root_anon_vma->rwsem); |
| 552 | 552 | anon_vma = NULL; |
| 553 | 553 | } |
| @@ -560,7 +560,7 @@ struct anon_vma *page_lock_anon_vma_read(struct page *page) · 6 unmodified lines | ||
| 560 | 560 | goto out; |
| 561 | 561 | } |
| 562 | 562 | |
| 563 | − if (!page_mapped(page)) { | |
| 563 | + if (!folio_mapped(folio)) { | |
| 564 | 564 | rcu_read_unlock(); |
| 565 | 565 | put_anon_vma(anon_vma); |
| 566 | 566 | return NULL; |
| @@ -737,8 +737,9 @@ static bool should_defer_flush(struct mm_struct *mm, enum ttu_flags flags) · 170 unmodified lines | ||
| 737 | 737 | */ |
| 738 | 738 | unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma) |
| 739 | 739 | { |
| 740 | − if (PageAnon(page)) { | |
| 741 | − struct anon_vma *page__anon_vma = page_anon_vma(page); | |
| 740 | + struct folio *folio = page_folio(page); | |
| 741 | + if (folio_test_anon(folio)) { | |
| 742 | + struct anon_vma *page__anon_vma = folio_anon_vma(folio); | |
| 742 | 743 | /* |
| 743 | 744 | * Note: swapoff's unuse_vma() is more efficient with this |
| 744 | 745 | * check, and needs it to match anon_vma when KSM is active. |
| @@ -748,7 +749,7 @@ unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma) · 3 unmodified lines | ||
| 748 | 749 | return -EFAULT; |
| 749 | 750 | } else if (!vma->vm_file) { |
| 750 | 751 | return -EFAULT; |
| 751 | − } else if (vma->vm_file->f_mapping != compound_head(page)->mapping) { | |
| 752 | + } else if (vma->vm_file->f_mapping != folio->mapping) { | |
| 752 | 753 | return -EFAULT; |
| 753 | 754 | } |
| 754 | 755 | |
| @@ -789,30 +790,29 @@ out: · 34 unmodified lines | ||
| 789 | 790 | return pmd; |
| 790 | 791 | } |
| 791 | 792 | |
| 792 | −struct page_referenced_arg { | |
| 793 | +struct folio_referenced_arg { | |
| 793 | 794 | int mapcount; |
| 794 | 795 | int referenced; |
| 795 | 796 | unsigned long vm_flags; |
| 796 | 797 | struct mem_cgroup *memcg; |
| 797 | 798 | }; |
| 798 | 799 | /* |
| 799 | − * arg: page_referenced_arg will be passed | |
| 800 | + * arg: folio_referenced_arg will be passed | |
| 800 | 801 | */ |
| 801 | −static bool page_referenced_one(struct page *page, struct vm_area_struct *vma, | |
| 802 | − unsigned long address, void *arg) | |
| 802 | +static bool folio_referenced_one(struct folio *folio, | |
| 803 | + struct vm_area_struct *vma, unsigned long address, void *arg) | |
| 803 | 804 | { |
| 804 | − struct page_referenced_arg *pra = arg; | |
| 805 | − struct page_vma_mapped_walk pvmw = { | |
| 806 | − .page = page, | |
| 807 | − .vma = vma, | |
| 808 | − .address = address, | |
| 809 | − }; | |
| 805 | + struct folio_referenced_arg *pra = arg; | |
| 806 | + DEFINE_FOLIO_VMA_WALK(pvmw, folio, vma, address, 0); | |
| 810 | 807 | int referenced = 0; |
| 811 | 808 | |
| 812 | 809 | while (page_vma_mapped_walk(&pvmw)) { |
| 813 | 810 | address = pvmw.address; |
| 814 | 811 | |
| 815 | − if (vma->vm_flags & VM_LOCKED) { | |
| 812 | + if ((vma->vm_flags & VM_LOCKED) && | |
| 813 | + (!folio_test_large(folio) || !pvmw.pte)) { | |
| 814 | + /* Restore the mlock which got missed */ | |
| 815 | + mlock_vma_folio(folio, vma, !pvmw.pte); | |
| 816 | 816 | page_vma_mapped_walk_done(&pvmw); |
| 817 | 817 | pra->vm_flags |= VM_LOCKED; |
| 818 | 818 | return false; /* To break the loop */ |
| @@ -824,10 +824,10 @@ static bool page_referenced_one(struct page *page, struct vm_area_struct *vma, · 5 unmodified lines | ||
| 824 | 824 | /* |
| 825 | 825 | * Don't treat a reference through |
| 826 | 826 | * a sequentially read mapping as such. |
| 827 | − * If the page has been used in another mapping, | |
| 827 | + * If the folio has been used in another mapping, | |
| 828 | 828 | * we will catch it; if this other mapping is |
| 829 | 829 | * already gone, the unmap path will have set |
| 830 | − * PG_referenced or activated the page. | |
| 830 | + * the referenced flag or activated the folio. | |
| 831 | 831 | */ |
| 832 | 832 | if (likely(!(vma->vm_flags & VM_SEQ_READ))) |
| 833 | 833 | referenced++; |
| @@ -837,7 +837,7 @@ static bool page_referenced_one(struct page *page, struct vm_area_struct *vma, · 3 unmodified lines | ||
| 837 | 837 | pvmw.pmd)) |
| 838 | 838 | referenced++; |
| 839 | 839 | } else { |
| 840 | − /* unexpected pmd-mapped page? */ | |
| 840 | + /* unexpected pmd-mapped folio? */ | |
| 841 | 841 | WARN_ON_ONCE(1); |
| 842 | 842 | } |
| 843 | 843 | |
| @@ -845,13 +845,13 @@ static bool page_referenced_one(struct page *page, struct vm_area_struct *vma, · 1 unmodified line | ||
| 845 | 845 | } |
| 846 | 846 | |
| 847 | 847 | if (referenced) |
| 848 | − clear_page_idle(page); | |
| 849 | − if (test_and_clear_page_young(page)) | |
| 848 | + folio_clear_idle(folio); | |
| 849 | + if (folio_test_clear_young(folio)) | |
| 850 | 850 | referenced++; |
| 851 | 851 | |
| 852 | 852 | if (referenced) { |
| 853 | 853 | pra->referenced++; |
| 854 | − pra->vm_flags |= vma->vm_flags; | |
| 854 | + pra->vm_flags |= vma->vm_flags & ~VM_LOCKED; | |
| 855 | 855 | } |
| 856 | 856 | |
| 857 | 857 | if (!pra->mapcount) |
| @@ -860,9 +860,9 @@ static bool page_referenced_one(struct page *page, struct vm_area_struct *vma, · 2 unmodified lines | ||
| 860 | 860 | return true; |
| 861 | 861 | } |
| 862 | 862 | |
| 863 | −static bool invalid_page_referenced_vma(struct vm_area_struct *vma, void *arg) | |
| 863 | +static bool invalid_folio_referenced_vma(struct vm_area_struct *vma, void *arg) | |
| 864 | 864 | { |
| 865 | − struct page_referenced_arg *pra = arg; | |
| 865 | + struct folio_referenced_arg *pra = arg; | |
| 866 | 866 | struct mem_cgroup *memcg = pra->memcg; |
| 867 | 867 | |
| 868 | 868 | if (!mm_match_cgroup(vma->vm_mm, memcg)) |
| @@ -872,40 +872,39 @@ static bool invalid_page_referenced_vma(struct vm_area_struct *vma, void *arg) · 3 unmodified lines | ||
| 872 | 872 | } |
| 873 | 873 | |
| 874 | 874 | /** |
| 875 | − * page_referenced - test if the page was referenced | |
| 876 | − * @page: the page to test | |
| 877 | − * @is_locked: caller holds lock on the page | |
| 875 | + * folio_referenced() - Test if the folio was referenced. | |
| 876 | + * @folio: The folio to test. | |
| 877 | + * @is_locked: Caller holds lock on the folio. | |
| 878 | 878 | * @memcg: target memory cgroup |
| 879 | − * @vm_flags: collect encountered vma->vm_flags who actually referenced the page | |
| 879 | + * @vm_flags: A combination of all the vma->vm_flags which referenced the folio. | |
| 880 | 880 | * |
| 881 | − * Quick test_and_clear_referenced for all mappings to a page, | |
| 882 | − * returns the number of ptes which referenced the page. | |
| 881 | + * Quick test_and_clear_referenced for all mappings of a folio, | |
| 882 | + * | |
| 883 | + * Return: The number of mappings which referenced the folio. | |
| 883 | 884 | */ |
| 884 | −int page_referenced(struct page *page, | |
| 885 | − int is_locked, | |
| 886 | − struct mem_cgroup *memcg, | |
| 887 | − unsigned long *vm_flags) | |
| 885 | +int folio_referenced(struct folio *folio, int is_locked, | |
| 886 | + struct mem_cgroup *memcg, unsigned long *vm_flags) | |
| 888 | 887 | { |
| 889 | 888 | int we_locked = 0; |
| 890 | − struct page_referenced_arg pra = { | |
| 891 | − .mapcount = total_mapcount(page), | |
| 889 | + struct folio_referenced_arg pra = { | |
| 890 | + .mapcount = folio_mapcount(folio), | |
| 892 | 891 | .memcg = memcg, |
| 893 | 892 | }; |
| 894 | 893 | struct rmap_walk_control rwc = { |
| 895 | − .rmap_one = page_referenced_one, | |
| 894 | + .rmap_one = folio_referenced_one, | |
| 896 | 895 | .arg = (void *)&pra, |
| 897 | − .anon_lock = page_lock_anon_vma_read, | |
| 896 | + .anon_lock = folio_lock_anon_vma_read, | |
| 898 | 897 | }; |
| 899 | 898 | |
| 900 | 899 | *vm_flags = 0; |
| 901 | 900 | if (!pra.mapcount) |
| 902 | 901 | return 0; |
| 903 | 902 | |
| 904 | − if (!page_rmapping(page)) | |
| 903 | + if (!folio_raw_mapping(folio)) | |
| 905 | 904 | return 0; |
| 906 | 905 | |
| 907 | − if (!is_locked && (!PageAnon(page) || PageKsm(page))) { | |
| 908 | − we_locked = trylock_page(page); | |
| 906 | + if (!is_locked && (!folio_test_anon(folio) || folio_test_ksm(folio))) { | |
| 907 | + we_locked = folio_trylock(folio); | |
| 909 | 908 | if (!we_locked) |
| 910 | 909 | return 1; |
| 911 | 910 | } |
| @@ -916,37 +915,32 @@ int page_referenced(struct page *page, · 4 unmodified lines | ||
| 916 | 915 | * cgroups |
| 917 | 916 | */ |
| 918 | 917 | if (memcg) { |
| 919 | − rwc.invalid_vma = invalid_page_referenced_vma; | |
| 918 | + rwc.invalid_vma = invalid_folio_referenced_vma; | |
| 920 | 919 | } |
| 921 | 920 | |
| 922 | − rmap_walk(page, &rwc); | |
| 921 | + rmap_walk(folio, &rwc); | |
| 923 | 922 | *vm_flags = pra.vm_flags; |
| 924 | 923 | |
| 925 | 924 | if (we_locked) |
| 926 | − unlock_page(page); | |
| 925 | + folio_unlock(folio); | |
| 927 | 926 | |
| 928 | 927 | return pra.referenced; |
| 929 | 928 | } |
| 930 | 929 | |
| 931 | −static bool page_mkclean_one(struct page *page, struct vm_area_struct *vma, | |
| 930 | +static bool page_mkclean_one(struct folio *folio, struct vm_area_struct *vma, | |
| 932 | 931 | unsigned long address, void *arg) |
| 933 | 932 | { |
| 934 | − struct page_vma_mapped_walk pvmw = { | |
| 935 | − .page = page, | |
| 936 | − .vma = vma, | |
| 937 | − .address = address, | |
| 938 | − .flags = PVMW_SYNC, | |
| 939 | − }; | |
| 933 | + DEFINE_FOLIO_VMA_WALK(pvmw, folio, vma, address, PVMW_SYNC); | |
| 940 | 934 | struct mmu_notifier_range range; |
| 941 | 935 | int *cleaned = arg; |
| 942 | 936 | |
| 943 | 937 | /* |
| 944 | 938 | * We have to assume the worse case ie pmd for invalidation. Note that |
| 945 | − * the page can not be free from this function. | |
| 939 | + * the folio can not be freed from this function. | |
| 946 | 940 | */ |
| 947 | 941 | mmu_notifier_range_init(&range, MMU_NOTIFY_PROTECTION_PAGE, |
| 948 | 942 | 0, vma, vma->vm_mm, address, |
| 949 | − vma_address_end(page, vma)); | |
| 943 | + vma_address_end(&pvmw)); | |
| 950 | 944 | mmu_notifier_invalidate_range_start(&range); |
| 951 | 945 | |
| 952 | 946 | while (page_vma_mapped_walk(&pvmw)) { |
| @@ -974,14 +968,14 @@ static bool page_mkclean_one(struct page *page, struct vm_area_struct *vma, · 21 unmodified lines | ||
| 974 | 968 | if (!pmd_dirty(*pmd) && !pmd_write(*pmd)) |
| 975 | 969 | continue; |
| 976 | 970 | |
| 977 | − flush_cache_page(vma, address, page_to_pfn(page)); | |
| 971 | + flush_cache_page(vma, address, folio_pfn(folio)); | |
| 978 | 972 | entry = pmdp_invalidate(vma, address, pmd); |
| 979 | 973 | entry = pmd_wrprotect(entry); |
| 980 | 974 | entry = pmd_mkclean(entry); |
| 981 | 975 | set_pmd_at(vma->vm_mm, address, pmd, entry); |
| 982 | 976 | ret = 1; |
| 983 | 977 | #else |
| 984 | − /* unexpected pmd-mapped page? */ | |
| 978 | + /* unexpected pmd-mapped folio? */ | |
| 985 | 979 | WARN_ON_ONCE(1); |
| 986 | 980 | #endif |
| 987 | 981 | } |
| @@ -1029,7 +1023,7 @@ int folio_mkclean(struct folio *folio) · 41 unmodified lines | ||
| 1029 | 1023 | if (!mapping) |
| 1030 | 1024 | return 0; |
| 1031 | 1025 | |
| 1032 | − rmap_walk(&folio->page, &rwc); | |
| 1026 | + rmap_walk(folio, &rwc); | |
| 1033 | 1027 | |
| 1034 | 1028 | return cleaned; |
| 1035 | 1029 | } |
| @@ -1057,8 +1051,8 @@ void page_move_anon_rmap(struct page *page, struct vm_area_struct *vma) · 21 unmodified lines | ||
| 1057 | 1051 | anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON; |
| 1058 | 1052 | /* |
| 1059 | 1053 | * Ensure that anon_vma and the PAGE_MAPPING_ANON bit are written |
| 1060 | − * simultaneously, so a concurrent reader (eg page_referenced()'s | |
| 1061 | − * PageAnon()) will not see one without the other. | |
| 1054 | + * simultaneously, so a concurrent reader (eg folio_referenced()'s | |
| 1055 | + * folio_test_anon()) will not see one without the other. | |
| 1062 | 1056 | */ |
| 1063 | 1057 | WRITE_ONCE(page->mapping, (struct address_space *) anon_vma); |
| 1064 | 1058 | } |
| @@ -1108,6 +1102,7 @@ static void __page_set_anon_rmap(struct page *page, · 43 unmodified lines | ||
| 1108 | 1102 | static void __page_check_anon_rmap(struct page *page, |
| 1109 | 1103 | struct vm_area_struct *vma, unsigned long address) |
| 1110 | 1104 | { |
| 1105 | + struct folio *folio = page_folio(page); | |
| 1111 | 1106 | /* |
| 1112 | 1107 | * The page's anon-rmap details (mapping and index) are guaranteed to |
| 1113 | 1108 | * be set up correctly at this point. |
| @@ -1119,7 +1114,8 @@ static void __page_check_anon_rmap(struct page *page, · 5 unmodified lines | ||
| 1119 | 1114 | * are initially only visible via the pagetables, and the pte is locked |
| 1120 | 1115 | * over the call to page_add_new_anon_rmap. |
| 1121 | 1116 | */ |
| 1122 | − VM_BUG_ON_PAGE(page_anon_vma(page)->root != vma->anon_vma->root, page); | |
| 1117 | + VM_BUG_ON_FOLIO(folio_anon_vma(folio)->root != vma->anon_vma->root, | |
| 1118 | + folio); | |
| 1123 | 1119 | VM_BUG_ON_PAGE(page_to_pgoff(page) != linear_page_index(vma, address), |
| 1124 | 1120 | page); |
| 1125 | 1121 | } |
| @@ -1181,17 +1177,17 @@ void do_page_add_anon_rmap(struct page *page, · 55 unmodified lines | ||
| 1181 | 1177 | __mod_lruvec_page_state(page, NR_ANON_MAPPED, nr); |
| 1182 | 1178 | } |
| 1183 | 1179 | |
| 1184 | − if (unlikely(PageKsm(page))) { | |
| 1180 | + if (unlikely(PageKsm(page))) | |
| 1185 | 1181 | unlock_page_memcg(page); |
| 1186 | − return; | |
| 1187 | − } | |
| 1188 | 1182 | |
| 1189 | 1183 | /* address might be in next vma when migration races vma_adjust */ |
| 1190 | − if (first) | |
| 1184 | + else if (first) | |
| 1191 | 1185 | __page_set_anon_rmap(page, vma, address, |
| 1192 | 1186 | flags & RMAP_EXCLUSIVE); |
| 1193 | 1187 | else |
| 1194 | 1188 | __page_check_anon_rmap(page, vma, address); |
| 1189 | + | |
| 1190 | + mlock_vma_page(page, vma, compound); | |
| 1195 | 1191 | } |
| 1196 | 1192 | |
| 1197 | 1193 | /** |
| @@ -1216,8 +1212,7 @@ void page_add_new_anon_rmap(struct page *page, · 18 unmodified lines | ||
| 1216 | 1212 | VM_BUG_ON_PAGE(!PageTransHuge(page), page); |
| 1217 | 1213 | /* increment count (starts at -1) */ |
| 1218 | 1214 | atomic_set(compound_mapcount_ptr(page), 0); |
| 1219 | − if (hpage_pincount_available(page)) | |
| 1220 | − atomic_set(compound_pincount_ptr(page), 0); | |
| 1215 | + atomic_set(compound_pincount_ptr(page), 0); | |
| 1221 | 1216 | |
| 1222 | 1217 | __mod_lruvec_page_state(page, NR_ANON_THPS, nr); |
| 1223 | 1218 | } else { |
| @@ -1232,12 +1227,14 @@ void page_add_new_anon_rmap(struct page *page, · 8 unmodified lines | ||
| 1232 | 1227 | |
| 1233 | 1228 | /** |
| 1234 | 1229 | * page_add_file_rmap - add pte mapping to a file page |
| 1235 | − * @page: the page to add the mapping to | |
| 1236 | − * @compound: charge the page as compound or small page | |
| 1230 | + * @page: the page to add the mapping to | |
| 1231 | + * @vma: the vm area in which the mapping is added | |
| 1232 | + * @compound: charge the page as compound or small page | |
| 1237 | 1233 | * |
| 1238 | 1234 | * The caller needs to hold the pte lock. |
| 1239 | 1235 | */ |
| 1240 | −void page_add_file_rmap(struct page *page, bool compound) | |
| 1236 | +void page_add_file_rmap(struct page *page, | |
| 1237 | + struct vm_area_struct *vma, bool compound) | |
| 1241 | 1238 | { |
| 1242 | 1239 | int i, nr = 1; |
| 1243 | 1240 | |
| @@ -1271,13 +1268,8 @@ void page_add_file_rmap(struct page *page, bool compound) · 27 unmodified lines | ||
| 1271 | 1268 | nr_pages); |
| 1272 | 1269 | } else { |
| 1273 | 1270 | if (PageTransCompound(page) && page_mapping(page)) { |
| 1274 | − struct page *head = compound_head(page); | |
| 1275 | − | |
| 1276 | 1271 | VM_WARN_ON_ONCE(!PageLocked(page)); |
| 1277 | − | |
| 1278 | − SetPageDoubleMap(head); | |
| 1279 | − if (PageMlocked(page)) | |
| 1280 | − clear_page_mlock(head); | |
| 1272 | + SetPageDoubleMap(compound_head(page)); | |
| 1281 | 1273 | } |
| 1282 | 1274 | if (!atomic_inc_and_test(&page->_mapcount)) |
| 1283 | 1275 | goto out; |
| @@ -1285,6 +1277,8 @@ void page_add_file_rmap(struct page *page, bool compound) · 1 unmodified line | ||
| 1285 | 1277 | __mod_lruvec_page_state(page, NR_FILE_MAPPED, nr); |
| 1286 | 1278 | out: |
| 1287 | 1279 | unlock_page_memcg(page); |
| 1280 | + | |
| 1281 | + mlock_vma_page(page, vma, compound); | |
| 1288 | 1282 | } |
| 1289 | 1283 | |
| 1290 | 1284 | static void page_remove_file_rmap(struct page *page, bool compound) |
| @@ -1327,9 +1321,6 @@ static void page_remove_file_rmap(struct page *page, bool compound) · 36 unmodified lines | ||
| 1327 | 1321 | * pte lock(a spinlock) is held, which implies preemption disabled. |
| 1328 | 1322 | */ |
| 1329 | 1323 | __mod_lruvec_page_state(page, NR_FILE_MAPPED, -nr); |
| 1330 | − | |
| 1331 | − if (unlikely(PageMlocked(page))) | |
| 1332 | − clear_page_mlock(page); | |
| 1333 | 1324 | } |
| 1334 | 1325 | |
| 1335 | 1326 | static void page_remove_anon_compound_rmap(struct page *page) |
| @@ -1369,9 +1360,6 @@ static void page_remove_anon_compound_rmap(struct page *page) · 33 unmodified lines | ||
| 1369 | 1360 | nr = thp_nr_pages(page); |
| 1370 | 1361 | } |
| 1371 | 1362 | |
| 1372 | − if (unlikely(PageMlocked(page))) | |
| 1373 | − clear_page_mlock(page); | |
| 1374 | − | |
| 1375 | 1363 | if (nr) |
| 1376 | 1364 | __mod_lruvec_page_state(page, NR_ANON_MAPPED, -nr); |
| 1377 | 1365 | } |
| @@ -1379,11 +1367,13 @@ static void page_remove_anon_compound_rmap(struct page *page) · 1 unmodified line | ||
| 1379 | 1367 | /** |
| 1380 | 1368 | * page_remove_rmap - take down pte mapping from a page |
| 1381 | 1369 | * @page: page to remove mapping from |
| 1370 | + * @vma: the vm area from which the mapping is removed | |
| 1382 | 1371 | * @compound: uncharge the page as compound or small page |
| 1383 | 1372 | * |
| 1384 | 1373 | * The caller needs to hold the pte lock. |
| 1385 | 1374 | */ |
| 1386 | −void page_remove_rmap(struct page *page, bool compound) | |
| 1375 | +void page_remove_rmap(struct page *page, | |
| 1376 | + struct vm_area_struct *vma, bool compound) | |
| 1387 | 1377 | { |
| 1388 | 1378 | lock_page_memcg(page); |
| 1389 | 1379 | |
| @@ -1408,9 +1398,6 @@ void page_remove_rmap(struct page *page, bool compound) · 18 unmodified lines | ||
| 1408 | 1398 | */ |
| 1409 | 1399 | __dec_lruvec_page_state(page, NR_ANON_MAPPED); |
| 1410 | 1400 | |
| 1411 | − if (unlikely(PageMlocked(page))) | |
| 1412 | − clear_page_mlock(page); | |
| 1413 | − | |
| 1414 | 1401 | if (PageTransCompound(page)) |
| 1415 | 1402 | deferred_split_huge_page(compound_head(page)); |
| 1416 | 1403 | |
| @@ -1425,20 +1412,18 @@ void page_remove_rmap(struct page *page, bool compound) · 8 unmodified lines | ||
| 1425 | 1412 | */ |
| 1426 | 1413 | out: |
| 1427 | 1414 | unlock_page_memcg(page); |
| 1415 | + | |
| 1416 | + munlock_vma_page(page, vma, compound); | |
| 1428 | 1417 | } |
| 1429 | 1418 | |
| 1430 | 1419 | /* |
| 1431 | 1420 | * @arg: enum ttu_flags will be passed to this argument |
| 1432 | 1421 | */ |
| 1433 | −static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma, | |
| 1422 | +static bool try_to_unmap_one(struct folio *folio, struct vm_area_struct *vma, | |
| 1434 | 1423 | unsigned long address, void *arg) |
| 1435 | 1424 | { |
| 1436 | 1425 | struct mm_struct *mm = vma->vm_mm; |
| 1437 | − struct page_vma_mapped_walk pvmw = { | |
| 1438 | − .page = page, | |
| 1439 | − .vma = vma, | |
| 1440 | − .address = address, | |
| 1441 | − }; | |
| 1426 | + DEFINE_FOLIO_VMA_WALK(pvmw, folio, vma, address, 0); | |
| 1442 | 1427 | pte_t pteval; |
| 1443 | 1428 | struct page *subpage; |
| 1444 | 1429 | bool ret = true; |
| @@ -1455,21 +1440,20 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma, · 10 unmodified lines | ||
| 1455 | 1440 | pvmw.flags = PVMW_SYNC; |
| 1456 | 1441 | |
| 1457 | 1442 | if (flags & TTU_SPLIT_HUGE_PMD) |
| 1458 | − split_huge_pmd_address(vma, address, false, page); | |
| 1443 | + split_huge_pmd_address(vma, address, false, folio); | |
| 1459 | 1444 | |
| 1460 | 1445 | /* |
| 1461 | 1446 | * For THP, we have to assume the worse case ie pmd for invalidation. |
| 1462 | 1447 | * For hugetlb, it could be much worse if we need to do pud |
| 1463 | 1448 | * invalidation in the case of pmd sharing. |
| 1464 | 1449 | * |
| 1465 | − * Note that the page can not be free in this function as call of | |
| 1466 | − * try_to_unmap() must hold a reference on the page. | |
| 1450 | + * Note that the folio can not be freed in this function as call of | |
| 1451 | + * try_to_unmap() must hold a reference on the folio. | |
| 1467 | 1452 | */ |
| 1468 | − range.end = PageKsm(page) ? | |
| 1469 | − address + PAGE_SIZE : vma_address_end(page, vma); | |
| 1453 | + range.end = vma_address_end(&pvmw); | |
| 1470 | 1454 | mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, vma->vm_mm, |
| 1471 | 1455 | address, range.end); |
| 1472 | − if (PageHuge(page)) { | |
| 1456 | + if (folio_test_hugetlb(folio)) { | |
| 1473 | 1457 | /* |
| 1474 | 1458 | * If sharing is possible, start and end will be adjusted |
| 1475 | 1459 | * accordingly. |
| @@ -1480,32 +1464,26 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma, · 4 unmodified lines | ||
| 1480 | 1464 | mmu_notifier_invalidate_range_start(&range); |
| 1481 | 1465 | |
| 1482 | 1466 | while (page_vma_mapped_walk(&pvmw)) { |
| 1467 | + /* Unexpected PMD-mapped THP? */ | |
| 1468 | + VM_BUG_ON_FOLIO(!pvmw.pte, folio); | |
| 1469 | + | |
| 1483 | 1470 | /* |
| 1484 | − * If the page is mlock()d, we cannot swap it out. | |
| 1471 | + * If the folio is in an mlock()d vma, we must not swap it out. | |
| 1485 | 1472 | */ |
| 1486 | 1473 | if (!(flags & TTU_IGNORE_MLOCK) && |
| 1487 | 1474 | (vma->vm_flags & VM_LOCKED)) { |
| 1488 | − /* | |
| 1489 | − * PTE-mapped THP are never marked as mlocked: so do | |
| 1490 | − * not set it on a DoubleMap THP, nor on an Anon THP | |
| 1491 | − * (which may still be PTE-mapped after DoubleMap was | |
| 1492 | − * cleared). But stop unmapping even in those cases. | |
| 1493 | − */ | |
| 1494 | − if (!PageTransCompound(page) || (PageHead(page) && | |
| 1495 | − !PageDoubleMap(page) && !PageAnon(page))) | |
| 1496 | − mlock_vma_page(page); | |
| 1475 | + /* Restore the mlock which got missed */ | |
| 1476 | + mlock_vma_folio(folio, vma, false); | |
| 1497 | 1477 | page_vma_mapped_walk_done(&pvmw); |
| 1498 | 1478 | ret = false; |
| 1499 | 1479 | break; |
| 1500 | 1480 | } |
| 1501 | 1481 | |
| 1502 | − /* Unexpected PMD-mapped THP? */ | |
| 1503 | − VM_BUG_ON_PAGE(!pvmw.pte, page); | |
| 1504 | − | |
| 1505 | − subpage = page - page_to_pfn(page) + pte_pfn(*pvmw.pte); | |
| 1482 | + subpage = folio_page(folio, | |
| 1483 | + pte_pfn(*pvmw.pte) - folio_pfn(folio)); | |
| 1506 | 1484 | address = pvmw.address; |
| 1507 | 1485 | |
| 1508 | − if (PageHuge(page) && !PageAnon(page)) { | |
| 1486 | + if (folio_test_hugetlb(folio) && !folio_test_anon(folio)) { | |
| 1509 | 1487 | /* |
| 1510 | 1488 | * To call huge_pmd_unshare, i_mmap_rwsem must be |
| 1511 | 1489 | * held in write mode. Caller needs to explicitly |
| @@ -1544,7 +1522,7 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma, · 32 unmodified lines | ||
| 1544 | 1522 | if (should_defer_flush(mm, flags)) { |
| 1545 | 1523 | /* |
| 1546 | 1524 | * We clear the PTE but do not flush so potentially |
| 1547 | − * a remote CPU could still be writing to the page. | |
| 1525 | + * a remote CPU could still be writing to the folio. | |
| 1548 | 1526 | * If the entry was previously clean then the |
| 1549 | 1527 | * architecture must guarantee that a clear->dirty |
| 1550 | 1528 | * transition on a cached TLB entry is written through |
| @@ -1557,22 +1535,22 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma, · 6 unmodified lines | ||
| 1557 | 1535 | pteval = ptep_clear_flush(vma, address, pvmw.pte); |
| 1558 | 1536 | } |
| 1559 | 1537 | |
| 1560 | − /* Move the dirty bit to the page. Now the pte is gone. */ | |
| 1538 | + /* Set the dirty flag on the folio now the pte is gone. */ | |
| 1561 | 1539 | if (pte_dirty(pteval)) |
| 1562 | − set_page_dirty(page); | |
| 1540 | + folio_mark_dirty(folio); | |
| 1563 | 1541 | |
| 1564 | 1542 | /* Update high watermark before we lower rss */ |
| 1565 | 1543 | update_hiwater_rss(mm); |
| 1566 | 1544 | |
| 1567 | 1545 | if (PageHWPoison(subpage) && !(flags & TTU_IGNORE_HWPOISON)) { |
| 1568 | 1546 | pteval = swp_entry_to_pte(make_hwpoison_entry(subpage)); |
| 1569 | − if (PageHuge(page)) { | |
| 1570 | − hugetlb_count_sub(compound_nr(page), mm); | |
| 1547 | + if (folio_test_hugetlb(folio)) { | |
| 1548 | + hugetlb_count_sub(folio_nr_pages(folio), mm); | |
| 1571 | 1549 | set_huge_swap_pte_at(mm, address, |
| 1572 | 1550 | pvmw.pte, pteval, |
| 1573 | 1551 | vma_mmu_pagesize(vma)); |
| 1574 | 1552 | } else { |
| 1575 | − dec_mm_counter(mm, mm_counter(page)); | |
| 1553 | + dec_mm_counter(mm, mm_counter(&folio->page)); | |
| 1576 | 1554 | set_pte_at(mm, address, pvmw.pte, pteval); |
| 1577 | 1555 | } |
| 1578 | 1556 | |
| @@ -1587,18 +1565,19 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma, · 8 unmodified lines | ||
| 1587 | 1565 | * migration) will not expect userfaults on already |
| 1588 | 1566 | * copied pages. |
| 1589 | 1567 | */ |
| 1590 | − dec_mm_counter(mm, mm_counter(page)); | |
| 1568 | + dec_mm_counter(mm, mm_counter(&folio->page)); | |
| 1591 | 1569 | /* We have to invalidate as we cleared the pte */ |
| 1592 | 1570 | mmu_notifier_invalidate_range(mm, address, |
| 1593 | 1571 | address + PAGE_SIZE); |
| 1594 | − } else if (PageAnon(page)) { | |
| 1572 | + } else if (folio_test_anon(folio)) { | |
| 1595 | 1573 | swp_entry_t entry = { .val = page_private(subpage) }; |
| 1596 | 1574 | pte_t swp_pte; |
| 1597 | 1575 | /* |
| 1598 | 1576 | * Store the swap location in the pte. |
| 1599 | 1577 | * See handle_pte_fault() ... |
| 1600 | 1578 | */ |
| 1601 | − if (unlikely(PageSwapBacked(page) != PageSwapCache(page))) { | |
| 1579 | + if (unlikely(folio_test_swapbacked(folio) != | |
| 1580 | + folio_test_swapcache(folio))) { | |
| 1602 | 1581 | WARN_ON_ONCE(1); |
| 1603 | 1582 | ret = false; |
| 1604 | 1583 | /* We have to invalidate as we cleared the pte */ |
| @@ -1609,8 +1588,8 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma, · 4 unmodified lines | ||
| 1609 | 1588 | } |
| 1610 | 1589 | |
| 1611 | 1590 | /* MADV_FREE page check */ |
| 1612 | − if (!PageSwapBacked(page)) { | |
| 1613 | − if (!PageDirty(page)) { | |
| 1591 | + if (!folio_test_swapbacked(folio)) { | |
| 1592 | + if (!folio_test_dirty(folio)) { | |
| 1614 | 1593 | /* Invalidate as we cleared the pte */ |
| 1615 | 1594 | mmu_notifier_invalidate_range(mm, |
| 1616 | 1595 | address, address + PAGE_SIZE); |
| @@ -1619,11 +1598,11 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma, · 2 unmodified lines | ||
| 1619 | 1598 | } |
| 1620 | 1599 | |
| 1621 | 1600 | /* |
| 1622 | − * If the page was redirtied, it cannot be | |
| 1601 | + * If the folio was redirtied, it cannot be | |
| 1623 | 1602 | * discarded. Remap the page to page table. |
| 1624 | 1603 | */ |
| 1625 | 1604 | set_pte_at(mm, address, pvmw.pte, pteval); |
| 1626 | − SetPageSwapBacked(page); | |
| 1605 | + folio_set_swapbacked(folio); | |
| 1627 | 1606 | ret = false; |
| 1628 | 1607 | page_vma_mapped_walk_done(&pvmw); |
| 1629 | 1608 | break; |
| @@ -1660,16 +1639,17 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma, · 30 unmodified lines | ||
| 1660 | 1639 | address + PAGE_SIZE); |
| 1661 | 1640 | } else { |
| 1662 | 1641 | /* |
| 1663 | − * This is a locked file-backed page, thus it cannot | |
| 1664 | − * be removed from the page cache and replaced by a new | |
| 1665 | − * page before mmu_notifier_invalidate_range_end, so no | |
| 1666 | − * concurrent thread might update its page table to | |
| 1667 | − * point at new page while a device still is using this | |
| 1668 | − * page. | |
| 1642 | + * This is a locked file-backed folio, | |
| 1643 | + * so it cannot be removed from the page | |
| 1644 | + * cache and replaced by a new folio before | |
| 1645 | + * mmu_notifier_invalidate_range_end, so no | |
| 1646 | + * concurrent thread might update its page table | |
| 1647 | + * to point at a new folio while a device is | |
| 1648 | + * still using this folio. | |
| 1669 | 1649 | * |
| 1670 | 1650 | * See Documentation/vm/mmu_notifier.rst |
| 1671 | 1651 | */ |
| 1672 | − dec_mm_counter(mm, mm_counter_file(page)); | |
| 1652 | + dec_mm_counter(mm, mm_counter_file(&folio->page)); | |
| 1673 | 1653 | } |
| 1674 | 1654 | discard: |
| 1675 | 1655 | /* |
| @@ -1679,8 +1659,10 @@ discard: · 3 unmodified lines | ||
| 1679 | 1659 | * |
| 1680 | 1660 | * See Documentation/vm/mmu_notifier.rst |
| 1681 | 1661 | */ |
| 1682 | − page_remove_rmap(subpage, PageHuge(page)); | |
| 1683 | − put_page(page); | |
| 1662 | + page_remove_rmap(subpage, vma, folio_test_hugetlb(folio)); | |
| 1663 | + if (vma->vm_flags & VM_LOCKED) | |
| 1664 | + mlock_page_drain(smp_processor_id()); | |
| 1665 | + folio_put(folio); | |
| 1684 | 1666 | } |
| 1685 | 1667 | |
| 1686 | 1668 | mmu_notifier_invalidate_range_end(&range); |
| @@ -1693,35 +1675,35 @@ static bool invalid_migration_vma(struct vm_area_struct *vma, void *arg) · 6 unmodified lines | ||
| 1693 | 1675 | return vma_is_temporary_stack(vma); |
| 1694 | 1676 | } |
| 1695 | 1677 | |
| 1696 | −static int page_not_mapped(struct page *page) | |
| 1678 | +static int page_not_mapped(struct folio *folio) | |
| 1697 | 1679 | { |
| 1698 | − return !page_mapped(page); | |
| 1680 | + return !folio_mapped(folio); | |
| 1699 | 1681 | } |
| 1700 | 1682 | |
| 1701 | 1683 | /** |
| 1702 | − * try_to_unmap - try to remove all page table mappings to a page | |
| 1703 | − * @page: the page to get unmapped | |
| 1684 | + * try_to_unmap - Try to remove all page table mappings to a folio. | |
| 1685 | + * @folio: The folio to unmap. | |
| 1704 | 1686 | * @flags: action and flags |
| 1705 | 1687 | * |
| 1706 | 1688 | * Tries to remove all the page table entries which are mapping this |
| 1707 | − * page, used in the pageout path. Caller must hold the page lock. | |
| 1689 | + * folio. It is the caller's responsibility to check if the folio is | |
| 1690 | + * still mapped if needed (use TTU_SYNC to prevent accounting races). | |
| 1708 | 1691 | * |
| 1709 | − * It is the caller's responsibility to check if the page is still | |
| 1710 | − * mapped when needed (use TTU_SYNC to prevent accounting races). | |
| 1692 | + * Context: Caller must hold the folio lock. | |
| 1711 | 1693 | */ |
| 1712 | −void try_to_unmap(struct page *page, enum ttu_flags flags) | |
| 1694 | +void try_to_unmap(struct folio *folio, enum ttu_flags flags) | |
| 1713 | 1695 | { |
| 1714 | 1696 | struct rmap_walk_control rwc = { |
| 1715 | 1697 | .rmap_one = try_to_unmap_one, |
| 1716 | 1698 | .arg = (void *)flags, |
| 1717 | 1699 | .done = page_not_mapped, |
| 1718 | − .anon_lock = page_lock_anon_vma_read, | |
| 1700 | + .anon_lock = folio_lock_anon_vma_read, | |
| 1719 | 1701 | }; |
| 1720 | 1702 | |
| 1721 | 1703 | if (flags & TTU_RMAP_LOCKED) |
| 1722 | − rmap_walk_locked(page, &rwc); | |
| 1704 | + rmap_walk_locked(folio, &rwc); | |
| 1723 | 1705 | else |
| 1724 | − rmap_walk(page, &rwc); | |
| 1706 | + rmap_walk(folio, &rwc); | |
| 1725 | 1707 | } |
| 1726 | 1708 | |
| 1727 | 1709 | /* |
| @@ -1730,15 +1712,11 @@ void try_to_unmap(struct page *page, enum ttu_flags flags) · 2 unmodified lines | ||
| 1730 | 1712 | * If TTU_SPLIT_HUGE_PMD is specified any PMD mappings will be split into PTEs |
| 1731 | 1713 | * containing migration entries. |
| 1732 | 1714 | */ |
| 1733 | −static bool try_to_migrate_one(struct page *page, struct vm_area_struct *vma, | |
| 1715 | +static bool try_to_migrate_one(struct folio *folio, struct vm_area_struct *vma, | |
| 1734 | 1716 | unsigned long address, void *arg) |
| 1735 | 1717 | { |
| 1736 | 1718 | struct mm_struct *mm = vma->vm_mm; |
| 1737 | − struct page_vma_mapped_walk pvmw = { | |
| 1738 | − .page = page, | |
| 1739 | − .vma = vma, | |
| 1740 | − .address = address, | |
| 1741 | − }; | |
| 1719 | + DEFINE_FOLIO_VMA_WALK(pvmw, folio, vma, address, 0); | |
| 1742 | 1720 | pte_t pteval; |
| 1743 | 1721 | struct page *subpage; |
| 1744 | 1722 | bool ret = true; |
| @@ -1759,7 +1737,7 @@ static bool try_to_migrate_one(struct page *page, struct vm_area_struct *vma, · 14 unmodified lines | ||
| 1759 | 1737 | * TTU_SPLIT_HUGE_PMD and it wants to freeze. |
| 1760 | 1738 | */ |
| 1761 | 1739 | if (flags & TTU_SPLIT_HUGE_PMD) |
| 1762 | − split_huge_pmd_address(vma, address, true, page); | |
| 1740 | + split_huge_pmd_address(vma, address, true, folio); | |
| 1763 | 1741 | |
| 1764 | 1742 | /* |
| 1765 | 1743 | * For THP, we have to assume the worse case ie pmd for invalidation. |
| @@ -1769,11 +1747,10 @@ static bool try_to_migrate_one(struct page *page, struct vm_area_struct *vma, · 3 unmodified lines | ||
| 1769 | 1747 | * Note that the page can not be free in this function as call of |
| 1770 | 1748 | * try_to_unmap() must hold a reference on the page. |
| 1771 | 1749 | */ |
| 1772 | − range.end = PageKsm(page) ? | |
| 1773 | − address + PAGE_SIZE : vma_address_end(page, vma); | |
| 1750 | + range.end = vma_address_end(&pvmw); | |
| 1774 | 1751 | mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, vma->vm_mm, |
| 1775 | 1752 | address, range.end); |
| 1776 | − if (PageHuge(page)) { | |
| 1753 | + if (folio_test_hugetlb(folio)) { | |
| 1777 | 1754 | /* |
| 1778 | 1755 | * If sharing is possible, start and end will be adjusted |
| 1779 | 1756 | * accordingly. |
| @@ -1787,21 +1764,24 @@ static bool try_to_migrate_one(struct page *page, struct vm_area_struct *vma, · 7 unmodified lines | ||
| 1787 | 1764 | #ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION |
| 1788 | 1765 | /* PMD-mapped THP migration entry */ |
| 1789 | 1766 | if (!pvmw.pte) { |
| 1790 | − VM_BUG_ON_PAGE(PageHuge(page) || | |
| 1791 | − !PageTransCompound(page), page); | |
| 1767 | + subpage = folio_page(folio, | |
| 1768 | + pmd_pfn(*pvmw.pmd) - folio_pfn(folio)); | |
| 1769 | + VM_BUG_ON_FOLIO(folio_test_hugetlb(folio) || | |
| 1770 | + !folio_test_pmd_mappable(folio), folio); | |
| 1792 | 1771 | |
| 1793 | − set_pmd_migration_entry(&pvmw, page); | |
| 1772 | + set_pmd_migration_entry(&pvmw, subpage); | |
| 1794 | 1773 | continue; |
| 1795 | 1774 | } |
| 1796 | 1775 | #endif |
| 1797 | 1776 | |
| 1798 | 1777 | /* Unexpected PMD-mapped THP? */ |
| 1799 | − VM_BUG_ON_PAGE(!pvmw.pte, page); | |
| 1778 | + VM_BUG_ON_FOLIO(!pvmw.pte, folio); | |
| 1800 | 1779 | |
| 1801 | − subpage = page - page_to_pfn(page) + pte_pfn(*pvmw.pte); | |
| 1780 | + subpage = folio_page(folio, | |
| 1781 | + pte_pfn(*pvmw.pte) - folio_pfn(folio)); | |
| 1802 | 1782 | address = pvmw.address; |
| 1803 | 1783 | |
| 1804 | − if (PageHuge(page) && !PageAnon(page)) { | |
| 1784 | + if (folio_test_hugetlb(folio) && !folio_test_anon(folio)) { | |
| 1805 | 1785 | /* |
| 1806 | 1786 | * To call huge_pmd_unshare, i_mmap_rwsem must be |
| 1807 | 1787 | * held in write mode. Caller needs to explicitly |
| @@ -1839,15 +1819,15 @@ static bool try_to_migrate_one(struct page *page, struct vm_area_struct *vma, · 31 unmodified lines | ||
| 1839 | 1819 | flush_cache_page(vma, address, pte_pfn(*pvmw.pte)); |
| 1840 | 1820 | pteval = ptep_clear_flush(vma, address, pvmw.pte); |
| 1841 | 1821 | |
| 1842 | − /* Move the dirty bit to the page. Now the pte is gone. */ | |
| 1822 | + /* Set the dirty flag on the folio now the pte is gone. */ | |
| 1843 | 1823 | if (pte_dirty(pteval)) |
| 1844 | − set_page_dirty(page); | |
| 1824 | + folio_mark_dirty(folio); | |
| 1845 | 1825 | |
| 1846 | 1826 | /* Update high watermark before we lower rss */ |
| 1847 | 1827 | update_hiwater_rss(mm); |
| 1848 | 1828 | |
| 1849 | − if (is_zone_device_page(page)) { | |
| 1850 | − unsigned long pfn = page_to_pfn(page); | |
| 1829 | + if (folio_is_zone_device(folio)) { | |
| 1830 | + unsigned long pfn = folio_pfn(folio); | |
| 1851 | 1831 | swp_entry_t entry; |
| 1852 | 1832 | pte_t swp_pte; |
| 1853 | 1833 | |
| @@ -1883,16 +1863,16 @@ static bool try_to_migrate_one(struct page *page, struct vm_area_struct *vma, · 29 unmodified lines | ||
| 1883 | 1863 | * changed when hugepage migrations to device private |
| 1884 | 1864 | * memory are supported. |
| 1885 | 1865 | */ |
| 1886 | − subpage = page; | |
| 1866 | + subpage = &folio->page; | |
| 1887 | 1867 | } else if (PageHWPoison(subpage)) { |
| 1888 | 1868 | pteval = swp_entry_to_pte(make_hwpoison_entry(subpage)); |
| 1889 | − if (PageHuge(page)) { | |
| 1890 | − hugetlb_count_sub(compound_nr(page), mm); | |
| 1869 | + if (folio_test_hugetlb(folio)) { | |
| 1870 | + hugetlb_count_sub(folio_nr_pages(folio), mm); | |
| 1891 | 1871 | set_huge_swap_pte_at(mm, address, |
| 1892 | 1872 | pvmw.pte, pteval, |
| 1893 | 1873 | vma_mmu_pagesize(vma)); |
| 1894 | 1874 | } else { |
| 1895 | − dec_mm_counter(mm, mm_counter(page)); | |
| 1875 | + dec_mm_counter(mm, mm_counter(&folio->page)); | |
| 1896 | 1876 | set_pte_at(mm, address, pvmw.pte, pteval); |
| 1897 | 1877 | } |
| 1898 | 1878 | |
| @@ -1907,7 +1887,7 @@ static bool try_to_migrate_one(struct page *page, struct vm_area_struct *vma, · 8 unmodified lines | ||
| 1907 | 1887 | * migration) will not expect userfaults on already |
| 1908 | 1888 | * copied pages. |
| 1909 | 1889 | */ |
| 1910 | − dec_mm_counter(mm, mm_counter(page)); | |
| 1890 | + dec_mm_counter(mm, mm_counter(&folio->page)); | |
| 1911 | 1891 | /* We have to invalidate as we cleared the pte */ |
| 1912 | 1892 | mmu_notifier_invalidate_range(mm, address, |
| 1913 | 1893 | address + PAGE_SIZE); |
| @@ -1953,8 +1933,10 @@ static bool try_to_migrate_one(struct page *page, struct vm_area_struct *vma, · 39 unmodified lines | ||
| 1953 | 1933 | * |
| 1954 | 1934 | * See Documentation/vm/mmu_notifier.rst |
| 1955 | 1935 | */ |
| 1956 | − page_remove_rmap(subpage, PageHuge(page)); | |
| 1957 | − put_page(page); | |
| 1936 | + page_remove_rmap(subpage, vma, folio_test_hugetlb(folio)); | |
| 1937 | + if (vma->vm_flags & VM_LOCKED) | |
| 1938 | + mlock_page_drain(smp_processor_id()); | |
| 1939 | + folio_put(folio); | |
| 1958 | 1940 | } |
| 1959 | 1941 | |
| 1960 | 1942 | mmu_notifier_invalidate_range_end(&range); |
| @@ -1964,19 +1946,19 @@ static bool try_to_migrate_one(struct page *page, struct vm_area_struct *vma, · 3 unmodified lines | ||
| 1964 | 1946 | |
| 1965 | 1947 | /** |
| 1966 | 1948 | * try_to_migrate - try to replace all page table mappings with swap entries |
| 1967 | − * @page: the page to replace page table entries for | |
| 1949 | + * @folio: the folio to replace page table entries for | |
| 1968 | 1950 | * @flags: action and flags |
| 1969 | 1951 | * |
| 1970 | − * Tries to remove all the page table entries which are mapping this page and | |
| 1971 | − * replace them with special swap entries. Caller must hold the page lock. | |
| 1952 | + * Tries to remove all the page table entries which are mapping this folio and | |
| 1953 | + * replace them with special swap entries. Caller must hold the folio lock. | |
| 1972 | 1954 | */ |
| 1973 | −void try_to_migrate(struct page *page, enum ttu_flags flags) | |
| 1955 | +void try_to_migrate(struct folio *folio, enum ttu_flags flags) | |
| 1974 | 1956 | { |
| 1975 | 1957 | struct rmap_walk_control rwc = { |
| 1976 | 1958 | .rmap_one = try_to_migrate_one, |
| 1977 | 1959 | .arg = (void *)flags, |
| 1978 | 1960 | .done = page_not_mapped, |
| 1979 | − .anon_lock = page_lock_anon_vma_read, | |
| 1961 | + .anon_lock = folio_lock_anon_vma_read, | |
| 1980 | 1962 | }; |
| 1981 | 1963 | |
| 1982 | 1964 | /* |
| @@ -1987,7 +1969,7 @@ void try_to_migrate(struct page *page, enum ttu_flags flags) · 4 unmodified lines | ||
| 1987 | 1969 | TTU_SYNC))) |
| 1988 | 1970 | return; |
| 1989 | 1971 | |
| 1990 | − if (is_zone_device_page(page) && !is_device_private_page(page)) | |
| 1972 | + if (folio_is_zone_device(folio) && !folio_is_device_private(folio)) | |
| 1991 | 1973 | return; |
| 1992 | 1974 | |
| 1993 | 1975 | /* |
| @@ -1998,83 +1980,13 @@ void try_to_migrate(struct page *page, enum ttu_flags flags) · 4 unmodified lines | ||
| 1998 | 1980 | * locking requirements of exec(), migration skips |
| 1999 | 1981 | * temporary VMAs until after exec() completes. |
| 2000 | 1982 | */ |
| 2001 | − if (!PageKsm(page) && PageAnon(page)) | |
| 1983 | + if (!folio_test_ksm(folio) && folio_test_anon(folio)) | |
| 2002 | 1984 | rwc.invalid_vma = invalid_migration_vma; |
| 2003 | 1985 | |
| 2004 | 1986 | if (flags & TTU_RMAP_LOCKED) |
| 2005 | − rmap_walk_locked(page, &rwc); | |
| 1987 | + rmap_walk_locked(folio, &rwc); | |
| 2006 | 1988 | else |
| 2007 | − rmap_walk(page, &rwc); | |
| 2008 | −} | |
| 2009 | − | |
| 2010 | −/* | |
| 2011 | − * Walks the vma's mapping a page and mlocks the page if any locked vma's are | |
| 2012 | − * found. Once one is found the page is locked and the scan can be terminated. | |
| 2013 | − */ | |
| 2014 | −static bool page_mlock_one(struct page *page, struct vm_area_struct *vma, | |
| 2015 | − unsigned long address, void *unused) | |
| 2016 | −{ | |
| 2017 | − struct page_vma_mapped_walk pvmw = { | |
| 2018 | − .page = page, | |
| 2019 | − .vma = vma, | |
| 2020 | − .address = address, | |
| 2021 | − }; | |
| 2022 | − | |
| 2023 | − /* An un-locked vma doesn't have any pages to lock, continue the scan */ | |
| 2024 | − if (!(vma->vm_flags & VM_LOCKED)) | |
| 2025 | − return true; | |
| 2026 | − | |
| 2027 | − while (page_vma_mapped_walk(&pvmw)) { | |
| 2028 | − /* | |
| 2029 | − * Need to recheck under the ptl to serialise with | |
| 2030 | − * __munlock_pagevec_fill() after VM_LOCKED is cleared in | |
| 2031 | − * munlock_vma_pages_range(). | |
| 2032 | − */ | |
| 2033 | − if (vma->vm_flags & VM_LOCKED) { | |
| 2034 | − /* | |
| 2035 | − * PTE-mapped THP are never marked as mlocked; but | |
| 2036 | − * this function is never called on a DoubleMap THP, | |
| 2037 | − * nor on an Anon THP (which may still be PTE-mapped | |
| 2038 | − * after DoubleMap was cleared). | |
| 2039 | − */ | |
| 2040 | − mlock_vma_page(page); | |
| 2041 | − /* | |
| 2042 | − * No need to scan further once the page is marked | |
| 2043 | − * as mlocked. | |
| 2044 | − */ | |
| 2045 | − page_vma_mapped_walk_done(&pvmw); | |
| 2046 | − return false; | |
| 2047 | − } | |
| 2048 | − } | |
| 2049 | − | |
| 2050 | − return true; | |
| 2051 | −} | |
| 2052 | − | |
| 2053 | −/** | |
| 2054 | − * page_mlock - try to mlock a page | |
| 2055 | − * @page: the page to be mlocked | |
| 2056 | − * | |
| 2057 | − * Called from munlock code. Checks all of the VMAs mapping the page and mlocks | |
| 2058 | − * the page if any are found. The page will be returned with PG_mlocked cleared | |
| 2059 | − * if it is not mapped by any locked vmas. | |
| 2060 | − */ | |
| 2061 | −void page_mlock(struct page *page) | |
| 2062 | −{ | |
| 2063 | − struct rmap_walk_control rwc = { | |
| 2064 | − .rmap_one = page_mlock_one, | |
| 2065 | − .done = page_not_mapped, | |
| 2066 | − .anon_lock = page_lock_anon_vma_read, | |
| 2067 | − | |
| 2068 | − }; | |
| 2069 | − | |
| 2070 | − VM_BUG_ON_PAGE(!PageLocked(page) || PageLRU(page), page); | |
| 2071 | − VM_BUG_ON_PAGE(PageCompound(page) && PageDoubleMap(page), page); | |
| 2072 | − | |
| 2073 | − /* Anon THP are only marked as mlocked when singly mapped */ | |
| 2074 | − if (PageTransCompound(page) && PageAnon(page)) | |
| 2075 | − return; | |
| 2076 | − | |
| 2077 | − rmap_walk(page, &rwc); | |
| 1989 | + rmap_walk(folio, &rwc); | |
| 2078 | 1990 | } |
| 2079 | 1991 | |
| 2080 | 1992 | #ifdef CONFIG_DEVICE_PRIVATE |
| @@ -2085,15 +1997,11 @@ struct make_exclusive_args { · 4 unmodified lines | ||
| 2085 | 1997 | bool valid; |
| 2086 | 1998 | }; |
| 2087 | 1999 | |
| 2088 | −static bool page_make_device_exclusive_one(struct page *page, | |
| 2000 | +static bool page_make_device_exclusive_one(struct folio *folio, | |
| 2089 | 2001 | struct vm_area_struct *vma, unsigned long address, void *priv) |
| 2090 | 2002 | { |
| 2091 | 2003 | struct mm_struct *mm = vma->vm_mm; |
| 2092 | − struct page_vma_mapped_walk pvmw = { | |
| 2093 | − .page = page, | |
| 2094 | − .vma = vma, | |
| 2095 | − .address = address, | |
| 2096 | − }; | |
| 2004 | + DEFINE_FOLIO_VMA_WALK(pvmw, folio, vma, address, 0); | |
| 2097 | 2005 | struct make_exclusive_args *args = priv; |
| 2098 | 2006 | pte_t pteval; |
| 2099 | 2007 | struct page *subpage; |
| @@ -2104,12 +2012,13 @@ static bool page_make_device_exclusive_one(struct page *page, · 4 unmodified lines | ||
| 2104 | 2012 | |
| 2105 | 2013 | mmu_notifier_range_init_owner(&range, MMU_NOTIFY_EXCLUSIVE, 0, vma, |
| 2106 | 2014 | vma->vm_mm, address, min(vma->vm_end, |
| 2107 | − address + page_size(page)), args->owner); | |
| 2015 | + address + folio_size(folio)), | |
| 2016 | + args->owner); | |
| 2108 | 2017 | mmu_notifier_invalidate_range_start(&range); |
| 2109 | 2018 | |
| 2110 | 2019 | while (page_vma_mapped_walk(&pvmw)) { |
| 2111 | 2020 | /* Unexpected PMD-mapped THP? */ |
| 2112 | − VM_BUG_ON_PAGE(!pvmw.pte, page); | |
| 2021 | + VM_BUG_ON_FOLIO(!pvmw.pte, folio); | |
| 2113 | 2022 | |
| 2114 | 2023 | if (!pte_present(*pvmw.pte)) { |
| 2115 | 2024 | ret = false; |
| @@ -2117,16 +2026,17 @@ static bool page_make_device_exclusive_one(struct page *page, · 1 unmodified line | ||
| 2117 | 2026 | break; |
| 2118 | 2027 | } |
| 2119 | 2028 | |
| 2120 | − subpage = page - page_to_pfn(page) + pte_pfn(*pvmw.pte); | |
| 2029 | + subpage = folio_page(folio, | |
| 2030 | + pte_pfn(*pvmw.pte) - folio_pfn(folio)); | |
| 2121 | 2031 | address = pvmw.address; |
| 2122 | 2032 | |
| 2123 | 2033 | /* Nuke the page table entry. */ |
| 2124 | 2034 | flush_cache_page(vma, address, pte_pfn(*pvmw.pte)); |
| 2125 | 2035 | pteval = ptep_clear_flush(vma, address, pvmw.pte); |
| 2126 | 2036 | |
| 2127 | − /* Move the dirty bit to the page. Now the pte is gone. */ | |
| 2037 | + /* Set the dirty flag on the folio now the pte is gone. */ | |
| 2128 | 2038 | if (pte_dirty(pteval)) |
| 2129 | − set_page_dirty(page); | |
| 2039 | + folio_mark_dirty(folio); | |
| 2130 | 2040 | |
| 2131 | 2041 | /* |
| 2132 | 2042 | * Check that our target page is still mapped at the expected |
| @@ -2159,7 +2069,7 @@ static bool page_make_device_exclusive_one(struct page *page, · 26 unmodified lines | ||
| 2159 | 2069 | * There is a reference on the page for the swap entry which has |
| 2160 | 2070 | * been removed, so shouldn't take another. |
| 2161 | 2071 | */ |
| 2162 | − page_remove_rmap(subpage, false); | |
| 2072 | + page_remove_rmap(subpage, vma, false); | |
| 2163 | 2073 | } |
| 2164 | 2074 | |
| 2165 | 2075 | mmu_notifier_invalidate_range_end(&range); |
| @@ -2168,21 +2078,22 @@ static bool page_make_device_exclusive_one(struct page *page, · 2 unmodified lines | ||
| 2168 | 2078 | } |
| 2169 | 2079 | |
| 2170 | 2080 | /** |
| 2171 | − * page_make_device_exclusive - mark the page exclusively owned by a device | |
| 2172 | − * @page: the page to replace page table entries for | |
| 2173 | − * @mm: the mm_struct where the page is expected to be mapped | |
| 2174 | − * @address: address where the page is expected to be mapped | |
| 2081 | + * folio_make_device_exclusive - Mark the folio exclusively owned by a device. | |
| 2082 | + * @folio: The folio to replace page table entries for. | |
| 2083 | + * @mm: The mm_struct where the folio is expected to be mapped. | |
| 2084 | + * @address: Address where the folio is expected to be mapped. | |
| 2175 | 2085 | * @owner: passed to MMU_NOTIFY_EXCLUSIVE range notifier callbacks |
| 2176 | 2086 | * |
| 2177 | − * Tries to remove all the page table entries which are mapping this page and | |
| 2178 | − * replace them with special device exclusive swap entries to grant a device | |
| 2179 | − * exclusive access to the page. Caller must hold the page lock. | |
| 2087 | + * Tries to remove all the page table entries which are mapping this | |
| 2088 | + * folio and replace them with special device exclusive swap entries to | |
| 2089 | + * grant a device exclusive access to the folio. | |
| 2180 | 2090 | * |
| 2181 | − * Returns false if the page is still mapped, or if it could not be unmapped | |
| 2091 | + * Context: Caller must hold the folio lock. | |
| 2092 | + * Return: false if the page is still mapped, or if it could not be unmapped | |
| 2182 | 2093 | * from the expected address. Otherwise returns true (success). |
| 2183 | 2094 | */ |
| 2184 | −static bool page_make_device_exclusive(struct page *page, struct mm_struct *mm, | |
| 2185 | − unsigned long address, void *owner) | |
| 2095 | +static bool folio_make_device_exclusive(struct folio *folio, | |
| 2096 | + struct mm_struct *mm, unsigned long address, void *owner) | |
| 2186 | 2097 | { |
| 2187 | 2098 | struct make_exclusive_args args = { |
| 2188 | 2099 | .mm = mm, |
| @@ -2193,21 +2104,20 @@ static bool page_make_device_exclusive(struct page *page, struct mm_struct *mm, · 4 unmodified lines | ||
| 2193 | 2104 | struct rmap_walk_control rwc = { |
| 2194 | 2105 | .rmap_one = page_make_device_exclusive_one, |
| 2195 | 2106 | .done = page_not_mapped, |
| 2196 | − .anon_lock = page_lock_anon_vma_read, | |
| 2107 | + .anon_lock = folio_lock_anon_vma_read, | |
| 2197 | 2108 | .arg = &args, |
| 2198 | 2109 | }; |
| 2199 | 2110 | |
| 2200 | 2111 | /* |
| 2201 | − * Restrict to anonymous pages for now to avoid potential writeback | |
| 2202 | − * issues. Also tail pages shouldn't be passed to rmap_walk so skip | |
| 2203 | − * those. | |
| 2112 | + * Restrict to anonymous folios for now to avoid potential writeback | |
| 2113 | + * issues. | |
| 2204 | 2114 | */ |
| 2205 | − if (!PageAnon(page) || PageTail(page)) | |
| 2115 | + if (!folio_test_anon(folio)) | |
| 2206 | 2116 | return false; |
| 2207 | 2117 | |
| 2208 | − rmap_walk(page, &rwc); | |
| 2118 | + rmap_walk(folio, &rwc); | |
| 2209 | 2119 | |
| 2210 | − return args.valid && !page_mapcount(page); | |
| 2120 | + return args.valid && !folio_mapcount(folio); | |
| 2211 | 2121 | } |
| 2212 | 2122 | |
| 2213 | 2123 | /** |
| @@ -2245,15 +2155,16 @@ int make_device_exclusive_range(struct mm_struct *mm, unsigned long start, · 31 unmodified lines | ||
| 2245 | 2155 | return npages; |
| 2246 | 2156 | |
| 2247 | 2157 | for (i = 0; i < npages; i++, start += PAGE_SIZE) { |
| 2248 | − if (!trylock_page(pages[i])) { | |
| 2249 | − put_page(pages[i]); | |
| 2158 | + struct folio *folio = page_folio(pages[i]); | |
| 2159 | + if (PageTail(pages[i]) || !folio_trylock(folio)) { | |
| 2160 | + folio_put(folio); | |
| 2250 | 2161 | pages[i] = NULL; |
| 2251 | 2162 | continue; |
| 2252 | 2163 | } |
| 2253 | 2164 | |
| 2254 | − if (!page_make_device_exclusive(pages[i], mm, start, owner)) { | |
| 2255 | − unlock_page(pages[i]); | |
| 2256 | − put_page(pages[i]); | |
| 2165 | + if (!folio_make_device_exclusive(folio, mm, start, owner)) { | |
| 2166 | + folio_unlock(folio); | |
| 2167 | + folio_put(folio); | |
| 2257 | 2168 | pages[i] = NULL; |
| 2258 | 2169 | } |
| 2259 | 2170 | } |
| @@ -2272,21 +2183,21 @@ void __put_anon_vma(struct anon_vma *anon_vma) · 12 unmodified lines | ||
| 2272 | 2183 | anon_vma_free(root); |
| 2273 | 2184 | } |
| 2274 | 2185 | |
| 2275 | −static struct anon_vma *rmap_walk_anon_lock(struct page *page, | |
| 2276 | − struct rmap_walk_control *rwc) | |
| 2186 | +static struct anon_vma *rmap_walk_anon_lock(struct folio *folio, | |
| 2187 | + const struct rmap_walk_control *rwc) | |
| 2277 | 2188 | { |
| 2278 | 2189 | struct anon_vma *anon_vma; |
| 2279 | 2190 | |
| 2280 | 2191 | if (rwc->anon_lock) |
| 2281 | − return rwc->anon_lock(page); | |
| 2192 | + return rwc->anon_lock(folio); | |
| 2282 | 2193 | |
| 2283 | 2194 | /* |
| 2284 | − * Note: remove_migration_ptes() cannot use page_lock_anon_vma_read() | |
| 2195 | + * Note: remove_migration_ptes() cannot use folio_lock_anon_vma_read() | |
| 2285 | 2196 | * because that depends on page_mapped(); but not all its usages |
| 2286 | 2197 | * are holding mmap_lock. Users without mmap_lock are required to |
| 2287 | 2198 | * take a reference count to prevent the anon_vma disappearing |
| 2288 | 2199 | */ |
| 2289 | − anon_vma = page_anon_vma(page); | |
| 2200 | + anon_vma = folio_anon_vma(folio); | |
| 2290 | 2201 | if (!anon_vma) |
| 2291 | 2202 | return NULL; |
| 2292 | 2203 | |
| @@ -2302,35 +2213,30 @@ static struct anon_vma *rmap_walk_anon_lock(struct page *page, · 9 unmodified lines | ||
| 2302 | 2213 | * |
| 2303 | 2214 | * Find all the mappings of a page using the mapping pointer and the vma chains |
| 2304 | 2215 | * contained in the anon_vma struct it points to. |
| 2305 | − * | |
| 2306 | − * When called from page_mlock(), the mmap_lock of the mm containing the vma | |
| 2307 | − * where the page was found will be held for write. So, we won't recheck | |
| 2308 | − * vm_flags for that VMA. That should be OK, because that vma shouldn't be | |
| 2309 | − * LOCKED. | |
| 2310 | 2216 | */ |
| 2311 | −static void rmap_walk_anon(struct page *page, struct rmap_walk_control *rwc, | |
| 2312 | − bool locked) | |
| 2217 | +static void rmap_walk_anon(struct folio *folio, | |
| 2218 | + const struct rmap_walk_control *rwc, bool locked) | |
| 2313 | 2219 | { |
| 2314 | 2220 | struct anon_vma *anon_vma; |
| 2315 | 2221 | pgoff_t pgoff_start, pgoff_end; |
| 2316 | 2222 | struct anon_vma_chain *avc; |
| 2317 | 2223 | |
| 2318 | 2224 | if (locked) { |
| 2319 | − anon_vma = page_anon_vma(page); | |
| 2225 | + anon_vma = folio_anon_vma(folio); | |
| 2320 | 2226 | /* anon_vma disappear under us? */ |
| 2321 | − VM_BUG_ON_PAGE(!anon_vma, page); | |
| 2227 | + VM_BUG_ON_FOLIO(!anon_vma, folio); | |
| 2322 | 2228 | } else { |
| 2323 | − anon_vma = rmap_walk_anon_lock(page, rwc); | |
| 2229 | + anon_vma = rmap_walk_anon_lock(folio, rwc); | |
| 2324 | 2230 | } |
| 2325 | 2231 | if (!anon_vma) |
| 2326 | 2232 | return; |
| 2327 | 2233 | |
| 2328 | − pgoff_start = page_to_pgoff(page); | |
| 2329 | − pgoff_end = pgoff_start + thp_nr_pages(page) - 1; | |
| 2234 | + pgoff_start = folio_pgoff(folio); | |
| 2235 | + pgoff_end = pgoff_start + folio_nr_pages(folio) - 1; | |
| 2330 | 2236 | anon_vma_interval_tree_foreach(avc, &anon_vma->rb_root, |
| 2331 | 2237 | pgoff_start, pgoff_end) { |
| 2332 | 2238 | struct vm_area_struct *vma = avc->vma; |
| 2333 | − unsigned long address = vma_address(page, vma); | |
| 2239 | + unsigned long address = vma_address(&folio->page, vma); | |
| 2334 | 2240 | |
| 2335 | 2241 | VM_BUG_ON_VMA(address == -EFAULT, vma); |
| 2336 | 2242 | cond_resched(); |
| @@ -2338,9 +2244,9 @@ static void rmap_walk_anon(struct page *page, struct rmap_walk_control *rwc, · 1 unmodified line | ||
| 2338 | 2244 | if (rwc->invalid_vma && rwc->invalid_vma(vma, rwc->arg)) |
| 2339 | 2245 | continue; |
| 2340 | 2246 | |
| 2341 | − if (!rwc->rmap_one(page, vma, address, rwc->arg)) | |
| 2247 | + if (!rwc->rmap_one(folio, vma, address, rwc->arg)) | |
| 2342 | 2248 | break; |
| 2343 | − if (rwc->done && rwc->done(page)) | |
| 2249 | + if (rwc->done && rwc->done(folio)) | |
| 2344 | 2250 | break; |
| 2345 | 2251 | } |
| 2346 | 2252 | |
| @@ -2355,16 +2261,11 @@ static void rmap_walk_anon(struct page *page, struct rmap_walk_control *rwc, · 8 unmodified lines | ||
| 2355 | 2261 | * |
| 2356 | 2262 | * Find all the mappings of a page using the mapping pointer and the vma chains |
| 2357 | 2263 | * contained in the address_space struct it points to. |
| 2358 | − * | |
| 2359 | − * When called from page_mlock(), the mmap_lock of the mm containing the vma | |
| 2360 | − * where the page was found will be held for write. So, we won't recheck | |
| 2361 | − * vm_flags for that VMA. That should be OK, because that vma shouldn't be | |
| 2362 | − * LOCKED. | |
| 2363 | 2264 | */ |
| 2364 | −static void rmap_walk_file(struct page *page, struct rmap_walk_control *rwc, | |
| 2365 | − bool locked) | |
| 2265 | +static void rmap_walk_file(struct folio *folio, | |
| 2266 | + const struct rmap_walk_control *rwc, bool locked) | |
| 2366 | 2267 | { |
| 2367 | − struct address_space *mapping = page_mapping(page); | |
| 2268 | + struct address_space *mapping = folio_mapping(folio); | |
| 2368 | 2269 | pgoff_t pgoff_start, pgoff_end; |
| 2369 | 2270 | struct vm_area_struct *vma; |
| 2370 | 2271 | |
| @@ -2374,18 +2275,18 @@ static void rmap_walk_file(struct page *page, struct rmap_walk_control *rwc, · 3 unmodified lines | ||
| 2374 | 2275 | * structure at mapping cannot be freed and reused yet, |
| 2375 | 2276 | * so we can safely take mapping->i_mmap_rwsem. |
| 2376 | 2277 | */ |
| 2377 | − VM_BUG_ON_PAGE(!PageLocked(page), page); | |
| 2278 | + VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio); | |
| 2378 | 2279 | |
| 2379 | 2280 | if (!mapping) |
| 2380 | 2281 | return; |
| 2381 | 2282 | |
| 2382 | − pgoff_start = page_to_pgoff(page); | |
| 2383 | − pgoff_end = pgoff_start + thp_nr_pages(page) - 1; | |
| 2283 | + pgoff_start = folio_pgoff(folio); | |
| 2284 | + pgoff_end = pgoff_start + folio_nr_pages(folio) - 1; | |
| 2384 | 2285 | if (!locked) |
| 2385 | 2286 | i_mmap_lock_read(mapping); |
| 2386 | 2287 | vma_interval_tree_foreach(vma, &mapping->i_mmap, |
| 2387 | 2288 | pgoff_start, pgoff_end) { |
| 2388 | − unsigned long address = vma_address(page, vma); | |
| 2289 | + unsigned long address = vma_address(&folio->page, vma); | |
| 2389 | 2290 | |
| 2390 | 2291 | VM_BUG_ON_VMA(address == -EFAULT, vma); |
| 2391 | 2292 | cond_resched(); |
| @@ -2393,9 +2294,9 @@ static void rmap_walk_file(struct page *page, struct rmap_walk_control *rwc, · 1 unmodified line | ||
| 2393 | 2294 | if (rwc->invalid_vma && rwc->invalid_vma(vma, rwc->arg)) |
| 2394 | 2295 | continue; |
| 2395 | 2296 | |
| 2396 | − if (!rwc->rmap_one(page, vma, address, rwc->arg)) | |
| 2297 | + if (!rwc->rmap_one(folio, vma, address, rwc->arg)) | |
| 2397 | 2298 | goto done; |
| 2398 | − if (rwc->done && rwc->done(page)) | |
| 2299 | + if (rwc->done && rwc->done(folio)) | |
| 2399 | 2300 | goto done; |
| 2400 | 2301 | } |
| 2401 | 2302 | |
| @@ -2404,25 +2305,25 @@ done: · 2 unmodified lines | ||
| 2404 | 2305 | i_mmap_unlock_read(mapping); |
| 2405 | 2306 | } |
| 2406 | 2307 | |
| 2407 | −void rmap_walk(struct page *page, struct rmap_walk_control *rwc) | |
| 2308 | +void rmap_walk(struct folio *folio, const struct rmap_walk_control *rwc) | |
| 2408 | 2309 | { |
| 2409 | − if (unlikely(PageKsm(page))) | |
| 2410 | − rmap_walk_ksm(page, rwc); | |
| 2411 | − else if (PageAnon(page)) | |
| 2412 | − rmap_walk_anon(page, rwc, false); | |
| 2310 | + if (unlikely(folio_test_ksm(folio))) | |
| 2311 | + rmap_walk_ksm(folio, rwc); | |
| 2312 | + else if (folio_test_anon(folio)) | |
| 2313 | + rmap_walk_anon(folio, rwc, false); | |
| 2413 | 2314 | else |
| 2414 | − rmap_walk_file(page, rwc, false); | |
| 2315 | + rmap_walk_file(folio, rwc, false); | |
| 2415 | 2316 | } |
| 2416 | 2317 | |
| 2417 | 2318 | /* Like rmap_walk, but caller holds relevant rmap lock */ |
| 2418 | −void rmap_walk_locked(struct page *page, struct rmap_walk_control *rwc) | |
| 2319 | +void rmap_walk_locked(struct folio *folio, const struct rmap_walk_control *rwc) | |
| 2419 | 2320 | { |
| 2420 | 2321 | /* no ksm support for now */ |
| 2421 | − VM_BUG_ON_PAGE(PageKsm(page), page); | |
| 2422 | − if (PageAnon(page)) | |
| 2423 | − rmap_walk_anon(page, rwc, true); | |
| 2322 | + VM_BUG_ON_FOLIO(folio_test_ksm(folio), folio); | |
| 2323 | + if (folio_test_anon(folio)) | |
| 2324 | + rmap_walk_anon(folio, rwc, true); | |
| 2424 | 2325 | else |
| 2425 | − rmap_walk_file(page, rwc, true); | |
| 2326 | + rmap_walk_file(folio, rwc, true); | |
| 2426 | 2327 | } |
| 2427 | 2328 | |
| 2428 | 2329 | #ifdef CONFIG_HUGETLB_PAGE |
| @@ -2450,8 +2351,7 @@ void hugepage_add_new_anon_rmap(struct page *page, · 21 unmodified lines | ||
| 2450 | 2351 | { |
| 2451 | 2352 | BUG_ON(address < vma->vm_start || address >= vma->vm_end); |
| 2452 | 2353 | atomic_set(compound_mapcount_ptr(page), 0); |
| 2453 | − if (hpage_pincount_available(page)) | |
| 2454 | − atomic_set(compound_pincount_ptr(page), 0); | |
| 2354 | + atomic_set(compound_pincount_ptr(page), 0); | |
| 2455 | 2355 | |
| 2456 | 2356 | __page_set_anon_rmap(page, vma, address, 1); |
| 2457 | 2357 | } |
| @@ -74,8 +74,8 @@ static DEFINE_PER_CPU(struct lru_pvecs, lru_pvecs) = { · 73 unmodified lines | ||
| 74 | 74 | }; |
| 75 | 75 | |
| 76 | 76 | /* |
| 77 | − * This path almost never happens for VM activity - pages are normally | |
| 78 | − * freed via pagevecs. But it gets used by networking. | |
| 77 | + * This path almost never happens for VM activity - pages are normally freed | |
| 78 | + * via pagevecs. But it gets used by networking - and for compound pages. | |
| 79 | 79 | */ |
| 80 | 80 | static void __page_cache_release(struct page *page) |
| 81 | 81 | { |
| @@ -89,6 +89,14 @@ static void __page_cache_release(struct page *page) · 7 unmodified lines | ||
| 89 | 89 | __clear_page_lru_flags(page); |
| 90 | 90 | unlock_page_lruvec_irqrestore(lruvec, flags); |
| 91 | 91 | } |
| 92 | + /* See comment on PageMlocked in release_pages() */ | |
| 93 | + if (unlikely(PageMlocked(page))) { | |
| 94 | + int nr_pages = thp_nr_pages(page); | |
| 95 | + | |
| 96 | + __ClearPageMlocked(page); | |
| 97 | + mod_zone_page_state(page_zone(page), NR_MLOCK, -nr_pages); | |
| 98 | + count_vm_events(UNEVICTABLE_PGCLEARED, nr_pages); | |
| 99 | + } | |
| 92 | 100 | __ClearPageWaiters(page); |
| 93 | 101 | } |
| 94 | 102 | |
| @@ -114,17 +122,9 @@ static void __put_compound_page(struct page *page) · 19 unmodified lines | ||
| 114 | 122 | |
| 115 | 123 | void __put_page(struct page *page) |
| 116 | 124 | { |
| 117 | − if (is_zone_device_page(page)) { | |
| 118 | − put_dev_pagemap(page->pgmap); | |
| 119 | − | |
| 120 | − /* | |
| 121 | − * The page belongs to the device that created pgmap. Do | |
| 122 | − * not return it to page allocator. | |
| 123 | − */ | |
| 124 | − return; | |
| 125 | − } | |
| 126 | − | |
| 127 | − if (unlikely(PageCompound(page))) | |
| 125 | + if (unlikely(is_zone_device_page(page))) | |
| 126 | + free_zone_device_page(page); | |
| 127 | + else if (unlikely(PageCompound(page))) | |
| 128 | 128 | __put_compound_page(page); |
| 129 | 129 | else |
| 130 | 130 | __put_single_page(page); |
| @@ -482,22 +482,12 @@ EXPORT_SYMBOL(folio_add_lru); · 351 unmodified lines | ||
| 482 | 482 | void lru_cache_add_inactive_or_unevictable(struct page *page, |
| 483 | 483 | struct vm_area_struct *vma) |
| 484 | 484 | { |
| 485 | − bool unevictable; | |
| 486 | − | |
| 487 | 485 | VM_BUG_ON_PAGE(PageLRU(page), page); |
| 488 | 486 | |
| 489 | − unevictable = (vma->vm_flags & (VM_LOCKED | VM_SPECIAL)) == VM_LOCKED; | |
| 490 | − if (unlikely(unevictable) && !TestSetPageMlocked(page)) { | |
| 491 | − int nr_pages = thp_nr_pages(page); | |
| 492 | − /* | |
| 493 | − * We use the irq-unsafe __mod_zone_page_state because this | |
| 494 | − * counter is not modified from interrupt context, and the pte | |
| 495 | − * lock is held(spinlock), which implies preemption disabled. | |
| 496 | − */ | |
| 497 | − __mod_zone_page_state(page_zone(page), NR_MLOCK, nr_pages); | |
| 498 | − count_vm_events(UNEVICTABLE_PGMLOCKED, nr_pages); | |
| 499 | − } | |
| 500 | − lru_cache_add(page); | |
| 487 | + if (unlikely((vma->vm_flags & (VM_LOCKED | VM_SPECIAL)) == VM_LOCKED)) | |
| 488 | + mlock_new_page(page); | |
| 489 | + else | |
| 490 | + lru_cache_add(page); | |
| 501 | 491 | } |
| 502 | 492 | |
| 503 | 493 | /* |
| @@ -636,35 +626,37 @@ void lru_add_drain_cpu(int cpu) · 132 unmodified lines | ||
| 636 | 626 | pagevec_lru_move_fn(pvec, lru_lazyfree_fn); |
| 637 | 627 | |
| 638 | 628 | activate_page_drain(cpu); |
| 629 | + mlock_page_drain(cpu); | |
| 639 | 630 | } |
| 640 | 631 | |
| 641 | 632 | /** |
| 642 | − * deactivate_file_page - forcefully deactivate a file page | |
| 643 | − * @page: page to deactivate | |
| 633 | + * deactivate_file_folio() - Forcefully deactivate a file folio. | |
| 634 | + * @folio: Folio to deactivate. | |
| 644 | 635 | * |
| 645 | − * This function hints the VM that @page is a good reclaim candidate, | |
| 646 | − * for example if its invalidation fails due to the page being dirty | |
| 636 | + * This function hints to the VM that @folio is a good reclaim candidate, | |
| 637 | + * for example if its invalidation fails due to the folio being dirty | |
| 647 | 638 | * or under writeback. |
| 639 | + * | |
| 640 | + * Context: Caller holds a reference on the page. | |
| 648 | 641 | */ |
| 649 | −void deactivate_file_page(struct page *page) | |
| 642 | +void deactivate_file_folio(struct folio *folio) | |
| 650 | 643 | { |
| 644 | + struct pagevec *pvec; | |
| 645 | + | |
| 651 | 646 | /* |
| 652 | − * In a workload with many unevictable page such as mprotect, | |
| 653 | − * unevictable page deactivation for accelerating reclaim is pointless. | |
| 647 | + * In a workload with many unevictable pages such as mprotect, | |
| 648 | + * unevictable folio deactivation for accelerating reclaim is pointless. | |
| 654 | 649 | */ |
| 655 | − if (PageUnevictable(page)) | |
| 650 | + if (folio_test_unevictable(folio)) | |
| 656 | 651 | return; |
| 657 | 652 | |
| 658 | − if (likely(get_page_unless_zero(page))) { | |
| 659 | − struct pagevec *pvec; | |
| 660 | − | |
| 661 | − local_lock(&lru_pvecs.lock); | |
| 662 | − pvec = this_cpu_ptr(&lru_pvecs.lru_deactivate_file); | |
| 653 | + folio_get(folio); | |
| 654 | + local_lock(&lru_pvecs.lock); | |
| 655 | + pvec = this_cpu_ptr(&lru_pvecs.lru_deactivate_file); | |
| 663 | 656 | |
| 664 | − if (pagevec_add_and_need_flush(pvec, page)) | |
| 665 | − pagevec_lru_move_fn(pvec, lru_deactivate_file_fn); | |
| 666 | − local_unlock(&lru_pvecs.lock); | |
| 667 | − } | |
| 657 | + if (pagevec_add_and_need_flush(pvec, &folio->page)) | |
| 658 | + pagevec_lru_move_fn(pvec, lru_deactivate_file_fn); | |
| 659 | + local_unlock(&lru_pvecs.lock); | |
| 668 | 660 | } |
| 669 | 661 | |
| 670 | 662 | /* |
| @@ -837,6 +829,7 @@ inline void __lru_add_drain_all(bool force_all_cpus) · 166 unmodified lines | ||
| 837 | 829 | pagevec_count(&per_cpu(lru_pvecs.lru_deactivate, cpu)) || |
| 838 | 830 | pagevec_count(&per_cpu(lru_pvecs.lru_lazyfree, cpu)) || |
| 839 | 831 | need_activate_page_drain(cpu) || |
| 832 | + need_mlock_page_drain(cpu) || | |
| 840 | 833 | has_bh_in_lru(cpu, NULL)) { |
| 841 | 834 | INIT_WORK(work, lru_add_drain_per_cpu); |
| 842 | 835 | queue_work_on(cpu, mm_percpu_wq, work); |
| @@ -935,18 +928,10 @@ void release_pages(struct page **pages, int nr) · 92 unmodified lines | ||
| 935 | 928 | unlock_page_lruvec_irqrestore(lruvec, flags); |
| 936 | 929 | lruvec = NULL; |
| 937 | 930 | } |
| 938 | − /* | |
| 939 | − * ZONE_DEVICE pages that return 'false' from | |
| 940 | − * page_is_devmap_managed() do not require special | |
| 941 | − * processing, and instead, expect a call to | |
| 942 | − * put_page_testzero(). | |
| 943 | − */ | |
| 944 | − if (page_is_devmap_managed(page)) { | |
| 945 | − put_devmap_managed_page(page); | |
| 931 | + if (put_devmap_managed_page(page)) | |
| 946 | 932 | continue; |
| 947 | − } | |
| 948 | 933 | if (put_page_testzero(page)) |
| 949 | − put_dev_pagemap(page->pgmap); | |
| 934 | + free_zone_device_page(page); | |
| 950 | 935 | continue; |
| 951 | 936 | } |
| 952 | 937 | |
| @@ -974,6 +959,18 @@ void release_pages(struct page **pages, int nr) · 21 unmodified lines | ||
| 974 | 959 | __clear_page_lru_flags(page); |
| 975 | 960 | } |
| 976 | 961 | |
| 962 | + /* | |
| 963 | + * In rare cases, when truncation or holepunching raced with | |
| 964 | + * munlock after VM_LOCKED was cleared, Mlocked may still be | |
| 965 | + * found set here. This does not indicate a problem, unless | |
| 966 | + * "unevictable_pgs_cleared" appears worryingly large. | |
| 967 | + */ | |
| 968 | + if (unlikely(PageMlocked(page))) { | |
| 969 | + __ClearPageMlocked(page); | |
| 970 | + dec_zone_page_state(page, NR_MLOCK); | |
| 971 | + count_vm_event(UNEVICTABLE_PGCLEARED); | |
| 972 | + } | |
| 973 | + | |
| 977 | 974 | __ClearPageWaiters(page); |
| 978 | 975 | |
| 979 | 976 | list_add(&page->lru, &pages_to_free); |
| @@ -1014,43 +1011,32 @@ static void __pagevec_lru_add_fn(struct folio *folio, struct lruvec *lruvec) · 34 unmodified lines | ||
| 1014 | 1011 | |
| 1015 | 1012 | VM_BUG_ON_FOLIO(folio_test_lru(folio), folio); |
| 1016 | 1013 | |
| 1014 | + folio_set_lru(folio); | |
| 1017 | 1015 | /* |
| 1018 | − * A folio becomes evictable in two ways: | |
| 1019 | − * 1) Within LRU lock [munlock_vma_page() and __munlock_pagevec()]. | |
| 1020 | − * 2) Before acquiring LRU lock to put the folio on the correct LRU | |
| 1021 | − * and then | |
| 1022 | − * a) do PageLRU check with lock [check_move_unevictable_pages] | |
| 1023 | − * b) do PageLRU check before lock [clear_page_mlock] | |
| 1024 | − * | |
| 1025 | − * (1) & (2a) are ok as LRU lock will serialize them. For (2b), we need | |
| 1026 | − * following strict ordering: | |
| 1027 | − * | |
| 1028 | − * #0: __pagevec_lru_add_fn #1: clear_page_mlock | |
| 1016 | + * Is an smp_mb__after_atomic() still required here, before | |
| 1017 | + * folio_evictable() tests PageMlocked, to rule out the possibility | |
| 1018 | + * of stranding an evictable folio on an unevictable LRU? I think | |
| 1019 | + * not, because __munlock_page() only clears PageMlocked while the LRU | |
| 1020 | + * lock is held. | |
| 1029 | 1021 | * |
| 1030 | − * folio_set_lru() folio_test_clear_mlocked() | |
| 1031 | − * smp_mb() // explicit ordering // above provides strict | |
| 1032 | − * // ordering | |
| 1033 | − * folio_test_mlocked() folio_test_lru() | |
| 1034 | − * | |
| 1035 | − * | |
| 1036 | − * if '#1' does not observe setting of PG_lru by '#0' and | |
| 1037 | − * fails isolation, the explicit barrier will make sure that | |
| 1038 | − * folio_evictable check will put the folio on the correct | |
| 1039 | − * LRU. Without smp_mb(), folio_set_lru() can be reordered | |
| 1040 | − * after folio_test_mlocked() check and can make '#1' fail the | |
| 1041 | − * isolation of the folio whose mlocked bit is cleared (#0 is | |
| 1042 | − * also looking at the same folio) and the evictable folio will | |
| 1043 | − * be stranded on an unevictable LRU. | |
| 1022 | + * (That is not true of __page_cache_release(), and not necessarily | |
| 1023 | + * true of release_pages(): but those only clear PageMlocked after | |
| 1024 | + * put_page_testzero() has excluded any other users of the page.) | |
| 1044 | 1025 | */ |
| 1045 | − folio_set_lru(folio); | |
| 1046 | − smp_mb__after_atomic(); | |
| 1047 | − | |
| 1048 | 1026 | if (folio_evictable(folio)) { |
| 1049 | 1027 | if (was_unevictable) |
| 1050 | 1028 | __count_vm_events(UNEVICTABLE_PGRESCUED, nr_pages); |
| 1051 | 1029 | } else { |
| 1052 | 1030 | folio_clear_active(folio); |
| 1053 | 1031 | folio_set_unevictable(folio); |
| 1032 | + /* | |
| 1033 | + * folio->mlock_count = !!folio_test_mlocked(folio)? | |
| 1034 | + * But that leaves __mlock_page() in doubt whether another | |
| 1035 | + * actor has already counted the mlock or not. Err on the | |
| 1036 | + * safe side, underestimate, let page reclaim fix it, rather | |
| 1037 | + * than leaving a page on the unevictable LRU indefinitely. | |
| 1038 | + */ | |
| 1039 | + folio->mlock_count = 0; | |
| 1054 | 1040 | if (!was_unevictable) |
| 1055 | 1041 | __count_vm_events(UNEVICTABLE_PGCULLED, nr_pages); |
| 1056 | 1042 | } |
| @@ -1158,26 +1144,3 @@ void __init swap_setup(void) · 101 unmodified lines | ||
| 1158 | 1144 | * _really_ don't want to cluster much more |
| 1159 | 1145 | */ |
| 1160 | 1146 | } |
| 1161 | − | |
| 1162 | −#ifdef CONFIG_DEV_PAGEMAP_OPS | |
| 1163 | −void put_devmap_managed_page(struct page *page) | |
| 1164 | −{ | |
| 1165 | − int count; | |
| 1166 | − | |
| 1167 | − if (WARN_ON_ONCE(!page_is_devmap_managed(page))) | |
| 1168 | − return; | |
| 1169 | − | |
| 1170 | − count = page_ref_dec_return(page); | |
| 1171 | − | |
| 1172 | − /* | |
| 1173 | − * devmap page refcounts are 1-based, rather than 0-based: if | |
| 1174 | − * refcount is 1, then the page is free and the refcount is | |
| 1175 | − * stable because nobody holds a reference on the page. | |
| 1176 | − */ | |
| 1177 | − if (count == 1) | |
| 1178 | − free_devmap_managed_page(page); | |
| 1179 | − else if (!count) | |
| 1180 | − __put_page(page); | |
| 1181 | −} | |
| 1182 | −EXPORT_SYMBOL(put_devmap_managed_page); | |
| 1183 | −#endif | |
| @@ -193,27 +193,6 @@ static void truncate_cleanup_folio(struct folio *folio) · 192 unmodified lines | ||
| 193 | 193 | folio_clear_mappedtodisk(folio); |
| 194 | 194 | } |
| 195 | 195 | |
| 196 | −/* | |
| 197 | − * This is for invalidate_mapping_pages(). That function can be called at | |
| 198 | − * any time, and is not supposed to throw away dirty pages. But pages can | |
| 199 | − * be marked dirty at any time too, so use remove_mapping which safely | |
| 200 | − * discards clean, unused pages. | |
| 201 | − * | |
| 202 | − * Returns non-zero if the page was successfully invalidated. | |
| 203 | − */ | |
| 204 | −static int | |
| 205 | −invalidate_complete_page(struct address_space *mapping, struct page *page) | |
| 206 | −{ | |
| 207 | − | |
| 208 | − if (page->mapping != mapping) | |
| 209 | − return 0; | |
| 210 | − | |
| 211 | − if (page_has_private(page) && !try_to_release_page(page, 0)) | |
| 212 | − return 0; | |
| 213 | − | |
| 214 | − return remove_mapping(mapping, page); | |
| 215 | −} | |
| 216 | − | |
| 217 | 196 | int truncate_inode_folio(struct address_space *mapping, struct folio *folio) |
| 218 | 197 | { |
| 219 | 198 | if (folio->mapping != mapping) |
| @@ -294,22 +273,40 @@ int generic_error_remove_page(struct address_space *mapping, struct page *page) · 74 unmodified lines | ||
| 294 | 273 | } |
| 295 | 274 | EXPORT_SYMBOL(generic_error_remove_page); |
| 296 | 275 | |
| 297 | −/* | |
| 276 | +static long mapping_evict_folio(struct address_space *mapping, | |
| 277 | + struct folio *folio) | |
| 278 | +{ | |
| 279 | + if (folio_test_dirty(folio) || folio_test_writeback(folio)) | |
| 280 | + return 0; | |
| 281 | + /* The refcount will be elevated if any page in the folio is mapped */ | |
| 282 | + if (folio_ref_count(folio) > | |
| 283 | + folio_nr_pages(folio) + folio_has_private(folio) + 1) | |
| 284 | + return 0; | |
| 285 | + if (folio_has_private(folio) && !filemap_release_folio(folio, 0)) | |
| 286 | + return 0; | |
| 287 | + | |
| 288 | + return remove_mapping(mapping, folio); | |
| 289 | +} | |
| 290 | + | |
| 291 | +/** | |
| 292 | + * invalidate_inode_page() - Remove an unused page from the pagecache. | |
| 293 | + * @page: The page to remove. | |
| 294 | + * | |
| 298 | 295 | * Safely invalidate one page from its pagecache mapping. |
| 299 | − * It only drops clean, unused pages. The page must be locked. | |
| 296 | + * It only drops clean, unused pages. | |
| 300 | 297 | * |
| 301 | − * Returns 1 if the page is successfully invalidated, otherwise 0. | |
| 298 | + * Context: Page must be locked. | |
| 299 | + * Return: The number of pages successfully removed. | |
| 302 | 300 | */ |
| 303 | −int invalidate_inode_page(struct page *page) | |
| 301 | +long invalidate_inode_page(struct page *page) | |
| 304 | 302 | { |
| 305 | − struct address_space *mapping = page_mapping(page); | |
| 303 | + struct folio *folio = page_folio(page); | |
| 304 | + struct address_space *mapping = folio_mapping(folio); | |
| 305 | + | |
| 306 | + /* The page may have been truncated before it was locked */ | |
| 306 | 307 | if (!mapping) |
| 307 | 308 | return 0; |
| 308 | − if (PageDirty(page) || PageWriteback(page)) | |
| 309 | − return 0; | |
| 310 | − if (page_mapped(page)) | |
| 311 | − return 0; | |
| 312 | − return invalidate_complete_page(mapping, page); | |
| 309 | + return mapping_evict_folio(mapping, folio); | |
| 313 | 310 | } |
| 314 | 311 | |
| 315 | 312 | /** |
| @@ -497,7 +494,18 @@ void truncate_inode_pages_final(struct address_space *mapping) · 181 unmodified lines | ||
| 497 | 494 | } |
| 498 | 495 | EXPORT_SYMBOL(truncate_inode_pages_final); |
| 499 | 496 | |
| 500 | −static unsigned long __invalidate_mapping_pages(struct address_space *mapping, | |
| 497 | +/** | |
| 498 | + * invalidate_mapping_pagevec - Invalidate all the unlocked pages of one inode | |
| 499 | + * @mapping: the address_space which holds the pages to invalidate | |
| 500 | + * @start: the offset 'from' which to invalidate | |
| 501 | + * @end: the offset 'to' which to invalidate (inclusive) | |
| 502 | + * @nr_pagevec: invalidate failed page number for caller | |
| 503 | + * | |
| 504 | + * This helper is similar to invalidate_mapping_pages(), except that it accounts | |
| 505 | + * for pages that are likely on a pagevec and counts them in @nr_pagevec, which | |
| 506 | + * will be used by the caller. | |
| 507 | + */ | |
| 508 | +unsigned long invalidate_mapping_pagevec(struct address_space *mapping, | |
| 501 | 509 | pgoff_t start, pgoff_t end, unsigned long *nr_pagevec) |
| 502 | 510 | { |
| 503 | 511 | pgoff_t indices[PAGEVEC_SIZE]; |
| @@ -510,27 +518,27 @@ static unsigned long __invalidate_mapping_pages(struct address_space *mapping, · 6 unmodified lines | ||
| 510 | 518 | folio_batch_init(&fbatch); |
| 511 | 519 | while (find_lock_entries(mapping, index, end, &fbatch, indices)) { |
| 512 | 520 | for (i = 0; i < folio_batch_count(&fbatch); i++) { |
| 513 | − struct page *page = &fbatch.folios[i]->page; | |
| 521 | + struct folio *folio = fbatch.folios[i]; | |
| 514 | 522 | |
| 515 | − /* We rely upon deletion not changing page->index */ | |
| 523 | + /* We rely upon deletion not changing folio->index */ | |
| 516 | 524 | index = indices[i]; |
| 517 | 525 | |
| 518 | − if (xa_is_value(page)) { | |
| 526 | + if (xa_is_value(folio)) { | |
| 519 | 527 | count += invalidate_exceptional_entry(mapping, |
| 520 | 528 | index, |
| 521 | − page); | |
| 529 | + folio); | |
| 522 | 530 | continue; |
| 523 | 531 | } |
| 524 | − index += thp_nr_pages(page) - 1; | |
| 532 | + index += folio_nr_pages(folio) - 1; | |
| 525 | 533 | |
| 526 | − ret = invalidate_inode_page(page); | |
| 527 | − unlock_page(page); | |
| 534 | + ret = mapping_evict_folio(mapping, folio); | |
| 535 | + folio_unlock(folio); | |
| 528 | 536 | /* |
| 529 | − * Invalidation is a hint that the page is no longer | |
| 537 | + * Invalidation is a hint that the folio is no longer | |
| 530 | 538 | * of interest and try to speed up its reclaim. |
| 531 | 539 | */ |
| 532 | 540 | if (!ret) { |
| 533 | − deactivate_file_page(page); | |
| 541 | + deactivate_file_folio(folio); | |
| 534 | 542 | /* It is likely on the pagevec of a remote CPU */ |
| 535 | 543 | if (nr_pagevec) |
| 536 | 544 | (*nr_pagevec)++; |
| @@ -562,29 +570,12 @@ static unsigned long __invalidate_mapping_pages(struct address_space *mapping, · 25 unmodified lines | ||
| 562 | 570 | unsigned long invalidate_mapping_pages(struct address_space *mapping, |
| 563 | 571 | pgoff_t start, pgoff_t end) |
| 564 | 572 | { |
| 565 | − return __invalidate_mapping_pages(mapping, start, end, NULL); | |
| 573 | + return invalidate_mapping_pagevec(mapping, start, end, NULL); | |
| 566 | 574 | } |
| 567 | 575 | EXPORT_SYMBOL(invalidate_mapping_pages); |
| 568 | 576 | |
| 569 | −/** | |
| 570 | − * invalidate_mapping_pagevec - Invalidate all the unlocked pages of one inode | |
| 571 | − * @mapping: the address_space which holds the pages to invalidate | |
| 572 | − * @start: the offset 'from' which to invalidate | |
| 573 | − * @end: the offset 'to' which to invalidate (inclusive) | |
| 574 | − * @nr_pagevec: invalidate failed page number for caller | |
| 575 | − * | |
| 576 | − * This helper is similar to invalidate_mapping_pages(), except that it accounts | |
| 577 | − * for pages that are likely on a pagevec and counts them in @nr_pagevec, which | |
| 578 | − * will be used by the caller. | |
| 579 | − */ | |
| 580 | −void invalidate_mapping_pagevec(struct address_space *mapping, | |
| 581 | − pgoff_t start, pgoff_t end, unsigned long *nr_pagevec) | |
| 582 | −{ | |
| 583 | − __invalidate_mapping_pages(mapping, start, end, nr_pagevec); | |
| 584 | −} | |
| 585 | − | |
| 586 | 577 | /* |
| 587 | − * This is like invalidate_complete_page(), except it ignores the page's | |
| 578 | + * This is like invalidate_inode_page(), except it ignores the page's | |
| 588 | 579 | * refcount. We do this because invalidate_inode_pages2() needs stronger |
| 589 | 580 | * invalidation guarantees, and cannot afford to leave pages behind because |
| 590 | 581 | * shrink_page_list() has a temp ref on them, or because they're transiently |
| @@ -95,10 +95,15 @@ int mfill_atomic_install_pte(struct mm_struct *dst_mm, pmd_t *dst_pmd, · 94 unmodified lines | ||
| 95 | 95 | if (!pte_none(*dst_pte)) |
| 96 | 96 | goto out_unlock; |
| 97 | 97 | |
| 98 | − if (page_in_cache) | |
| 99 | − page_add_file_rmap(page, false); | |
| 100 | − else | |
| 98 | + if (page_in_cache) { | |
| 99 | + /* Usually, cache pages are already added to LRU */ | |
| 100 | + if (newly_allocated) | |
| 101 | + lru_cache_add(page); | |
| 102 | + page_add_file_rmap(page, dst_vma, false); | |
| 103 | + } else { | |
| 101 | 104 | page_add_new_anon_rmap(page, dst_vma, dst_addr, false); |
| 105 | + lru_cache_add_inactive_or_unevictable(page, dst_vma); | |
| 106 | + } | |
| 102 | 107 | |
| 103 | 108 | /* |
| 104 | 109 | * Must happen after rmap, as mm_counter() checks mapping (via |
| @@ -106,9 +111,6 @@ int mfill_atomic_install_pte(struct mm_struct *dst_mm, pmd_t *dst_pmd, · 1 unmodified line | ||
| 106 | 111 | */ |
| 107 | 112 | inc_mm_counter(dst_mm, mm_counter(page)); |
| 108 | 113 | |
| 109 | − if (newly_allocated) | |
| 110 | − lru_cache_add_inactive_or_unevictable(page, dst_vma); | |
| 111 | − | |
| 112 | 114 | set_pte_at(dst_mm, dst_addr, dst_pte, _dst_pte); |
| 113 | 115 | |
| 114 | 116 | /* No need to invalidate - it was non-present before */ |
| @@ -681,9 +681,8 @@ bool folio_mapped(struct folio *folio) · 680 unmodified lines | ||
| 681 | 681 | } |
| 682 | 682 | EXPORT_SYMBOL(folio_mapped); |
| 683 | 683 | |
| 684 | −struct anon_vma *page_anon_vma(struct page *page) | |
| 684 | +struct anon_vma *folio_anon_vma(struct folio *folio) | |
| 685 | 685 | { |
| 686 | − struct folio *folio = page_folio(page); | |
| 687 | 686 | unsigned long mapping = (unsigned long)folio->mapping; |
| 688 | 687 | |
| 689 | 688 | if ((mapping & PAGE_MAPPING_FLAGS) != PAGE_MAPPING_ANON) |
| @@ -742,6 +741,39 @@ int __page_mapcount(struct page *page) · 52 unmodified lines | ||
| 742 | 741 | } |
| 743 | 742 | EXPORT_SYMBOL_GPL(__page_mapcount); |
| 744 | 743 | |
| 744 | +/** | |
| 745 | + * folio_mapcount() - Calculate the number of mappings of this folio. | |
| 746 | + * @folio: The folio. | |
| 747 | + * | |
| 748 | + * A large folio tracks both how many times the entire folio is mapped, | |
| 749 | + * and how many times each individual page in the folio is mapped. | |
| 750 | + * This function calculates the total number of times the folio is | |
| 751 | + * mapped. | |
| 752 | + * | |
| 753 | + * Return: The number of times this folio is mapped. | |
| 754 | + */ | |
| 755 | +int folio_mapcount(struct folio *folio) | |
| 756 | +{ | |
| 757 | + int i, compound, nr, ret; | |
| 758 | + | |
| 759 | + if (likely(!folio_test_large(folio))) | |
| 760 | + return atomic_read(&folio->_mapcount) + 1; | |
| 761 | + | |
| 762 | + compound = folio_entire_mapcount(folio); | |
| 763 | + nr = folio_nr_pages(folio); | |
| 764 | + if (folio_test_hugetlb(folio)) | |
| 765 | + return compound; | |
| 766 | + ret = compound; | |
| 767 | + for (i = 0; i < nr; i++) | |
| 768 | + ret += atomic_read(&folio_page(folio, i)->_mapcount) + 1; | |
| 769 | + /* File pages has compound_mapcount included in _mapcount */ | |
| 770 | + if (!folio_test_anon(folio)) | |
| 771 | + return ret - compound * nr; | |
| 772 | + if (folio_test_double_map(folio)) | |
| 773 | + ret -= nr; | |
| 774 | + return ret; | |
| 775 | +} | |
| 776 | + | |
| 745 | 777 | /** |
| 746 | 778 | * folio_copy - Copy the contents of one folio to another. |
| 747 | 779 | * @dst: Folio to copy to. |
| @@ -979,36 +979,36 @@ void drop_slab(void) · 978 unmodified lines | ||
| 979 | 979 | drop_slab_node(nid); |
| 980 | 980 | } |
| 981 | 981 | |
| 982 | −static inline int is_page_cache_freeable(struct page *page) | |
| 982 | +static inline int is_page_cache_freeable(struct folio *folio) | |
| 983 | 983 | { |
| 984 | 984 | /* |
| 985 | 985 | * A freeable page cache page is referenced only by the caller |
| 986 | 986 | * that isolated the page, the page cache and optional buffer |
| 987 | 987 | * heads at page->private. |
| 988 | 988 | */ |
| 989 | − int page_cache_pins = thp_nr_pages(page); | |
| 990 | − return page_count(page) - page_has_private(page) == 1 + page_cache_pins; | |
| 989 | + return folio_ref_count(folio) - folio_test_private(folio) == | |
| 990 | + 1 + folio_nr_pages(folio); | |
| 991 | 991 | } |
| 992 | 992 | |
| 993 | 993 | /* |
| 994 | − * We detected a synchronous write error writing a page out. Probably | |
| 994 | + * We detected a synchronous write error writing a folio out. Probably | |
| 995 | 995 | * -ENOSPC. We need to propagate that into the address_space for a subsequent |
| 996 | 996 | * fsync(), msync() or close(). |
| 997 | 997 | * |
| 998 | 998 | * The tricky part is that after writepage we cannot touch the mapping: nothing |
| 999 | − * prevents it from being freed up. But we have a ref on the page and once | |
| 1000 | − * that page is locked, the mapping is pinned. | |
| 999 | + * prevents it from being freed up. But we have a ref on the folio and once | |
| 1000 | + * that folio is locked, the mapping is pinned. | |
| 1001 | 1001 | * |
| 1002 | − * We're allowed to run sleeping lock_page() here because we know the caller has | |
| 1002 | + * We're allowed to run sleeping folio_lock() here because we know the caller has | |
| 1003 | 1003 | * __GFP_FS. |
| 1004 | 1004 | */ |
| 1005 | 1005 | static void handle_write_error(struct address_space *mapping, |
| 1006 | − struct page *page, int error) | |
| 1006 | + struct folio *folio, int error) | |
| 1007 | 1007 | { |
| 1008 | − lock_page(page); | |
| 1009 | − if (page_mapping(page) == mapping) | |
| 1008 | + folio_lock(folio); | |
| 1009 | + if (folio_mapping(folio) == mapping) | |
| 1010 | 1010 | mapping_set_error(mapping, error); |
| 1011 | − unlock_page(page); | |
| 1011 | + folio_unlock(folio); | |
| 1012 | 1012 | } |
| 1013 | 1013 | |
| 1014 | 1014 | static bool skip_throttle_noprogress(pg_data_t *pgdat) |
| @@ -1155,35 +1155,35 @@ typedef enum { · 140 unmodified lines | ||
| 1155 | 1155 | * pageout is called by shrink_page_list() for each dirty page. |
| 1156 | 1156 | * Calls ->writepage(). |
| 1157 | 1157 | */ |
| 1158 | −static pageout_t pageout(struct page *page, struct address_space *mapping) | |
| 1158 | +static pageout_t pageout(struct folio *folio, struct address_space *mapping) | |
| 1159 | 1159 | { |
| 1160 | 1160 | /* |
| 1161 | − * If the page is dirty, only perform writeback if that write | |
| 1161 | + * If the folio is dirty, only perform writeback if that write | |
| 1162 | 1162 | * will be non-blocking. To prevent this allocation from being |
| 1163 | 1163 | * stalled by pagecache activity. But note that there may be |
| 1164 | 1164 | * stalls if we need to run get_block(). We could test |
| 1165 | 1165 | * PagePrivate for that. |
| 1166 | 1166 | * |
| 1167 | 1167 | * If this process is currently in __generic_file_write_iter() against |
| 1168 | − * this page's queue, we can perform writeback even if that | |
| 1168 | + * this folio's queue, we can perform writeback even if that | |
| 1169 | 1169 | * will block. |
| 1170 | 1170 | * |
| 1171 | − * If the page is swapcache, write it back even if that would | |
| 1171 | + * If the folio is swapcache, write it back even if that would | |
| 1172 | 1172 | * block, for some throttling. This happens by accident, because |
| 1173 | 1173 | * swap_backing_dev_info is bust: it doesn't reflect the |
| 1174 | 1174 | * congestion state of the swapdevs. Easy to fix, if needed. |
| 1175 | 1175 | */ |
| 1176 | − if (!is_page_cache_freeable(page)) | |
| 1176 | + if (!is_page_cache_freeable(folio)) | |
| 1177 | 1177 | return PAGE_KEEP; |
| 1178 | 1178 | if (!mapping) { |
| 1179 | 1179 | /* |
| 1180 | − * Some data journaling orphaned pages can have | |
| 1181 | − * page->mapping == NULL while being dirty with clean buffers. | |
| 1180 | + * Some data journaling orphaned folios can have | |
| 1181 | + * folio->mapping == NULL while being dirty with clean buffers. | |
| 1182 | 1182 | */ |
| 1183 | − if (page_has_private(page)) { | |
| 1184 | − if (try_to_free_buffers(page)) { | |
| 1185 | − ClearPageDirty(page); | |
| 1186 | − pr_info("%s: orphaned page\n", __func__); | |
| 1183 | + if (folio_test_private(folio)) { | |
| 1184 | + if (try_to_free_buffers(&folio->page)) { | |
| 1185 | + folio_clear_dirty(folio); | |
| 1186 | + pr_info("%s: orphaned folio\n", __func__); | |
| 1187 | 1187 | return PAGE_CLEAN; |
| 1188 | 1188 | } |
| 1189 | 1189 | } |
| @@ -1192,7 +1192,7 @@ static pageout_t pageout(struct page *page, struct address_space *mapping) · 2 unmodified lines | ||
| 1192 | 1192 | if (mapping->a_ops->writepage == NULL) |
| 1193 | 1193 | return PAGE_ACTIVATE; |
| 1194 | 1194 | |
| 1195 | − if (clear_page_dirty_for_io(page)) { | |
| 1195 | + if (folio_clear_dirty_for_io(folio)) { | |
| 1196 | 1196 | int res; |
| 1197 | 1197 | struct writeback_control wbc = { |
| 1198 | 1198 | .sync_mode = WB_SYNC_NONE, |
| @@ -1202,21 +1202,21 @@ static pageout_t pageout(struct page *page, struct address_space *mapping) · 3 unmodified lines | ||
| 1202 | 1202 | .for_reclaim = 1, |
| 1203 | 1203 | }; |
| 1204 | 1204 | |
| 1205 | − SetPageReclaim(page); | |
| 1206 | − res = mapping->a_ops->writepage(page, &wbc); | |
| 1205 | + folio_set_reclaim(folio); | |
| 1206 | + res = mapping->a_ops->writepage(&folio->page, &wbc); | |
| 1207 | 1207 | if (res < 0) |
| 1208 | − handle_write_error(mapping, page, res); | |
| 1208 | + handle_write_error(mapping, folio, res); | |
| 1209 | 1209 | if (res == AOP_WRITEPAGE_ACTIVATE) { |
| 1210 | − ClearPageReclaim(page); | |
| 1210 | + folio_clear_reclaim(folio); | |
| 1211 | 1211 | return PAGE_ACTIVATE; |
| 1212 | 1212 | } |
| 1213 | 1213 | |
| 1214 | − if (!PageWriteback(page)) { | |
| 1214 | + if (!folio_test_writeback(folio)) { | |
| 1215 | 1215 | /* synchronous write or broken a_ops? */ |
| 1216 | − ClearPageReclaim(page); | |
| 1216 | + folio_clear_reclaim(folio); | |
| 1217 | 1217 | } |
| 1218 | − trace_mm_vmscan_writepage(page); | |
| 1219 | − inc_node_page_state(page, NR_VMSCAN_WRITE); | |
| 1218 | + trace_mm_vmscan_write_folio(folio); | |
| 1219 | + node_stat_add_folio(folio, NR_VMSCAN_WRITE); | |
| 1220 | 1220 | return PAGE_SUCCESS; |
| 1221 | 1221 | } |
| 1222 | 1222 | |
| @@ -1227,16 +1227,16 @@ static pageout_t pageout(struct page *page, struct address_space *mapping) · 4 unmodified lines | ||
| 1227 | 1227 | * Same as remove_mapping, but if the page is removed from the mapping, it |
| 1228 | 1228 | * gets returned with a refcount of 0. |
| 1229 | 1229 | */ |
| 1230 | −static int __remove_mapping(struct address_space *mapping, struct page *page, | |
| 1230 | +static int __remove_mapping(struct address_space *mapping, struct folio *folio, | |
| 1231 | 1231 | bool reclaimed, struct mem_cgroup *target_memcg) |
| 1232 | 1232 | { |
| 1233 | 1233 | int refcount; |
| 1234 | 1234 | void *shadow = NULL; |
| 1235 | 1235 | |
| 1236 | − BUG_ON(!PageLocked(page)); | |
| 1237 | − BUG_ON(mapping != page_mapping(page)); | |
| 1236 | + BUG_ON(!folio_test_locked(folio)); | |
| 1237 | + BUG_ON(mapping != folio_mapping(folio)); | |
| 1238 | 1238 | |
| 1239 | − if (!PageSwapCache(page)) | |
| 1239 | + if (!folio_test_swapcache(folio)) | |
| 1240 | 1240 | spin_lock(&mapping->host->i_lock); |
| 1241 | 1241 | xa_lock_irq(&mapping->i_pages); |
| 1242 | 1242 | /* |
| @@ -1264,23 +1264,23 @@ static int __remove_mapping(struct address_space *mapping, struct page *page, · 21 unmodified lines | ||
| 1264 | 1264 | * Note that if SetPageDirty is always performed via set_page_dirty, |
| 1265 | 1265 | * and thus under the i_pages lock, then this ordering is not required. |
| 1266 | 1266 | */ |
| 1267 | − refcount = 1 + compound_nr(page); | |
| 1268 | − if (!page_ref_freeze(page, refcount)) | |
| 1267 | + refcount = 1 + folio_nr_pages(folio); | |
| 1268 | + if (!folio_ref_freeze(folio, refcount)) | |
| 1269 | 1269 | goto cannot_free; |
| 1270 | 1270 | /* note: atomic_cmpxchg in page_ref_freeze provides the smp_rmb */ |
| 1271 | − if (unlikely(PageDirty(page))) { | |
| 1272 | − page_ref_unfreeze(page, refcount); | |
| 1271 | + if (unlikely(folio_test_dirty(folio))) { | |
| 1272 | + folio_ref_unfreeze(folio, refcount); | |
| 1273 | 1273 | goto cannot_free; |
| 1274 | 1274 | } |
| 1275 | 1275 | |
| 1276 | − if (PageSwapCache(page)) { | |
| 1277 | − swp_entry_t swap = { .val = page_private(page) }; | |
| 1278 | − mem_cgroup_swapout(page, swap); | |
| 1276 | + if (folio_test_swapcache(folio)) { | |
| 1277 | + swp_entry_t swap = folio_swap_entry(folio); | |
| 1278 | + mem_cgroup_swapout(folio, swap); | |
| 1279 | 1279 | if (reclaimed && !mapping_exiting(mapping)) |
| 1280 | − shadow = workingset_eviction(page, target_memcg); | |
| 1281 | − __delete_from_swap_cache(page, swap, shadow); | |
| 1280 | + shadow = workingset_eviction(folio, target_memcg); | |
| 1281 | + __delete_from_swap_cache(&folio->page, swap, shadow); | |
| 1282 | 1282 | xa_unlock_irq(&mapping->i_pages); |
| 1283 | − put_swap_page(page, swap); | |
| 1283 | + put_swap_page(&folio->page, swap); | |
| 1284 | 1284 | } else { |
| 1285 | 1285 | void (*freepage)(struct page *); |
| 1286 | 1286 | |
| @@ -1301,61 +1301,67 @@ static int __remove_mapping(struct address_space *mapping, struct page *page, · 14 unmodified lines | ||
| 1301 | 1301 | * exceptional entries and shadow exceptional entries in the |
| 1302 | 1302 | * same address_space. |
| 1303 | 1303 | */ |
| 1304 | − if (reclaimed && page_is_file_lru(page) && | |
| 1304 | + if (reclaimed && folio_is_file_lru(folio) && | |
| 1305 | 1305 | !mapping_exiting(mapping) && !dax_mapping(mapping)) |
| 1306 | − shadow = workingset_eviction(page, target_memcg); | |
| 1307 | − __delete_from_page_cache(page, shadow); | |
| 1306 | + shadow = workingset_eviction(folio, target_memcg); | |
| 1307 | + __filemap_remove_folio(folio, shadow); | |
| 1308 | 1308 | xa_unlock_irq(&mapping->i_pages); |
| 1309 | 1309 | if (mapping_shrinkable(mapping)) |
| 1310 | 1310 | inode_add_lru(mapping->host); |
| 1311 | 1311 | spin_unlock(&mapping->host->i_lock); |
| 1312 | 1312 | |
| 1313 | 1313 | if (freepage != NULL) |
| 1314 | − freepage(page); | |
| 1314 | + freepage(&folio->page); | |
| 1315 | 1315 | } |
| 1316 | 1316 | |
| 1317 | 1317 | return 1; |
| 1318 | 1318 | |
| 1319 | 1319 | cannot_free: |
| 1320 | 1320 | xa_unlock_irq(&mapping->i_pages); |
| 1321 | − if (!PageSwapCache(page)) | |
| 1321 | + if (!folio_test_swapcache(folio)) | |
| 1322 | 1322 | spin_unlock(&mapping->host->i_lock); |
| 1323 | 1323 | return 0; |
| 1324 | 1324 | } |
| 1325 | 1325 | |
| 1326 | −/* | |
| 1327 | − * Attempt to detach a locked page from its ->mapping. If it is dirty or if | |
| 1328 | − * someone else has a ref on the page, abort and return 0. If it was | |
| 1329 | − * successfully detached, return 1. Assumes the caller has a single ref on | |
| 1330 | − * this page. | |
| 1326 | +/** | |
| 1327 | + * remove_mapping() - Attempt to remove a folio from its mapping. | |
| 1328 | + * @mapping: The address space. | |
| 1329 | + * @folio: The folio to remove. | |
| 1330 | + * | |
| 1331 | + * If the folio is dirty, under writeback or if someone else has a ref | |
| 1332 | + * on it, removal will fail. | |
| 1333 | + * Return: The number of pages removed from the mapping. 0 if the folio | |
| 1334 | + * could not be removed. | |
| 1335 | + * Context: The caller should have a single refcount on the folio and | |
| 1336 | + * hold its lock. | |
| 1331 | 1337 | */ |
| 1332 | −int remove_mapping(struct address_space *mapping, struct page *page) | |
| 1338 | +long remove_mapping(struct address_space *mapping, struct folio *folio) | |
| 1333 | 1339 | { |
| 1334 | − if (__remove_mapping(mapping, page, false, NULL)) { | |
| 1340 | + if (__remove_mapping(mapping, folio, false, NULL)) { | |
| 1335 | 1341 | /* |
| 1336 | − * Unfreezing the refcount with 1 rather than 2 effectively | |
| 1342 | + * Unfreezing the refcount with 1 effectively | |
| 1337 | 1343 | * drops the pagecache ref for us without requiring another |
| 1338 | 1344 | * atomic operation. |
| 1339 | 1345 | */ |
| 1340 | − page_ref_unfreeze(page, 1); | |
| 1341 | − return 1; | |
| 1346 | + folio_ref_unfreeze(folio, 1); | |
| 1347 | + return folio_nr_pages(folio); | |
| 1342 | 1348 | } |
| 1343 | 1349 | return 0; |
| 1344 | 1350 | } |
| 1345 | 1351 | |
| 1346 | 1352 | /** |
| 1347 | − * putback_lru_page - put previously isolated page onto appropriate LRU list | |
| 1348 | − * @page: page to be put back to appropriate lru list | |
| 1353 | + * folio_putback_lru - Put previously isolated folio onto appropriate LRU list. | |
| 1354 | + * @folio: Folio to be returned to an LRU list. | |
| 1349 | 1355 | * |
| 1350 | − * Add previously isolated @page to appropriate LRU list. | |
| 1351 | − * Page may still be unevictable for other reasons. | |
| 1356 | + * Add previously isolated @folio to appropriate LRU list. | |
| 1357 | + * The folio may still be unevictable for other reasons. | |
| 1352 | 1358 | * |
| 1353 | − * lru_lock must not be held, interrupts must be enabled. | |
| 1359 | + * Context: lru_lock must not be held, interrupts must be enabled. | |
| 1354 | 1360 | */ |
| 1355 | −void putback_lru_page(struct page *page) | |
| 1361 | +void folio_putback_lru(struct folio *folio) | |
| 1356 | 1362 | { |
| 1357 | − lru_cache_add(page); | |
| 1358 | − put_page(page); /* drop ref from isolate */ | |
| 1363 | + folio_add_lru(folio); | |
| 1364 | + folio_put(folio); /* drop ref from isolate */ | |
| 1359 | 1365 | } |
| 1360 | 1366 | |
| 1361 | 1367 | enum page_references { |
| @@ -1365,61 +1371,61 @@ enum page_references { · 3 unmodified lines | ||
| 1365 | 1371 | PAGEREF_ACTIVATE, |
| 1366 | 1372 | }; |
| 1367 | 1373 | |
| 1368 | −static enum page_references page_check_references(struct page *page, | |
| 1374 | +static enum page_references folio_check_references(struct folio *folio, | |
| 1369 | 1375 | struct scan_control *sc) |
| 1370 | 1376 | { |
| 1371 | − int referenced_ptes, referenced_page; | |
| 1377 | + int referenced_ptes, referenced_folio; | |
| 1372 | 1378 | unsigned long vm_flags; |
| 1373 | 1379 | |
| 1374 | − referenced_ptes = page_referenced(page, 1, sc->target_mem_cgroup, | |
| 1375 | − &vm_flags); | |
| 1376 | − referenced_page = TestClearPageReferenced(page); | |
| 1380 | + referenced_ptes = folio_referenced(folio, 1, sc->target_mem_cgroup, | |
| 1381 | + &vm_flags); | |
| 1382 | + referenced_folio = folio_test_clear_referenced(folio); | |
| 1377 | 1383 | |
| 1378 | 1384 | /* |
| 1379 | − * Mlock lost the isolation race with us. Let try_to_unmap() | |
| 1380 | − * move the page to the unevictable list. | |
| 1385 | + * The supposedly reclaimable folio was found to be in a VM_LOCKED vma. | |
| 1386 | + * Let the folio, now marked Mlocked, be moved to the unevictable list. | |
| 1381 | 1387 | */ |
| 1382 | 1388 | if (vm_flags & VM_LOCKED) |
| 1383 | − return PAGEREF_RECLAIM; | |
| 1389 | + return PAGEREF_ACTIVATE; | |
| 1384 | 1390 | |
| 1385 | 1391 | if (referenced_ptes) { |
| 1386 | 1392 | /* |
| 1387 | − * All mapped pages start out with page table | |
| 1393 | + * All mapped folios start out with page table | |
| 1388 | 1394 | * references from the instantiating fault, so we need |
| 1389 | − * to look twice if a mapped file/anon page is used more | |
| 1395 | + * to look twice if a mapped file/anon folio is used more | |
| 1390 | 1396 | * than once. |
| 1391 | 1397 | * |
| 1392 | 1398 | * Mark it and spare it for another trip around the |
| 1393 | 1399 | * inactive list. Another page table reference will |
| 1394 | 1400 | * lead to its activation. |
| 1395 | 1401 | * |
| 1396 | − * Note: the mark is set for activated pages as well | |
| 1397 | − * so that recently deactivated but used pages are | |
| 1402 | + * Note: the mark is set for activated folios as well | |
| 1403 | + * so that recently deactivated but used folios are | |
| 1398 | 1404 | * quickly recovered. |
| 1399 | 1405 | */ |
| 1400 | − SetPageReferenced(page); | |
| 1406 | + folio_set_referenced(folio); | |
| 1401 | 1407 | |
| 1402 | − if (referenced_page || referenced_ptes > 1) | |
| 1408 | + if (referenced_folio || referenced_ptes > 1) | |
| 1403 | 1409 | return PAGEREF_ACTIVATE; |
| 1404 | 1410 | |
| 1405 | 1411 | /* |
| 1406 | − * Activate file-backed executable pages after first usage. | |
| 1412 | + * Activate file-backed executable folios after first usage. | |
| 1407 | 1413 | */ |
| 1408 | − if ((vm_flags & VM_EXEC) && !PageSwapBacked(page)) | |
| 1414 | + if ((vm_flags & VM_EXEC) && !folio_test_swapbacked(folio)) | |
| 1409 | 1415 | return PAGEREF_ACTIVATE; |
| 1410 | 1416 | |
| 1411 | 1417 | return PAGEREF_KEEP; |
| 1412 | 1418 | } |
| 1413 | 1419 | |
| 1414 | − /* Reclaim if clean, defer dirty pages to writeback */ | |
| 1415 | − if (referenced_page && !PageSwapBacked(page)) | |
| 1420 | + /* Reclaim if clean, defer dirty folios to writeback */ | |
| 1421 | + if (referenced_folio && !folio_test_swapbacked(folio)) | |
| 1416 | 1422 | return PAGEREF_RECLAIM_CLEAN; |
| 1417 | 1423 | |
| 1418 | 1424 | return PAGEREF_RECLAIM; |
| 1419 | 1425 | } |
| 1420 | 1426 | |
| 1421 | 1427 | /* Check if a page is dirty or under writeback */ |
| 1422 | −static void page_check_dirty_writeback(struct page *page, | |
| 1428 | +static void folio_check_dirty_writeback(struct folio *folio, | |
| 1423 | 1429 | bool *dirty, bool *writeback) |
| 1424 | 1430 | { |
| 1425 | 1431 | struct address_space *mapping; |
| @@ -1428,24 +1434,24 @@ static void page_check_dirty_writeback(struct page *page, · 2 unmodified lines | ||
| 1428 | 1434 | * Anonymous pages are not handled by flushers and must be written |
| 1429 | 1435 | * from reclaim context. Do not stall reclaim based on them |
| 1430 | 1436 | */ |
| 1431 | − if (!page_is_file_lru(page) || | |
| 1432 | − (PageAnon(page) && !PageSwapBacked(page))) { | |
| 1437 | + if (!folio_is_file_lru(folio) || | |
| 1438 | + (folio_test_anon(folio) && !folio_test_swapbacked(folio))) { | |
| 1433 | 1439 | *dirty = false; |
| 1434 | 1440 | *writeback = false; |
| 1435 | 1441 | return; |
| 1436 | 1442 | } |
| 1437 | 1443 | |
| 1438 | − /* By default assume that the page flags are accurate */ | |
| 1439 | − *dirty = PageDirty(page); | |
| 1440 | − *writeback = PageWriteback(page); | |
| 1444 | + /* By default assume that the folio flags are accurate */ | |
| 1445 | + *dirty = folio_test_dirty(folio); | |
| 1446 | + *writeback = folio_test_writeback(folio); | |
| 1441 | 1447 | |
| 1442 | 1448 | /* Verify dirty/writeback state if the filesystem supports it */ |
| 1443 | − if (!page_has_private(page)) | |
| 1449 | + if (!folio_test_private(folio)) | |
| 1444 | 1450 | return; |
| 1445 | 1451 | |
| 1446 | − mapping = page_mapping(page); | |
| 1452 | + mapping = folio_mapping(folio); | |
| 1447 | 1453 | if (mapping && mapping->a_ops->is_dirty_writeback) |
| 1448 | − mapping->a_ops->is_dirty_writeback(page, dirty, writeback); | |
| 1454 | + mapping->a_ops->is_dirty_writeback(&folio->page, dirty, writeback); | |
| 1449 | 1455 | } |
| 1450 | 1456 | |
| 1451 | 1457 | static struct page *alloc_demote_page(struct page *page, unsigned long node) |
| @@ -1519,14 +1525,16 @@ retry: · 67 unmodified lines | ||
| 1519 | 1525 | while (!list_empty(page_list)) { |
| 1520 | 1526 | struct address_space *mapping; |
| 1521 | 1527 | struct page *page; |
| 1528 | + struct folio *folio; | |
| 1522 | 1529 | enum page_references references = PAGEREF_RECLAIM; |
| 1523 | 1530 | bool dirty, writeback, may_enter_fs; |
| 1524 | 1531 | unsigned int nr_pages; |
| 1525 | 1532 | |
| 1526 | 1533 | cond_resched(); |
| 1527 | 1534 | |
| 1528 | − page = lru_to_page(page_list); | |
| 1529 | − list_del(&page->lru); | |
| 1535 | + folio = lru_to_folio(page_list); | |
| 1536 | + list_del(&folio->lru); | |
| 1537 | + page = &folio->page; | |
| 1530 | 1538 | |
| 1531 | 1539 | if (!trylock_page(page)) |
| 1532 | 1540 | goto keep; |
| @@ -1552,12 +1560,12 @@ retry: · 19 unmodified lines | ||
| 1552 | 1560 | * reclaim_congested. kswapd will stall and start writing |
| 1553 | 1561 | * pages if the tail of the LRU is all dirty unqueued pages. |
| 1554 | 1562 | */ |
| 1555 | − page_check_dirty_writeback(page, &dirty, &writeback); | |
| 1563 | + folio_check_dirty_writeback(folio, &dirty, &writeback); | |
| 1556 | 1564 | if (dirty || writeback) |
| 1557 | − stat->nr_dirty++; | |
| 1565 | + stat->nr_dirty += nr_pages; | |
| 1558 | 1566 | |
| 1559 | 1567 | if (dirty && !writeback) |
| 1560 | − stat->nr_unqueued_dirty++; | |
| 1568 | + stat->nr_unqueued_dirty += nr_pages; | |
| 1561 | 1569 | |
| 1562 | 1570 | /* |
| 1563 | 1571 | * Treat this page as congested if the underlying BDI is or if |
| @@ -1567,7 +1575,7 @@ retry: · 3 unmodified lines | ||
| 1567 | 1575 | */ |
| 1568 | 1576 | mapping = page_mapping(page); |
| 1569 | 1577 | if (writeback && PageReclaim(page)) |
| 1570 | − stat->nr_congested++; | |
| 1578 | + stat->nr_congested += nr_pages; | |
| 1571 | 1579 | |
| 1572 | 1580 | /* |
| 1573 | 1581 | * If a page at the tail of the LRU is under writeback, there |
| @@ -1616,7 +1624,7 @@ retry: · 42 unmodified lines | ||
| 1616 | 1624 | if (current_is_kswapd() && |
| 1617 | 1625 | PageReclaim(page) && |
| 1618 | 1626 | test_bit(PGDAT_WRITEBACK, &pgdat->flags)) { |
| 1619 | − stat->nr_immediate++; | |
| 1627 | + stat->nr_immediate += nr_pages; | |
| 1620 | 1628 | goto activate_locked; |
| 1621 | 1629 | |
| 1622 | 1630 | /* Case 2 above */ |
| @@ -1634,7 +1642,7 @@ retry: · 11 unmodified lines | ||
| 1634 | 1642 | * and it's also appropriate in global reclaim. |
| 1635 | 1643 | */ |
| 1636 | 1644 | SetPageReclaim(page); |
| 1637 | − stat->nr_writeback++; | |
| 1645 | + stat->nr_writeback += nr_pages; | |
| 1638 | 1646 | goto activate_locked; |
| 1639 | 1647 | |
| 1640 | 1648 | /* Case 3 above */ |
| @@ -1648,7 +1656,7 @@ retry: · 7 unmodified lines | ||
| 1648 | 1656 | } |
| 1649 | 1657 | |
| 1650 | 1658 | if (!ignore_references) |
| 1651 | − references = page_check_references(page, sc); | |
| 1659 | + references = folio_check_references(folio, sc); | |
| 1652 | 1660 | |
| 1653 | 1661 | switch (references) { |
| 1654 | 1662 | case PAGEREF_ACTIVATE: |
| @@ -1681,28 +1689,28 @@ retry: · 26 unmodified lines | ||
| 1681 | 1689 | if (!PageSwapCache(page)) { |
| 1682 | 1690 | if (!(sc->gfp_mask & __GFP_IO)) |
| 1683 | 1691 | goto keep_locked; |
| 1684 | − if (page_maybe_dma_pinned(page)) | |
| 1692 | + if (folio_maybe_dma_pinned(folio)) | |
| 1685 | 1693 | goto keep_locked; |
| 1686 | 1694 | if (PageTransHuge(page)) { |
| 1687 | 1695 | /* cannot split THP, skip it */ |
| 1688 | − if (!can_split_huge_page(page, NULL)) | |
| 1696 | + if (!can_split_folio(folio, NULL)) | |
| 1689 | 1697 | goto activate_locked; |
| 1690 | 1698 | /* |
| 1691 | 1699 | * Split pages without a PMD map right |
| 1692 | 1700 | * away. Chances are some or all of the |
| 1693 | 1701 | * tail pages can be freed without IO. |
| 1694 | 1702 | */ |
| 1695 | − if (!compound_mapcount(page) && | |
| 1696 | − split_huge_page_to_list(page, | |
| 1697 | − page_list)) | |
| 1703 | + if (!folio_entire_mapcount(folio) && | |
| 1704 | + split_folio_to_list(folio, | |
| 1705 | + page_list)) | |
| 1698 | 1706 | goto activate_locked; |
| 1699 | 1707 | } |
| 1700 | 1708 | if (!add_to_swap(page)) { |
| 1701 | 1709 | if (!PageTransHuge(page)) |
| 1702 | 1710 | goto activate_locked_split; |
| 1703 | 1711 | /* Fallback to swap normal pages */ |
| 1704 | − if (split_huge_page_to_list(page, | |
| 1705 | − page_list)) | |
| 1712 | + if (split_folio_to_list(folio, | |
| 1713 | + page_list)) | |
| 1706 | 1714 | goto activate_locked; |
| 1707 | 1715 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
| 1708 | 1716 | count_vm_event(THP_SWPOUT_FALLBACK); |
| @@ -1716,9 +1724,9 @@ retry: · 7 unmodified lines | ||
| 1716 | 1724 | /* Adding to swap updated mapping */ |
| 1717 | 1725 | mapping = page_mapping(page); |
| 1718 | 1726 | } |
| 1719 | − } else if (unlikely(PageTransHuge(page))) { | |
| 1720 | − /* Split file THP */ | |
| 1721 | − if (split_huge_page_to_list(page, page_list)) | |
| 1727 | + } else if (PageSwapBacked(page) && PageTransHuge(page)) { | |
| 1728 | + /* Split shmem THP */ | |
| 1729 | + if (split_folio_to_list(folio, page_list)) | |
| 1722 | 1730 | goto keep_locked; |
| 1723 | 1731 | } |
| 1724 | 1732 | |
| @@ -1742,10 +1750,11 @@ retry: · 17 unmodified lines | ||
| 1742 | 1750 | enum ttu_flags flags = TTU_BATCH_FLUSH; |
| 1743 | 1751 | bool was_swapbacked = PageSwapBacked(page); |
| 1744 | 1752 | |
| 1745 | − if (unlikely(PageTransHuge(page))) | |
| 1753 | + if (PageTransHuge(page) && | |
| 1754 | + thp_order(page) >= HPAGE_PMD_ORDER) | |
| 1746 | 1755 | flags |= TTU_SPLIT_HUGE_PMD; |
| 1747 | 1756 | |
| 1748 | − try_to_unmap(page, flags); | |
| 1757 | + try_to_unmap(folio, flags); | |
| 1749 | 1758 | if (page_mapped(page)) { |
| 1750 | 1759 | stat->nr_unmap_fail += nr_pages; |
| 1751 | 1760 | if (!was_swapbacked && PageSwapBacked(page)) |
| @@ -1793,13 +1802,13 @@ retry: · 41 unmodified lines | ||
| 1793 | 1802 | * starts and then write it out here. |
| 1794 | 1803 | */ |
| 1795 | 1804 | try_to_unmap_flush_dirty(); |
| 1796 | − switch (pageout(page, mapping)) { | |
| 1805 | + switch (pageout(folio, mapping)) { | |
| 1797 | 1806 | case PAGE_KEEP: |
| 1798 | 1807 | goto keep_locked; |
| 1799 | 1808 | case PAGE_ACTIVATE: |
| 1800 | 1809 | goto activate_locked; |
| 1801 | 1810 | case PAGE_SUCCESS: |
| 1802 | − stat->nr_pageout += thp_nr_pages(page); | |
| 1811 | + stat->nr_pageout += nr_pages; | |
| 1803 | 1812 | |
| 1804 | 1813 | if (PageWriteback(page)) |
| 1805 | 1814 | goto keep; |
| @@ -1877,7 +1886,7 @@ retry: · 71 unmodified lines | ||
| 1877 | 1886 | */ |
| 1878 | 1887 | count_vm_event(PGLAZYFREED); |
| 1879 | 1888 | count_memcg_page_event(page, PGLAZYFREED); |
| 1880 | − } else if (!mapping || !__remove_mapping(mapping, page, true, | |
| 1889 | + } else if (!mapping || !__remove_mapping(mapping, folio, true, | |
| 1881 | 1890 | sc->target_mem_cgroup)) |
| 1882 | 1891 | goto keep_locked; |
| 1883 | 1892 | |
| @@ -2132,45 +2141,40 @@ move: · 248 unmodified lines | ||
| 2132 | 2141 | } |
| 2133 | 2142 | |
| 2134 | 2143 | /** |
| 2135 | − * isolate_lru_page - tries to isolate a page from its LRU list | |
| 2136 | − * @page: page to isolate from its LRU list | |
| 2144 | + * folio_isolate_lru() - Try to isolate a folio from its LRU list. | |
| 2145 | + * @folio: Folio to isolate from its LRU list. | |
| 2137 | 2146 | * |
| 2138 | − * Isolates a @page from an LRU list, clears PageLRU and adjusts the | |
| 2139 | − * vmstat statistic corresponding to whatever LRU list the page was on. | |
| 2147 | + * Isolate a @folio from an LRU list and adjust the vmstat statistic | |
| 2148 | + * corresponding to whatever LRU list the folio was on. | |
| 2140 | 2149 | * |
| 2141 | − * Returns 0 if the page was removed from an LRU list. | |
| 2142 | − * Returns -EBUSY if the page was not on an LRU list. | |
| 2143 | − * | |
| 2144 | − * The returned page will have PageLRU() cleared. If it was found on | |
| 2145 | − * the active list, it will have PageActive set. If it was found on | |
| 2146 | − * the unevictable list, it will have the PageUnevictable bit set. That flag | |
| 2150 | + * The folio will have its LRU flag cleared. If it was found on the | |
| 2151 | + * active list, it will have the Active flag set. If it was found on the | |
| 2152 | + * unevictable list, it will have the Unevictable flag set. These flags | |
| 2147 | 2153 | * may need to be cleared by the caller before letting the page go. |
| 2148 | 2154 | * |
| 2149 | − * The vmstat statistic corresponding to the list on which the page was | |
| 2150 | − * found will be decremented. | |
| 2151 | − * | |
| 2152 | − * Restrictions: | |
| 2155 | + * Context: | |
| 2153 | 2156 | * |
| 2154 | 2157 | * (1) Must be called with an elevated refcount on the page. This is a |
| 2155 | − * fundamental difference from isolate_lru_pages (which is called | |
| 2158 | + * fundamental difference from isolate_lru_pages() (which is called | |
| 2156 | 2159 | * without a stable reference). |
| 2157 | − * (2) the lru_lock must not be held. | |
| 2158 | − * (3) interrupts must be enabled. | |
| 2160 | + * (2) The lru_lock must not be held. | |
| 2161 | + * (3) Interrupts must be enabled. | |
| 2162 | + * | |
| 2163 | + * Return: 0 if the folio was removed from an LRU list. | |
| 2164 | + * -EBUSY if the folio was not on an LRU list. | |
| 2159 | 2165 | */ |
| 2160 | −int isolate_lru_page(struct page *page) | |
| 2166 | +int folio_isolate_lru(struct folio *folio) | |
| 2161 | 2167 | { |
| 2162 | − struct folio *folio = page_folio(page); | |
| 2163 | 2168 | int ret = -EBUSY; |
| 2164 | 2169 | |
| 2165 | − VM_BUG_ON_PAGE(!page_count(page), page); | |
| 2166 | − WARN_RATELIMIT(PageTail(page), "trying to isolate tail page"); | |
| 2170 | + VM_BUG_ON_FOLIO(!folio_ref_count(folio), folio); | |
| 2167 | 2171 | |
| 2168 | − if (TestClearPageLRU(page)) { | |
| 2172 | + if (folio_test_clear_lru(folio)) { | |
| 2169 | 2173 | struct lruvec *lruvec; |
| 2170 | 2174 | |
| 2171 | − get_page(page); | |
| 2175 | + folio_get(folio); | |
| 2172 | 2176 | lruvec = folio_lruvec_lock_irq(folio); |
| 2173 | − del_page_from_lru_list(page, lruvec); | |
| 2177 | + lruvec_del_folio(lruvec, folio); | |
| 2174 | 2178 | unlock_page_lruvec_irq(lruvec); |
| 2175 | 2179 | ret = 0; |
| 2176 | 2180 | } |
| @@ -2406,7 +2410,7 @@ shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec, · 229 unmodified lines | ||
| 2406 | 2410 | * |
| 2407 | 2411 | * If the pages are mostly unmapped, the processing is fast and it is |
| 2408 | 2412 | * appropriate to hold lru_lock across the whole operation. But if |
| 2409 | − * the pages are mapped, the processing is slow (page_referenced()), so | |
| 2413 | + * the pages are mapped, the processing is slow (folio_referenced()), so | |
| 2410 | 2414 | * we should drop lru_lock around each page. It's impossible to balance |
| 2411 | 2415 | * this, so instead we remove the pages from the LRU while processing them. |
| 2412 | 2416 | * It is safe to rely on PG_active against the non-LRU pages in here because |
| @@ -2426,7 +2430,6 @@ static void shrink_active_list(unsigned long nr_to_scan, · 13 unmodified lines | ||
| 2426 | 2430 | LIST_HEAD(l_hold); /* The pages which were snipped off */ |
| 2427 | 2431 | LIST_HEAD(l_active); |
| 2428 | 2432 | LIST_HEAD(l_inactive); |
| 2429 | − struct page *page; | |
| 2430 | 2433 | unsigned nr_deactivate, nr_activate; |
| 2431 | 2434 | unsigned nr_rotated = 0; |
| 2432 | 2435 | int file = is_file_lru(lru); |
| @@ -2448,9 +2451,13 @@ static void shrink_active_list(unsigned long nr_to_scan, · 15 unmodified lines | ||
| 2448 | 2451 | spin_unlock_irq(&lruvec->lru_lock); |
| 2449 | 2452 | |
| 2450 | 2453 | while (!list_empty(&l_hold)) { |
| 2454 | + struct folio *folio; | |
| 2455 | + struct page *page; | |
| 2456 | + | |
| 2451 | 2457 | cond_resched(); |
| 2452 | − page = lru_to_page(&l_hold); | |
| 2453 | − list_del(&page->lru); | |
| 2458 | + folio = lru_to_folio(&l_hold); | |
| 2459 | + list_del(&folio->lru); | |
| 2460 | + page = &folio->page; | |
| 2454 | 2461 | |
| 2455 | 2462 | if (unlikely(!page_evictable(page))) { |
| 2456 | 2463 | putback_lru_page(page); |
| @@ -2465,8 +2472,8 @@ static void shrink_active_list(unsigned long nr_to_scan, · 8 unmodified lines | ||
| 2465 | 2472 | } |
| 2466 | 2473 | } |
| 2467 | 2474 | |
| 2468 | − if (page_referenced(page, 0, sc->target_mem_cgroup, | |
| 2469 | − &vm_flags)) { | |
| 2475 | + if (folio_referenced(folio, 0, sc->target_mem_cgroup, | |
| 2476 | + &vm_flags)) { | |
| 2470 | 2477 | /* |
| 2471 | 2478 | * Identify referenced, file-backed active pages and |
| 2472 | 2479 | * give them one more trip around the active list. So |
| @@ -245,31 +245,32 @@ void workingset_age_nonresident(struct lruvec *lruvec, unsigned long nr_pages) · 244 unmodified lines | ||
| 245 | 245 | } |
| 246 | 246 | |
| 247 | 247 | /** |
| 248 | − * workingset_eviction - note the eviction of a page from memory | |
| 248 | + * workingset_eviction - note the eviction of a folio from memory | |
| 249 | 249 | * @target_memcg: the cgroup that is causing the reclaim |
| 250 | − * @page: the page being evicted | |
| 250 | + * @folio: the folio being evicted | |
| 251 | 251 | * |
| 252 | − * Return: a shadow entry to be stored in @page->mapping->i_pages in place | |
| 253 | − * of the evicted @page so that a later refault can be detected. | |
| 252 | + * Return: a shadow entry to be stored in @folio->mapping->i_pages in place | |
| 253 | + * of the evicted @folio so that a later refault can be detected. | |
| 254 | 254 | */ |
| 255 | −void *workingset_eviction(struct page *page, struct mem_cgroup *target_memcg) | |
| 255 | +void *workingset_eviction(struct folio *folio, struct mem_cgroup *target_memcg) | |
| 256 | 256 | { |
| 257 | − struct pglist_data *pgdat = page_pgdat(page); | |
| 257 | + struct pglist_data *pgdat = folio_pgdat(folio); | |
| 258 | 258 | unsigned long eviction; |
| 259 | 259 | struct lruvec *lruvec; |
| 260 | 260 | int memcgid; |
| 261 | 261 | |
| 262 | − /* Page is fully exclusive and pins page's memory cgroup pointer */ | |
| 263 | − VM_BUG_ON_PAGE(PageLRU(page), page); | |
| 264 | − VM_BUG_ON_PAGE(page_count(page), page); | |
| 265 | − VM_BUG_ON_PAGE(!PageLocked(page), page); | |
| 262 | + /* Folio is fully exclusive and pins folio's memory cgroup pointer */ | |
| 263 | + VM_BUG_ON_FOLIO(folio_test_lru(folio), folio); | |
| 264 | + VM_BUG_ON_FOLIO(folio_ref_count(folio), folio); | |
| 265 | + VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio); | |
| 266 | 266 | |
| 267 | 267 | lruvec = mem_cgroup_lruvec(target_memcg, pgdat); |
| 268 | 268 | /* XXX: target_memcg can be NULL, go through lruvec */ |
| 269 | 269 | memcgid = mem_cgroup_id(lruvec_memcg(lruvec)); |
| 270 | 270 | eviction = atomic_long_read(&lruvec->nonresident_age); |
| 271 | − workingset_age_nonresident(lruvec, thp_nr_pages(page)); | |
| 272 | − return pack_shadow(memcgid, pgdat, eviction, PageWorkingset(page)); | |
| 271 | + workingset_age_nonresident(lruvec, folio_nr_pages(folio)); | |
| 272 | + return pack_shadow(memcgid, pgdat, eviction, | |
| 273 | + folio_test_workingset(folio)); | |
| 273 | 274 | } |
| 274 | 275 | |
| 275 | 276 | /** |
| @@ -26,15 +26,17 @@ · 25 unmodified lines | ||
| 26 | 26 | #define PAGEMAP_PFN(ent) ((ent) & ((1ull << 55) - 1)) |
| 27 | 27 | |
| 28 | 28 | int pagemap_fd; |
| 29 | +int backing_fd = -1; | |
| 30 | +int mmap_flags = MAP_ANONYMOUS | MAP_NORESERVE | MAP_PRIVATE; | |
| 31 | +#define PROT_RW (PROT_READ | PROT_WRITE) | |
| 29 | 32 | |
| 30 | 33 | int64_t allocate_transhuge(void *ptr) |
| 31 | 34 | { |
| 32 | 35 | uint64_t ent[2]; |
| 33 | 36 | |
| 34 | 37 | /* drop pmd */ |
| 35 | − if (mmap(ptr, HPAGE_SIZE, PROT_READ | PROT_WRITE, | |
| 36 | − MAP_FIXED | MAP_ANONYMOUS | | |
| 37 | − MAP_NORESERVE | MAP_PRIVATE, -1, 0) != ptr) | |
| 38 | + if (mmap(ptr, HPAGE_SIZE, PROT_RW, MAP_FIXED | mmap_flags, | |
| 39 | + backing_fd, 0) != ptr) | |
| 38 | 40 | errx(2, "mmap transhuge"); |
| 39 | 41 | |
| 40 | 42 | if (madvise(ptr, HPAGE_SIZE, MADV_HUGEPAGE)) |
| @@ -60,6 +62,8 @@ int main(int argc, char **argv) · 19 unmodified lines | ||
| 60 | 62 | size_t ram, len; |
| 61 | 63 | void *ptr, *p; |
| 62 | 64 | struct timespec a, b; |
| 65 | + int i = 0; | |
| 66 | + char *name = NULL; | |
| 63 | 67 | double s; |
| 64 | 68 | uint8_t *map; |
| 65 | 69 | size_t map_len; |
| @@ -69,13 +73,23 @@ int main(int argc, char **argv) · 3 unmodified lines | ||
| 69 | 73 | ram = SIZE_MAX / 4; |
| 70 | 74 | else |
| 71 | 75 | ram *= sysconf(_SC_PAGESIZE); |
| 76 | + len = ram; | |
| 77 | + | |
| 78 | + while (++i < argc) { | |
| 79 | + if (!strcmp(argv[i], "-h")) | |
| 80 | + errx(1, "usage: %s [size in MiB]", argv[0]); | |
| 81 | + else if (!strcmp(argv[i], "-f")) | |
| 82 | + name = argv[++i]; | |
| 83 | + else | |
| 84 | + len = atoll(argv[i]) << 20; | |
| 85 | + } | |
| 72 | 86 | |
| 73 | − if (argc == 1) | |
| 74 | − len = ram; | |
| 75 | − else if (!strcmp(argv[1], "-h")) | |
| 76 | − errx(1, "usage: %s [size in MiB]", argv[0]); | |
| 77 | − else | |
| 78 | − len = atoll(argv[1]) << 20; | |
| 87 | + if (name) { | |
| 88 | + backing_fd = open(name, O_RDWR); | |
| 89 | + if (backing_fd == -1) | |
| 90 | + errx(2, "open %s", name); | |
| 91 | + mmap_flags = MAP_SHARED; | |
| 92 | + } | |
| 79 | 93 | |
| 80 | 94 | warnx("allocate %zd transhuge pages, using %zd MiB virtual memory" |
| 81 | 95 | " and %zd MiB of ram", len >> HPAGE_SHIFT, len >> 20, |
| @@ -86,8 +100,7 @@ int main(int argc, char **argv) · 4 unmodified lines | ||
| 86 | 100 | err(2, "open pagemap"); |
| 87 | 101 | |
| 88 | 102 | len -= len % HPAGE_SIZE; |
| 89 | − ptr = mmap(NULL, len + HPAGE_SIZE, PROT_READ | PROT_WRITE, | |
| 90 | − MAP_ANONYMOUS | MAP_NORESERVE | MAP_PRIVATE, -1, 0); | |
| 103 | + ptr = mmap(NULL, len + HPAGE_SIZE, PROT_RW, mmap_flags, backing_fd, 0); | |
| 91 | 104 | if (ptr == MAP_FAILED) |
| 92 | 105 | err(2, "initial mmap"); |
| 93 | 106 | ptr += HPAGE_SIZE - (uintptr_t)ptr % HPAGE_SIZE; |