return 0;
 }
 
+/* See page_try_share_anon_rmap() */
+static inline int hugetlb_try_share_anon_rmap(struct folio *folio)
+{
+       VM_WARN_ON_FOLIO(!folio_test_hugetlb(folio), folio);
+       VM_WARN_ON_FOLIO(!folio_test_anon(folio), folio);
+       VM_WARN_ON_FOLIO(!PageAnonExclusive(&folio->page), folio);
+
+       /* Paired with the memory barrier in try_grab_folio(). */
+       if (IS_ENABLED(CONFIG_HAVE_FAST_GUP))
+               smp_mb();
+
+       if (unlikely(folio_maybe_dma_pinned(folio)))
+               return -EBUSY;
+       ClearPageAnonExclusive(&folio->page);
+
+       /*
+        * This is conceptually a smp_wmb() paired with the smp_rmb() in
+        * gup_must_unshare().
+        */
+       if (IS_ENABLED(CONFIG_HAVE_FAST_GUP))
+               smp_mb__after_atomic();
+       return 0;
+}
+
 static inline void hugetlb_add_file_rmap(struct folio *folio)
 {
        VM_WARN_ON_FOLIO(!folio_test_hugetlb(folio), folio);
  */
 static inline int page_try_share_anon_rmap(struct page *page)
 {
+       VM_WARN_ON(folio_test_hugetlb(page_folio(page)));
        VM_BUG_ON_PAGE(!PageAnon(page) || !PageAnonExclusive(page), page);
 
        /* device private pages cannot get pinned via GUP. */
 
                                       !anon_exclusive, subpage);
 
                        /* See page_try_share_anon_rmap(): clear PTE first. */
-                       if (anon_exclusive &&
-                           page_try_share_anon_rmap(subpage)) {
-                               if (folio_test_hugetlb(folio))
+                       if (folio_test_hugetlb(folio)) {
+                               if (anon_exclusive &&
+                                   hugetlb_try_share_anon_rmap(folio)) {
                                        set_huge_pte_at(mm, address, pvmw.pte,
                                                        pteval, hsz);
-                               else
-                                       set_pte_at(mm, address, pvmw.pte, pteval);
+                                       ret = false;
+                                       page_vma_mapped_walk_done(&pvmw);
+                                       break;
+                               }
+                       } else if (anon_exclusive &&
+                                  page_try_share_anon_rmap(subpage)) {
+                               set_pte_at(mm, address, pvmw.pte, pteval);
                                ret = false;
                                page_vma_mapped_walk_done(&pvmw);
                                break;