Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 28 additions & 18 deletions mm/rmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1845,23 +1845,32 @@ void folio_remove_rmap_pud(struct folio *folio, struct page *page,
#endif
}

/* We support batch unmapping of PTEs for lazyfree large folios */
static inline bool can_batch_unmap_folio_ptes(unsigned long addr,
struct folio *folio, pte_t *ptep)
static inline unsigned int folio_unmap_pte_batch(struct folio *folio,
struct page_vma_mapped_walk *pvmw,
enum ttu_flags flags, pte_t pte)
{
const fpb_t fpb_flags = FPB_IGNORE_DIRTY | FPB_IGNORE_SOFT_DIRTY;
int max_nr = folio_nr_pages(folio);
pte_t pte = ptep_get(ptep);
unsigned long end_addr, addr = pvmw->address;
struct vm_area_struct *vma = pvmw->vma;
unsigned int max_nr;

if (flags & TTU_HWPOISON)
return 1;
if (!folio_test_large(folio))
return 1;

/* We may only batch within a single VMA and a single page table. */
end_addr = pmd_addr_end(addr, vma->vm_end);
max_nr = (end_addr - addr) >> PAGE_SHIFT;

/* We only support lazyfree batching for now ... */
if (!folio_test_anon(folio) || folio_test_swapbacked(folio))
return false;
return 1;
if (pte_unused(pte))
return false;
if (pte_pfn(pte) != folio_pfn(folio))
return false;
return 1;

return folio_pte_batch(folio, addr, ptep, pte, max_nr, fpb_flags, NULL,
NULL, NULL) == max_nr;
return folio_pte_batch(folio, addr, pvmw->pte, pte, max_nr, fpb_flags,
NULL, NULL, NULL);
}

/*
Expand Down Expand Up @@ -2024,9 +2033,7 @@ static bool try_to_unmap_one(struct folio *folio, struct vm_area_struct *vma,
if (pte_dirty(pteval))
folio_mark_dirty(folio);
} else if (likely(pte_present(pteval))) {
if (folio_test_large(folio) && !(flags & TTU_HWPOISON) &&
can_batch_unmap_folio_ptes(address, folio, pvmw.pte))
nr_pages = folio_nr_pages(folio);
nr_pages = folio_unmap_pte_batch(folio, &pvmw, flags, pteval);
end_addr = address + nr_pages * PAGE_SIZE;
flush_cache_range(vma, address, end_addr);

Expand Down Expand Up @@ -2206,13 +2213,16 @@ static bool try_to_unmap_one(struct folio *folio, struct vm_area_struct *vma,
hugetlb_remove_rmap(folio);
} else {
folio_remove_rmap_ptes(folio, subpage, nr_pages, vma);
folio_ref_sub(folio, nr_pages - 1);
}
if (vma->vm_flags & VM_LOCKED)
mlock_drain_local();
folio_put(folio);
/* We have already batched the entire folio */
if (nr_pages > 1)
folio_put_refs(folio, nr_pages);

/*
* If we are sure that we batched the entire folio and cleared
* all PTEs, we can just optimize and stop right here.
*/
if (nr_pages == folio_nr_pages(folio))
goto walk_done;
continue;
walk_abort:
Expand Down
Loading