mm/rmap: introduce and use hugetlb_add_file_rmap()
hugetlb rmap handling differs quite a lot from "ordinary" rmap code. For example, hugetlb currently only supports entire mappings, and treats any mapping as mapped using a single "logical PTE". Let's move it out of the way so we can overhaul our "ordinary" rmap. implementation/interface. Right now we're using page_dup_file_rmap() in some cases where "ordinary" rmap code would have used page_add_file_rmap(). So let's introduce and use hugetlb_add_file_rmap() instead. We won't be adding a "hugetlb_dup_file_rmap()" functon for the fork() case, as it would be doing the same: "dup" is just an optimization for "add". What remains is a single page_dup_file_rmap() call in fork() code. Add sanity checks that we end up with the right folios in the right functions. Link: https://lkml.kernel.org/r/20231220224504.646757-4-david@redhat.com Signed-off-by: David Hildenbrand <david@redhat.com> Reviewed-by: Yin Fengwei <fengwei.yin@intel.com> Reviewed-by: Ryan Roberts <ryan.roberts@arm.com> Reviewed-by: Muchun Song <songmuchun@bytedance.com> Cc: Hugh Dickins <hughd@google.com> Cc: Matthew Wilcox (Oracle) <willy@infradead.org> Cc: Muchun Song <muchun.song@linux.dev> Cc: Peter Xu <peterx@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
e135826b2d
commit
44887f3994
@ -211,6 +211,14 @@ void hugetlb_add_anon_rmap(struct folio *, struct vm_area_struct *,
|
||||
void hugetlb_add_new_anon_rmap(struct folio *, struct vm_area_struct *,
|
||||
unsigned long address);
|
||||
|
||||
static inline void hugetlb_add_file_rmap(struct folio *folio)
|
||||
{
|
||||
VM_WARN_ON_FOLIO(!folio_test_hugetlb(folio), folio);
|
||||
VM_WARN_ON_FOLIO(folio_test_anon(folio), folio);
|
||||
|
||||
atomic_inc(&folio->_entire_mapcount);
|
||||
}
|
||||
|
||||
static inline void hugetlb_remove_rmap(struct folio *folio)
|
||||
{
|
||||
VM_WARN_ON_FOLIO(!folio_test_hugetlb(folio), folio);
|
||||
|
@ -5408,7 +5408,7 @@ again:
|
||||
* sleep during the process.
|
||||
*/
|
||||
if (!folio_test_anon(pte_folio)) {
|
||||
page_dup_file_rmap(&pte_folio->page, true);
|
||||
hugetlb_add_file_rmap(pte_folio);
|
||||
} else if (page_try_dup_anon_rmap(&pte_folio->page,
|
||||
true, src_vma)) {
|
||||
pte_t src_pte_old = entry;
|
||||
@ -6279,7 +6279,7 @@ static vm_fault_t hugetlb_no_page(struct mm_struct *mm,
|
||||
if (anon_rmap)
|
||||
hugetlb_add_new_anon_rmap(folio, vma, haddr);
|
||||
else
|
||||
page_dup_file_rmap(&folio->page, true);
|
||||
hugetlb_add_file_rmap(folio);
|
||||
new_pte = make_huge_pte(vma, &folio->page, ((vma->vm_flags & VM_WRITE)
|
||||
&& (vma->vm_flags & VM_SHARED)));
|
||||
/*
|
||||
@ -6730,7 +6730,7 @@ int hugetlb_mfill_atomic_pte(pte_t *dst_pte,
|
||||
goto out_release_unlock;
|
||||
|
||||
if (folio_in_pagecache)
|
||||
page_dup_file_rmap(&folio->page, true);
|
||||
hugetlb_add_file_rmap(folio);
|
||||
else
|
||||
hugetlb_add_new_anon_rmap(folio, dst_vma, dst_addr);
|
||||
|
||||
|
@ -252,7 +252,7 @@ static bool remove_migration_pte(struct folio *folio,
|
||||
hugetlb_add_anon_rmap(folio, vma, pvmw.address,
|
||||
rmap_flags);
|
||||
else
|
||||
page_dup_file_rmap(new, true);
|
||||
hugetlb_add_file_rmap(folio);
|
||||
set_huge_pte_at(vma->vm_mm, pvmw.address, pvmw.pte, pte,
|
||||
psize);
|
||||
} else
|
||||
|
@ -1395,6 +1395,7 @@ void folio_add_file_rmap_range(struct folio *folio, struct page *page,
|
||||
unsigned int nr_pmdmapped = 0, first;
|
||||
int nr = 0;
|
||||
|
||||
VM_WARN_ON_FOLIO(folio_test_hugetlb(folio), folio);
|
||||
VM_WARN_ON_FOLIO(compound && !folio_test_pmd_mappable(folio), folio);
|
||||
|
||||
/* Is page being mapped by PTE? Is this its first map to be added? */
|
||||
|
Loading…
Reference in New Issue
Block a user