Message ID | 20210427161317.50682-17-peterx@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | userfaultfd-wp: Support shmem and hugetlbfs | expand |
On Tue, Apr 27, 2021 at 12:13:09PM -0400, Peter Xu wrote: > Hook up hugetlbfs_fault() with the capability to handle userfaultfd-wp faults. > > We do this slightly earlier than hugetlb_cow() so that we can avoid taking some > extra locks that we definitely don't need. > > Reviewed-by: Mike Kravetz <mike.kravetz@oracle.com> > Signed-off-by: Peter Xu <peterx@redhat.com> > --- > mm/hugetlb.c | 19 +++++++++++++++++++ > 1 file changed, 19 insertions(+) > > diff --git a/mm/hugetlb.c b/mm/hugetlb.c > index 629aa4c2259c8..8e234ee9a15e2 100644 > --- a/mm/hugetlb.c > +++ b/mm/hugetlb.c > @@ -4802,6 +4802,25 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, > if (unlikely(!pte_same(entry, huge_ptep_get(ptep)))) > goto out_ptl; > > + /* Handle userfault-wp first, before trying to lock more pages */ > + if (userfaultfd_pte_wp(vma, huge_ptep_get(ptep)) && I'm going to change this to: - if (userfaultfd_pte_wp(vma, huge_ptep_get(ptep)) && + if (userfaultfd_wp(vma) && huge_pte_uffd_wp(huge_ptep_get(ptep)) && As strictly speaking it's not right to use userfaultfd_pte_wp() directly on a huge pte... Currently huge_pte_uffd_wp() is missing in this version (which is still pte_uffd_wp() anyways), but I'll add a separate patch to introduce all these helpers (also mention about what arch should do when the huge pte is not handled the same way as small pte). I'll try to keep Mike's R-b as this change should be trivial, or please shoot. Thanks, > + (flags & FAULT_FLAG_WRITE) && !huge_pte_write(entry)) { > + struct vm_fault vmf = { > + .vma = vma, > + .address = haddr, > + .flags = flags, > + }; > + > + spin_unlock(ptl); > + if (pagecache_page) { > + unlock_page(pagecache_page); > + put_page(pagecache_page); > + } > + mutex_unlock(&hugetlb_fault_mutex_table[hash]); > + i_mmap_unlock_read(mapping); > + return handle_userfault(&vmf, VM_UFFD_WP); > + } > + > /* > * hugetlb_cow() requires page locks of pte_page(entry) and > * pagecache_page, so here we need take the former one > -- > 2.26.2 >
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 629aa4c2259c8..8e234ee9a15e2 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -4802,6 +4802,25 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, if (unlikely(!pte_same(entry, huge_ptep_get(ptep)))) goto out_ptl; + /* Handle userfault-wp first, before trying to lock more pages */ + if (userfaultfd_pte_wp(vma, huge_ptep_get(ptep)) && + (flags & FAULT_FLAG_WRITE) && !huge_pte_write(entry)) { + struct vm_fault vmf = { + .vma = vma, + .address = haddr, + .flags = flags, + }; + + spin_unlock(ptl); + if (pagecache_page) { + unlock_page(pagecache_page); + put_page(pagecache_page); + } + mutex_unlock(&hugetlb_fault_mutex_table[hash]); + i_mmap_unlock_read(mapping); + return handle_userfault(&vmf, VM_UFFD_WP); + } + /* * hugetlb_cow() requires page locks of pte_page(entry) and * pagecache_page, so here we need take the former one