{
        const bool unshare = vmf->flags & FAULT_FLAG_UNSHARE;
        struct vm_area_struct *vma = vmf->vma;
-       struct folio *folio;
+       struct folio *folio = NULL;
 
        if (likely(!unshare)) {
                if (userfaultfd_pte_wp(vma, *vmf->pte)) {
        }
 
        vmf->page = vm_normal_page(vma, vmf->address, vmf->orig_pte);
-       if (!vmf->page) {
-               if (unlikely(unshare)) {
-                       /* No anonymous page -> nothing to do. */
-                       pte_unmap_unlock(vmf->pte, vmf->ptl);
-                       return 0;
-               }
 
+       /*
+        * Shared mapping: we are guaranteed to have VM_WRITE and
+        * FAULT_FLAG_WRITE set at this point.
+        */
+       if (vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) {
                /*
                 * VM_MIXEDMAP !pfn_valid() case, or VM_SOFTDIRTY clear on a
                 * VM_PFNMAP VMA.
                 * We should not cow pages in a shared writeable mapping.
                 * Just mark the pages writable and/or call ops->pfn_mkwrite.
                 */
-               if ((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
-                                    (VM_WRITE|VM_SHARED))
+               if (!vmf->page)
                        return wp_pfn_shared(vmf);
-
-               pte_unmap_unlock(vmf->pte, vmf->ptl);
-               return wp_page_copy(vmf);
+               return wp_page_shared(vmf);
        }
 
+       if (vmf->page)
+               folio = page_folio(vmf->page);
+
        /*
-        * Take out anonymous pages first, anonymous shared vmas are
-        * not dirty accountable.
+        * Private mapping: create an exclusive anonymous page copy if reuse
+        * is impossible. We might miss VM_WRITE for FOLL_FORCE handling.
         */
-       folio = page_folio(vmf->page);
-       if (folio_test_anon(folio)) {
+       if (folio && folio_test_anon(folio)) {
                /*
                 * If the page is exclusive to this process we must reuse the
                 * page without further checks.
                /* No anonymous page -> nothing to do. */
                pte_unmap_unlock(vmf->pte, vmf->ptl);
                return 0;
-       } else if (unlikely((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
-                                       (VM_WRITE|VM_SHARED))) {
-               return wp_page_shared(vmf);
        }
 copy:
        /*
         * Ok, we need to copy. Oh, well..
         */
-       get_page(vmf->page);
+       if (folio)
+               folio_get(folio);
 
        pte_unmap_unlock(vmf->pte, vmf->ptl);
 #ifdef CONFIG_KSM
-       if (PageKsm(vmf->page))
+       if (folio && folio_test_ksm(folio))
                count_vm_event(COW_KSM);
 #endif
        return wp_page_copy(vmf);