mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 13:22:23 +00:00
mm/huge_memory: batch rmap operations in __split_huge_pmd_locked()
Let's use folio_add_anon_rmap_ptes(), batching the rmap operations. While at it, use more folio operations (but only in the code branch we're touching), use VM_WARN_ON_FOLIO(), and pass RMAP_EXCLUSIVE instead of manually setting PageAnonExclusive. We should never see non-anon pages on that branch: otherwise, the existing page_add_anon_rmap() call would have been flawed already. Link: https://lkml.kernel.org/r/20231220224504.646757-16-david@redhat.com Signed-off-by: David Hildenbrand <david@redhat.com> Reviewed-by: Yin Fengwei <fengwei.yin@intel.com> Cc: Hugh Dickins <hughd@google.com> Cc: Matthew Wilcox (Oracle) <willy@infradead.org> Cc: Muchun Song <muchun.song@linux.dev> Cc: Muchun Song <songmuchun@bytedance.com> Cc: Peter Xu <peterx@redhat.com> Cc: Ryan Roberts <ryan.roberts@arm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
8bd5130070
commit
91b2978a34
@ -2398,6 +2398,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
|
||||
unsigned long haddr, bool freeze)
|
||||
{
|
||||
struct mm_struct *mm = vma->vm_mm;
|
||||
struct folio *folio;
|
||||
struct page *page;
|
||||
pgtable_t pgtable;
|
||||
pmd_t old_pmd, _pmd;
|
||||
@ -2493,16 +2494,18 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
|
||||
uffd_wp = pmd_swp_uffd_wp(old_pmd);
|
||||
} else {
|
||||
page = pmd_page(old_pmd);
|
||||
folio = page_folio(page);
|
||||
if (pmd_dirty(old_pmd)) {
|
||||
dirty = true;
|
||||
SetPageDirty(page);
|
||||
folio_set_dirty(folio);
|
||||
}
|
||||
write = pmd_write(old_pmd);
|
||||
young = pmd_young(old_pmd);
|
||||
soft_dirty = pmd_soft_dirty(old_pmd);
|
||||
uffd_wp = pmd_uffd_wp(old_pmd);
|
||||
|
||||
VM_BUG_ON_PAGE(!page_count(page), page);
|
||||
VM_WARN_ON_FOLIO(!folio_ref_count(folio), folio);
|
||||
VM_WARN_ON_FOLIO(!folio_test_anon(folio), folio);
|
||||
|
||||
/*
|
||||
* Without "freeze", we'll simply split the PMD, propagating the
|
||||
@ -2519,11 +2522,18 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
|
||||
*
|
||||
* See page_try_share_anon_rmap(): invalidate PMD first.
|
||||
*/
|
||||
anon_exclusive = PageAnon(page) && PageAnonExclusive(page);
|
||||
anon_exclusive = PageAnonExclusive(page);
|
||||
if (freeze && anon_exclusive && page_try_share_anon_rmap(page))
|
||||
freeze = false;
|
||||
if (!freeze)
|
||||
page_ref_add(page, HPAGE_PMD_NR - 1);
|
||||
if (!freeze) {
|
||||
rmap_t rmap_flags = RMAP_NONE;
|
||||
|
||||
folio_ref_add(folio, HPAGE_PMD_NR - 1);
|
||||
if (anon_exclusive)
|
||||
rmap_flags |= RMAP_EXCLUSIVE;
|
||||
folio_add_anon_rmap_ptes(folio, page, HPAGE_PMD_NR,
|
||||
vma, haddr, rmap_flags);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2566,8 +2576,6 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
|
||||
entry = mk_pte(page + i, READ_ONCE(vma->vm_page_prot));
|
||||
if (write)
|
||||
entry = pte_mkwrite(entry, vma);
|
||||
if (anon_exclusive)
|
||||
SetPageAnonExclusive(page + i);
|
||||
if (!young)
|
||||
entry = pte_mkold(entry);
|
||||
/* NOTE: this may set soft-dirty too on some archs */
|
||||
@ -2577,7 +2585,6 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
|
||||
entry = pte_mksoft_dirty(entry);
|
||||
if (uffd_wp)
|
||||
entry = pte_mkuffd_wp(entry);
|
||||
page_add_anon_rmap(page + i, vma, addr, RMAP_NONE);
|
||||
}
|
||||
VM_BUG_ON(!pte_none(ptep_get(pte)));
|
||||
set_pte_at(mm, addr, pte, entry);
|
||||
|
Loading…
Reference in New Issue
Block a user