The PTE loop mixes its PTL-protected scan with the surrounding lock drops
for rescheduling and large-folio splitting.

Move the scan into a helper that runs entirely under the PTE lock. It
returns a locked and referenced split candidate, or stops at the existing
scheduling boundary so the caller can drop the lock before yielding.

No functional change intended.

Assisted-by: LLM
Signed-off-by: Gregory Price (Meta) <[email protected]>
---
 mm/madvise.c | 66 +++++++++++++++++++++++++++++++---------------------
 1 file changed, 39 insertions(+), 27 deletions(-)

diff --git a/mm/madvise.c b/mm/madvise.c
index 350b854ccc197..e3c3acfcd9b66 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -531,6 +531,28 @@ static bool madvise_lru_huge_pmd(pmd_t *pmd, unsigned long 
addr,
 }
 #endif
 
+static struct folio *
+madvise_lru_pte_range_locked(pte_t *pte, unsigned long *addr,
+               unsigned long end, struct mm_walk *walk,
+               struct list_head *folio_list, bool pageout_anon_only, int *nr,
+               unsigned int *batch_count)
+{
+       struct folio *folio;
+
+       for (; *addr < end; pte += *nr, *addr += *nr * PAGE_SIZE) {
+               if (++(*batch_count) == SWAP_CLUSTER_MAX) {
+                       *batch_count = 0;
+                       if (need_resched())
+                               return NULL;
+               }
+               folio = madvise_lru_pte_batch_locked(pte, *addr, end, walk,
+                               folio_list, pageout_anon_only, nr);
+               if (folio)
+                       return folio;
+       }
+       return NULL;
+}
+
 static int madvise_lru_pmd_entry(pmd_t *pmd, unsigned long addr,
                unsigned long end, struct mm_walk *walk)
 {
@@ -562,36 +584,26 @@ static int madvise_lru_pmd_entry(pmd_t *pmd, unsigned 
long addr,
                goto out;
        flush_tlb_batched_pending(mm);
        lazy_mmu_mode_enable();
-       for (; addr < end; pte += nr, addr += nr * PAGE_SIZE) {
-               if (++batch_count == SWAP_CLUSTER_MAX) {
-                       batch_count = 0;
-                       if (need_resched()) {
-                               lazy_mmu_mode_disable();
-                               pte_unmap_unlock(start_pte, ptl);
-                               cond_resched();
-                               goto restart;
-                       }
-               }
-
-               folio = madvise_lru_pte_batch_locked(pte, addr, end, walk,
-                               &folio_list, pageout_anon_only, &nr);
-               if (!folio)
-                       continue;
-
+       folio = madvise_lru_pte_range_locked(pte, &addr, end, walk,
+                       &folio_list, pageout_anon_only, &nr, &batch_count);
+       if (!folio && addr < end) {
                lazy_mmu_mode_disable();
                pte_unmap_unlock(start_pte, ptl);
-               start_pte = NULL;
-               if (!split_folio(folio))
-                       nr = 0;
-               folio_unlock(folio);
-               folio_put(folio);
-               start_pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
-               if (!start_pte)
-                       break;
-               pte = start_pte;
-               flush_tlb_batched_pending(mm);
-               lazy_mmu_mode_enable();
+               cond_resched();
+               goto restart;
        }
+       if (!folio)
+               goto out;
+
+       lazy_mmu_mode_disable();
+       pte_unmap_unlock(start_pte, ptl);
+       start_pte = NULL;
+       if (!split_folio(folio))
+               nr = 0;
+       folio_unlock(folio);
+       folio_put(folio);
+       addr += nr * PAGE_SIZE;
+       goto restart;
 
 out:
        if (start_pte) {
-- 
2.53.0-Meta


Reply via email to