We've had all the necessary changes ready for both shmem and hugetlbfs.  Turn
on all the shmem/hugetlbfs switches for userfaultfd-wp.

Now we can remove the flags parameter for vma_can_userfault() since not used
any more.  Meanwhile, we can expand UFFD_API_RANGE_IOCTLS_BASIC with
_UFFDIO_WRITEPROTECT too because all existing types now support write
protection mode.

Since vma_can_userfault() will be used elsewhere, move into userfaultfd_k.h.

Signed-off-by: Peter Xu <pet...@redhat.com>
---
 fs/userfaultfd.c                 | 17 ++++-------------
 include/linux/userfaultfd_k.h    |  7 +++++++
 include/uapi/linux/userfaultfd.h |  3 ++-
 mm/userfaultfd.c                 | 10 +++-------
 4 files changed, 16 insertions(+), 21 deletions(-)

diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index 3264ec46242b..88ad90fc8539 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -1307,15 +1307,6 @@ static __always_inline int validate_range(struct 
mm_struct *mm,
        return 0;
 }
 
-static inline bool vma_can_userfault(struct vm_area_struct *vma,
-                                    unsigned long vm_flags)
-{
-       /* FIXME: add WP support to hugetlbfs and shmem */
-       return vma_is_anonymous(vma) ||
-               ((is_vm_hugetlb_page(vma) || vma_is_shmem(vma)) &&
-                !(vm_flags & VM_UFFD_WP));
-}
-
 static int userfaultfd_register(struct userfaultfd_ctx *ctx,
                                unsigned long arg)
 {
@@ -1394,7 +1385,7 @@ static int userfaultfd_register(struct userfaultfd_ctx 
*ctx,
 
                /* check not compatible vmas */
                ret = -EINVAL;
-               if (!vma_can_userfault(cur, vm_flags))
+               if (!vma_can_userfault(cur))
                        goto out_unlock;
 
                /*
@@ -1453,7 +1444,7 @@ static int userfaultfd_register(struct userfaultfd_ctx 
*ctx,
        do {
                cond_resched();
 
-               BUG_ON(!vma_can_userfault(vma, vm_flags));
+               BUG_ON(!vma_can_userfault(vma));
                BUG_ON(vma->vm_userfaultfd_ctx.ctx &&
                       vma->vm_userfaultfd_ctx.ctx != ctx);
                WARN_ON(!(vma->vm_flags & VM_MAYWRITE));
@@ -1602,7 +1593,7 @@ static int userfaultfd_unregister(struct userfaultfd_ctx 
*ctx,
                 * provides for more strict behavior to notice
                 * unregistration errors.
                 */
-               if (!vma_can_userfault(cur, cur->vm_flags))
+               if (!vma_can_userfault(cur))
                        goto out_unlock;
 
                found = true;
@@ -1616,7 +1607,7 @@ static int userfaultfd_unregister(struct userfaultfd_ctx 
*ctx,
        do {
                cond_resched();
 
-               BUG_ON(!vma_can_userfault(vma, vma->vm_flags));
+               BUG_ON(!vma_can_userfault(vma));
 
                /*
                 * Nothing to do: this vma is already registered into this
diff --git a/include/linux/userfaultfd_k.h b/include/linux/userfaultfd_k.h
index 7d14444862d4..fd7031173949 100644
--- a/include/linux/userfaultfd_k.h
+++ b/include/linux/userfaultfd_k.h
@@ -16,6 +16,7 @@
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <asm-generic/pgtable_uffd.h>
+#include <linux/hugetlb_inline.h>
 
 /*
  * CAREFUL: Check include/uapi/asm-generic/fcntl.h when defining
@@ -88,6 +89,12 @@ static inline bool userfaultfd_armed(struct vm_area_struct 
*vma)
        return vma->vm_flags & (VM_UFFD_MISSING | VM_UFFD_WP);
 }
 
+static inline bool vma_can_userfault(struct vm_area_struct *vma)
+{
+       return vma_is_anonymous(vma) || vma_is_shmem(vma) ||
+           is_vm_hugetlb_page(vma);
+}
+
 extern int dup_userfaultfd(struct vm_area_struct *, struct list_head *);
 extern void dup_userfaultfd_complete(struct list_head *);
 
diff --git a/include/uapi/linux/userfaultfd.h b/include/uapi/linux/userfaultfd.h
index e7e98bde221f..83bcd739de50 100644
--- a/include/uapi/linux/userfaultfd.h
+++ b/include/uapi/linux/userfaultfd.h
@@ -39,7 +39,8 @@
         (__u64)1 << _UFFDIO_WRITEPROTECT)
 #define UFFD_API_RANGE_IOCTLS_BASIC            \
        ((__u64)1 << _UFFDIO_WAKE |             \
-        (__u64)1 << _UFFDIO_COPY)
+        (__u64)1 << _UFFDIO_COPY |             \
+        (__u64)1 << _UFFDIO_WRITEPROTECT)
 
 /*
  * Valid ioctl command number range with this API is from 0x00 to
diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
index 1dff5b9a2c26..3ad52f01553b 100644
--- a/mm/userfaultfd.c
+++ b/mm/userfaultfd.c
@@ -445,7 +445,6 @@ static __always_inline ssize_t mfill_atomic_pte(struct 
mm_struct *dst_mm,
                        err = mfill_zeropage_pte(dst_mm, dst_pmd,
                                                 dst_vma, dst_addr);
        } else {
-               VM_WARN_ON_ONCE(wp_copy);
                if (!zeropage)
                        err = shmem_mcopy_atomic_pte(dst_mm, dst_pmd,
                                                     dst_vma, dst_addr,
@@ -671,15 +670,12 @@ int mwriteprotect_range(struct mm_struct *dst_mm, 
unsigned long start,
 
        err = -ENOENT;
        dst_vma = find_dst_vma(dst_mm, start, len);
-       /*
-        * Make sure the vma is not shared, that the dst range is
-        * both valid and fully within a single existing vma.
-        */
-       if (!dst_vma || (dst_vma->vm_flags & VM_SHARED))
+
+       if (!dst_vma)
                goto out_unlock;
        if (!userfaultfd_wp(dst_vma))
                goto out_unlock;
-       if (!vma_is_anonymous(dst_vma))
+       if (!vma_can_userfault(dst_vma))
                goto out_unlock;
 
        if (is_vm_hugetlb_page(dst_vma)) {
-- 
2.26.2

Reply via email to