On Sat, 9 Sep 2023 13:33:08 +0800 Jiexun Wang <wangjiexun@xxxxxxxxxxx> wrote: > Currently the madvise_cold_or_pageout_pte_range() function exhibits > significant latency under memory pressure, which can be effectively > reduced by adding cond_resched() within the loop. > > When the batch_count reaches SWAP_CLUSTER_MAX, we reschedule > the task to ensure fairness and avoid long lock holding times. > > ... > > @@ -441,6 +443,13 @@ static int madvise_cold_or_pageout_pte_range(pmd_t *pmd, > arch_enter_lazy_mmu_mode(); > for (; addr < end; pte++, addr += PAGE_SIZE) { > ptent = ptep_get(pte); > + > + if (++batch_count == SWAP_CLUSTER_MAX) { > + pte_unmap_unlock(start_pte, ptl); > + cond_resched(); > + start_pte = pte_offset_map_lock(mm, pmd, addr, &ptl); > + batch_count = 0; > + } > > if (pte_none(ptent)) > continue; I doubt if we can simply drop the lock like this then proceed as if nothing has changed while the lock was released. Could be that something along these lines: @@ -434,6 +436,7 @@ huge_unlock: regular_folio: #endif tlb_change_page_size(tlb, PAGE_SIZE); +restart: start_pte = pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); if (!start_pte) return 0; @@ -441,6 +444,15 @@ regular_folio: arch_enter_lazy_mmu_mode(); for (; addr < end; pte++, addr += PAGE_SIZE) { ptent = ptep_get(pte); + + if (++batch_count == SWAP_CLUSTER_MAX) { + batch_count = 0; + if (need_resched()) { + pte_unmap_unlock(start_pte, ptl); + cond_resched(); + goto restart; + } + } if (pte_none(ptent)) continue; would work, but more analysis would be needed.