We've have multiple (and more coming) places that would like to find a
userfault enabled VMA from a mm struct that covers a specific memory
range.  This patch introduce the helper for it, meanwhile apply it to
the code.

Suggested-by: Mike Rapoport <r...@linux.vnet.ibm.com>
Reviewed-by: Jerome Glisse <jgli...@redhat.com>
Reviewed-by: Mike Rapoport <r...@linux.vnet.ibm.com>
Signed-off-by: Peter Xu <pet...@redhat.com>
---
 mm/userfaultfd.c | 54 +++++++++++++++++++++++++++---------------------
 1 file changed, 30 insertions(+), 24 deletions(-)

diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
index 5363376cb07a..6b9dd5b66f64 100644
--- a/mm/userfaultfd.c
+++ b/mm/userfaultfd.c
@@ -20,6 +20,34 @@
 #include <asm/tlbflush.h>
 #include "internal.h"
 
+/*
+ * Find a valid userfault enabled VMA region that covers the whole
+ * address range, or NULL on failure.  Must be called with mmap_sem
+ * held.
+ */
+static struct vm_area_struct *vma_find_uffd(struct mm_struct *mm,
+                                           unsigned long start,
+                                           unsigned long len)
+{
+       struct vm_area_struct *vma = find_vma(mm, start);
+
+       if (!vma)
+               return NULL;
+
+       /*
+        * Check the vma is registered in uffd, this is required to
+        * enforce the VM_MAYWRITE check done at uffd registration
+        * time.
+        */
+       if (!vma->vm_userfaultfd_ctx.ctx)
+               return NULL;
+
+       if (start < vma->vm_start || start + len > vma->vm_end)
+               return NULL;
+
+       return vma;
+}
+
 static int mcopy_atomic_pte(struct mm_struct *dst_mm,
                            pmd_t *dst_pmd,
                            struct vm_area_struct *dst_vma,
@@ -228,20 +256,9 @@ static __always_inline ssize_t 
__mcopy_atomic_hugetlb(struct mm_struct *dst_mm,
         */
        if (!dst_vma) {
                err = -ENOENT;
-               dst_vma = find_vma(dst_mm, dst_start);
+               dst_vma = vma_find_uffd(dst_mm, dst_start, len);
                if (!dst_vma || !is_vm_hugetlb_page(dst_vma))
                        goto out_unlock;
-               /*
-                * Check the vma is registered in uffd, this is
-                * required to enforce the VM_MAYWRITE check done at
-                * uffd registration time.
-                */
-               if (!dst_vma->vm_userfaultfd_ctx.ctx)
-                       goto out_unlock;
-
-               if (dst_start < dst_vma->vm_start ||
-                   dst_start + len > dst_vma->vm_end)
-                       goto out_unlock;
 
                err = -EINVAL;
                if (vma_hpagesize != vma_kernel_pagesize(dst_vma))
@@ -487,20 +504,9 @@ static __always_inline ssize_t __mcopy_atomic(struct 
mm_struct *dst_mm,
         * both valid and fully within a single existing vma.
         */
        err = -ENOENT;
-       dst_vma = find_vma(dst_mm, dst_start);
+       dst_vma = vma_find_uffd(dst_mm, dst_start, len);
        if (!dst_vma)
                goto out_unlock;
-       /*
-        * Check the vma is registered in uffd, this is required to
-        * enforce the VM_MAYWRITE check done at uffd registration
-        * time.
-        */
-       if (!dst_vma->vm_userfaultfd_ctx.ctx)
-               goto out_unlock;
-
-       if (dst_start < dst_vma->vm_start ||
-           dst_start + len > dst_vma->vm_end)
-               goto out_unlock;
 
        err = -EINVAL;
        /*
-- 
2.21.0

Reply via email to