]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
mm/userfaultfd: Moduarlize uffd_writeprotect() for memory types
authorLiam R. Howlett <Liam.Howlett@oracle.com>
Wed, 29 Oct 2025 08:40:31 +0000 (04:40 -0400)
committerLiam R. Howlett <Liam.Howlett@oracle.com>
Thu, 30 Oct 2025 16:54:56 +0000 (12:54 -0400)
Each memory type that treats the writeprotect differently has its own
implementation so that each one can do what it needs without injecting
checks on other types unnecessarily.

Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com>
include/linux/userfaultfd_k.h
mm/hugetlb.c
mm/shmem.c
mm/userfaultfd.c

index 114f9257d240f97dbbf36ff205d939b84efc327d..6f919008bddea8d5fa44d97cbaf56a9f3260396c 100644 (file)
@@ -116,6 +116,7 @@ struct uffd_info {
 }
 
 /* VMA userfaultfd operations */
+int uffd_writeprotect(struct uffd_info *info);
 ssize_t uffd_failed_do_unlock(struct userfaultfd_ctx *ctx,
                struct vm_area_struct *dst, struct folio *folio,
                unsigned long src_addr);
@@ -125,6 +126,7 @@ struct vm_uffd_ops {
        int (*zeropage)(struct uffd_info *info);
        int (*cont)(struct uffd_info *info);
        int (*poison)(struct uffd_info *info);
+       int (*writeprotect)(struct uffd_info *info);
        /* Required features below */
        ssize_t (*is_dst_valid)(struct vm_area_struct *dst_vma,
                                unsigned long dst_start, unsigned long len);
index 97b402762921d3c33562b680f5197a19d400fc8e..72daaf8d06e1ead02a0e8ef6327a87b1a293216e 100644 (file)
@@ -5538,6 +5538,7 @@ static const struct vm_uffd_ops hugetlb_uffd_ops = {
        .zeropage               =       NULL,
        .cont                   =       hugetlb_mfill_pte_continue,
        .poison                 =       hugetlb_mfill_pte_poison,
+       .writeprotect           =       uffd_writeprotect,
        .is_dst_valid           =       hugetlb_is_dst_valid,
        .increment              =       hugetlb_mfill_size,
        .failed_do_unlock       =       hugetlb_failed_do_unlock,
index 165b428a661e0845c39ea51565317e1a3ab51f3b..3ddf7f42e1fa9b5b84178804df7f21c597bef539 100644 (file)
@@ -5273,6 +5273,7 @@ static const struct vm_uffd_ops shmem_uffd_ops = {
        .zeropage               =       shmem_mfill_atomic_pte_zeropage,
        .cont                   =       shmem_mfill_atomic_pte_continue,
        .poison                 =       mfill_atomic_pte_poison,
+       .writeprotect           =       uffd_writeprotect,
        .is_dst_valid           =       shmem_is_dst_valid,
        .increment              =       mfill_size,
        .failed_do_unlock       =       uffd_failed_do_unlock,
index 1bdccadcaeb3545f16a1cf4677d8a5ac5c1d6ce8..f7c5b40f3e0571d6710eb1297e3be730c0de7984 100644 (file)
@@ -475,6 +475,7 @@ static const struct vm_uffd_ops default_uffd_ops = {
        .zeropage               = mfill_atomic_pte_zeropage,
        .cont                   = NULL,
        .poison                 = mfill_atomic_pte_poison,
+       .writeprotect           = uffd_writeprotect,
        .is_dst_valid           = uffd_def_is_dst_valid,
        .increment              = mfill_size,
        .failed_do_unlock       = uffd_failed_do_unlock,
@@ -784,7 +785,7 @@ long uffd_wp_range(struct vm_area_struct *dst_vma,
        return ret;
 }
 
-static int uffd_writeprotect(struct uffd_info *info)
+int uffd_writeprotect(struct uffd_info *info)
 {
        long err;
        struct vm_area_struct *dst_vma;
@@ -843,7 +844,11 @@ int mwriteprotect_range(struct userfaultfd_ctx *ctx, unsigned long start,
 
        err = -ENOENT;
        for_each_vma_range(vmi, info.dst_vma, start + len) {
-               err = uffd_writeprotect(&info);
+               info.uffd_ops = vma_get_uffd_ops(info.dst_vma);
+               err = -EINVAL;
+               if (!info.uffd_ops || !info.uffd_ops->writeprotect)
+                       break;
+               err = info.uffd_ops->writeprotect(&info);
                if (err)
                        break;
        }