Previously, we did a dance where we had one calling path in
userfaultfd.c (mfill_atomic_pte), but then we split it into two in
shmem_fs.h (shmem_{mcopy_atomic,mfill_zeropage}_pte), and then rejoined
into a single shared function in shmem.c (shmem_mfill_atomic_pte).

This is all a bit overly complex. Just call the single combined shmem
function directly, allowing us to clean up various branches,
boilerplate, etc.

While we're touching this function, two other small cleanup changes:
- offset is equivalent to pgoff, so we can get rid of offset entirely.
- Split two VM_BUG_ON cases into two statements. This means the line
  number reported when the BUG is hit specifies exactly which condition
  was true.

Reviewed-by: Peter Xu <pet...@redhat.com>
Acked-by: Hugh Dickins <hu...@google.com>
Signed-off-by: Axel Rasmussen <axelrasmus...@google.com>
---
 include/linux/shmem_fs.h | 17 ++++++-------
 mm/shmem.c               | 52 +++++++++++++---------------------------
 mm/userfaultfd.c         | 10 +++-----
 3 files changed, 26 insertions(+), 53 deletions(-)

diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index d82b6f396588..47c3409d02ac 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -122,21 +122,18 @@ static inline bool shmem_file(struct file *file)
 extern bool shmem_charge(struct inode *inode, long pages);
 extern void shmem_uncharge(struct inode *inode, long pages);
 
+#ifdef CONFIG_USERFAULTFD
 #ifdef CONFIG_SHMEM
 extern int shmem_mcopy_atomic_pte(struct mm_struct *dst_mm, pmd_t *dst_pmd,
                                  struct vm_area_struct *dst_vma,
                                  unsigned long dst_addr,
                                  unsigned long src_addr,
+                                 bool zeropage,
                                  struct page **pagep);
-extern int shmem_mfill_zeropage_pte(struct mm_struct *dst_mm,
-                                   pmd_t *dst_pmd,
-                                   struct vm_area_struct *dst_vma,
-                                   unsigned long dst_addr);
-#else
-#define shmem_mcopy_atomic_pte(dst_mm, dst_pte, dst_vma, dst_addr, \
-                              src_addr, pagep)        ({ BUG(); 0; })
-#define shmem_mfill_zeropage_pte(dst_mm, dst_pmd, dst_vma, \
-                                dst_addr)      ({ BUG(); 0; })
-#endif
+#else /* !CONFIG_SHMEM */
+#define shmem_mcopy_atomic_pte(dst_mm, dst_pmd, dst_vma, dst_addr, \
+                              src_addr, zeropage, pagep)       ({ BUG(); 0; })
+#endif /* CONFIG_SHMEM */
+#endif /* CONFIG_USERFAULTFD */
 
 #endif
diff --git a/mm/shmem.c b/mm/shmem.c
index 26c76b13ad23..b72c55aa07fc 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2354,13 +2354,14 @@ static struct inode *shmem_get_inode(struct super_block 
*sb, const struct inode
        return inode;
 }
 
-static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
-                                 pmd_t *dst_pmd,
-                                 struct vm_area_struct *dst_vma,
-                                 unsigned long dst_addr,
-                                 unsigned long src_addr,
-                                 bool zeropage,
-                                 struct page **pagep)
+#ifdef CONFIG_USERFAULTFD
+int shmem_mcopy_atomic_pte(struct mm_struct *dst_mm,
+                          pmd_t *dst_pmd,
+                          struct vm_area_struct *dst_vma,
+                          unsigned long dst_addr,
+                          unsigned long src_addr,
+                          bool zeropage,
+                          struct page **pagep)
 {
        struct inode *inode = file_inode(dst_vma->vm_file);
        struct shmem_inode_info *info = SHMEM_I(inode);
@@ -2372,7 +2373,7 @@ static int shmem_mfill_atomic_pte(struct mm_struct 
*dst_mm,
        struct page *page;
        pte_t _dst_pte, *dst_pte;
        int ret;
-       pgoff_t offset, max_off;
+       pgoff_t max_off;
 
        ret = -ENOMEM;
        if (!shmem_inode_acct_block(inode, 1))
@@ -2383,7 +2384,7 @@ static int shmem_mfill_atomic_pte(struct mm_struct 
*dst_mm,
                if (!page)
                        goto out_unacct_blocks;
 
-               if (!zeropage) {        /* mcopy_atomic */
+               if (!zeropage) {        /* COPY */
                        page_kaddr = kmap_atomic(page);
                        ret = copy_from_user(page_kaddr,
                                             (const void __user *)src_addr,
@@ -2397,7 +2398,7 @@ static int shmem_mfill_atomic_pte(struct mm_struct 
*dst_mm,
                                /* don't free the page */
                                return -ENOENT;
                        }
-               } else {                /* mfill_zeropage_atomic */
+               } else {                /* ZEROPAGE */
                        clear_highpage(page);
                }
        } else {
@@ -2405,15 +2406,15 @@ static int shmem_mfill_atomic_pte(struct mm_struct 
*dst_mm,
                *pagep = NULL;
        }
 
-       VM_BUG_ON(PageLocked(page) || PageSwapBacked(page));
+       VM_BUG_ON(PageLocked(page));
+       VM_BUG_ON(PageSwapBacked(page));
        __SetPageLocked(page);
        __SetPageSwapBacked(page);
        __SetPageUptodate(page);
 
        ret = -EFAULT;
-       offset = linear_page_index(dst_vma, dst_addr);
        max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE);
-       if (unlikely(offset >= max_off))
+       if (unlikely(pgoff >= max_off))
                goto out_release;
 
        ret = shmem_add_to_page_cache(page, mapping, pgoff, NULL,
@@ -2439,7 +2440,7 @@ static int shmem_mfill_atomic_pte(struct mm_struct 
*dst_mm,
 
        ret = -EFAULT;
        max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE);
-       if (unlikely(offset >= max_off))
+       if (unlikely(pgoff >= max_off))
                goto out_release_unlock;
 
        ret = -EEXIST;
@@ -2476,28 +2477,7 @@ static int shmem_mfill_atomic_pte(struct mm_struct 
*dst_mm,
        shmem_inode_unacct_blocks(inode, 1);
        goto out;
 }
-
-int shmem_mcopy_atomic_pte(struct mm_struct *dst_mm,
-                          pmd_t *dst_pmd,
-                          struct vm_area_struct *dst_vma,
-                          unsigned long dst_addr,
-                          unsigned long src_addr,
-                          struct page **pagep)
-{
-       return shmem_mfill_atomic_pte(dst_mm, dst_pmd, dst_vma,
-                                     dst_addr, src_addr, false, pagep);
-}
-
-int shmem_mfill_zeropage_pte(struct mm_struct *dst_mm,
-                            pmd_t *dst_pmd,
-                            struct vm_area_struct *dst_vma,
-                            unsigned long dst_addr)
-{
-       struct page *page = NULL;
-
-       return shmem_mfill_atomic_pte(dst_mm, dst_pmd, dst_vma,
-                                     dst_addr, 0, true, &page);
-}
+#endif /* CONFIG_USERFAULTFD */
 
 #ifdef CONFIG_TMPFS
 static const struct inode_operations shmem_symlink_inode_operations;
diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
index e14b3820c6a8..23fa2583bbd1 100644
--- a/mm/userfaultfd.c
+++ b/mm/userfaultfd.c
@@ -440,13 +440,9 @@ static __always_inline ssize_t mfill_atomic_pte(struct 
mm_struct *dst_mm,
                                                 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,
-                                                    src_addr, page);
-               else
-                       err = shmem_mfill_zeropage_pte(dst_mm, dst_pmd,
-                                                      dst_vma, dst_addr);
+               err = shmem_mcopy_atomic_pte(dst_mm, dst_pmd, dst_vma,
+                                            dst_addr, src_addr, zeropage,
+                                            page);
        }
 
        return err;
-- 
2.31.1.368.gbe11c130af-goog

Reply via email to