Signed-off-by: Nikita Kalyazin <kalya...@amazon.com>
---
 include/linux/userfaultfd_k.h | 13 ++++++-------
 mm/userfaultfd.c              | 10 +++++++---
 2 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/include/linux/userfaultfd_k.h b/include/linux/userfaultfd_k.h
index 75342022d144..64551e8a55fb 100644
--- a/include/linux/userfaultfd_k.h
+++ b/include/linux/userfaultfd_k.h
@@ -221,8 +221,8 @@ static inline bool vma_can_userfault(struct vm_area_struct 
*vma,
        if (vm_flags & VM_DROPPABLE)
                return false;
 
-       if ((vm_flags & VM_UFFD_MINOR) &&
-           (!is_vm_hugetlb_page(vma) && !vma_is_shmem(vma)))
+       if (!vma->vm_ops->can_userfault ||
+           !vma->vm_ops->can_userfault(vma, VM_UFFD_MINOR))
                return false;
 
        /*
@@ -235,16 +235,15 @@ static inline bool vma_can_userfault(struct 
vm_area_struct *vma,
 #ifndef CONFIG_PTE_MARKER_UFFD_WP
        /*
         * If user requested uffd-wp but not enabled pte markers for
-        * uffd-wp, then shmem & hugetlbfs are not supported but only
-        * anonymous.
+        * uffd-wp, then only anonymous is supported.
         */
        if ((vm_flags & VM_UFFD_WP) && !vma_is_anonymous(vma))
                return false;
 #endif
 
-       /* By default, allow any of anon|shmem|hugetlb */
-       return vma_is_anonymous(vma) || is_vm_hugetlb_page(vma) ||
-           vma_is_shmem(vma);
+       return vma_is_anonymous(vma) ||
+           (vma->vm_ops->can_userfault &&
+            vma->vm_ops->can_userfault(vma, vm_flags));
 }
 
 static inline bool vma_has_uffd_without_event_remap(struct vm_area_struct *vma)
diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
index 4b3dbc7dac64..0aa82c968e16 100644
--- a/mm/userfaultfd.c
+++ b/mm/userfaultfd.c
@@ -728,6 +728,7 @@ static __always_inline ssize_t mfill_atomic(struct 
userfaultfd_ctx *ctx,
        unsigned long src_addr, dst_addr;
        long copied;
        struct folio *folio;
+       bool can_userfault;
 
        /*
         * Sanitize the command parameters:
@@ -787,10 +788,13 @@ static __always_inline ssize_t mfill_atomic(struct 
userfaultfd_ctx *ctx,
                return  mfill_atomic_hugetlb(ctx, dst_vma, dst_start,
                                             src_start, len, flags);
 
-       if (!vma_is_anonymous(dst_vma) && !vma_is_shmem(dst_vma))
+       can_userfault = dst_vma->vm_ops->can_userfault &&
+           dst_vma->vm_ops->can_userfault(dst_vma, __VM_UFFD_FLAGS);
+
+       if (!vma_is_anonymous(dst_vma) && !can_userfault)
                goto out_unlock;
-       if (!vma_is_shmem(dst_vma) &&
-           uffd_flags_mode_is(flags, MFILL_ATOMIC_CONTINUE))
+
+       if (!can_userfault && uffd_flags_mode_is(flags, MFILL_ATOMIC_CONTINUE))
                goto out_unlock;
 
        while (src_addr < src_start + len) {
-- 
2.47.1


Reply via email to