unsigned long end, struct mm_walk *walk)
 
 {
+       const cydp_t cydp_flags = CYDP_CLEAR_YOUNG | CYDP_CLEAR_DIRTY;
        struct mmu_gather *tlb = walk->private;
        struct mm_struct *mm = tlb->mm;
        struct vm_area_struct *vma = walk->vma;
                        continue;
 
                /*
-                * If pmd isn't transhuge but the folio is large and
-                * is owned by only this process, split it and
-                * deactivate all pages.
+                * If we encounter a large folio, only split it if it is not
+                * fully mapped within the range we are operating on. Otherwise
+                * leave it as is so that it can be marked as lazyfree. If we
+                * fail to split a folio, leave it in place and advance to the
+                * next pte in the range.
                 */
                if (folio_test_large(folio)) {
-                       int err;
+                       bool any_young, any_dirty;
 
-                       if (folio_likely_mapped_shared(folio))
-                               break;
-                       if (!folio_trylock(folio))
-                               break;
-                       folio_get(folio);
-                       arch_leave_lazy_mmu_mode();
-                       pte_unmap_unlock(start_pte, ptl);
-                       start_pte = NULL;
-                       err = split_folio(folio);
-                       folio_unlock(folio);
-                       folio_put(folio);
-                       if (err)
-                               break;
-                       start_pte = pte =
-                               pte_offset_map_lock(mm, pmd, addr, &ptl);
-                       if (!start_pte)
-                               break;
-                       arch_enter_lazy_mmu_mode();
-                       pte--;
-                       addr -= PAGE_SIZE;
-                       continue;
+                       nr = madvise_folio_pte_batch(addr, end, folio, pte,
+                                                    ptent, &any_young, &any_dirty);
+
+                       if (nr < folio_nr_pages(folio)) {
+                               int err;
+
+                               if (folio_likely_mapped_shared(folio))
+                                       continue;
+                               if (!folio_trylock(folio))
+                                       continue;
+                               folio_get(folio);
+                               arch_leave_lazy_mmu_mode();
+                               pte_unmap_unlock(start_pte, ptl);
+                               start_pte = NULL;
+                               err = split_folio(folio);
+                               folio_unlock(folio);
+                               folio_put(folio);
+                               pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
+                               start_pte = pte;
+                               if (!start_pte)
+                                       break;
+                               arch_enter_lazy_mmu_mode();
+                               if (!err)
+                                       nr = 0;
+                               continue;
+                       }
+
+                       if (any_young)
+                               ptent = pte_mkyoung(ptent);
+                       if (any_dirty)
+                               ptent = pte_mkdirty(ptent);
                }
 
                if (folio_test_swapcache(folio) || folio_test_dirty(folio)) {
                        if (!folio_trylock(folio))
                                continue;
                        /*
-                        * If folio is shared with others, we mustn't clear
-                        * the folio's dirty flag.
+                        * If we have a large folio at this point, we know it is
+                        * fully mapped so if its mapcount is the same as its
+                        * number of pages, it must be exclusive.
                         */
-                       if (folio_mapcount(folio) != 1) {
+                       if (folio_mapcount(folio) != folio_nr_pages(folio)) {
                                folio_unlock(folio);
                                continue;
                        }
                }
 
                if (pte_young(ptent) || pte_dirty(ptent)) {
-                       /*
-                        * Some of architecture(ex, PPC) don't update TLB
-                        * with set_pte_at and tlb_remove_tlb_entry so for
-                        * the portability, remap the pte with old|clean
-                        * after pte clearing.
-                        */
-                       ptent = ptep_get_and_clear_full(mm, addr, pte,
-                                                       tlb->fullmm);
-
-                       ptent = pte_mkold(ptent);
-                       ptent = pte_mkclean(ptent);
-                       set_pte_at(mm, addr, pte, ptent);
-                       tlb_remove_tlb_entry(tlb, pte, addr);
+                       clear_young_dirty_ptes(vma, addr, pte, nr, cydp_flags);
+                       tlb_remove_tlb_entries(tlb, pte, nr, addr);
                }
                folio_mark_lazyfree(folio);
        }