Re: [PATCH] mm/mglru: Fix young counter undercount for large folios
Barry Song <[email protected]>
| Newsgroups | org.kvack.linux-mm,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <CAGsJ_4wE7E2G8H4ugwSWbQMF+5ecx+mrYQxXa1U6HY3utuQz0w@mail.gmail.com> |
On Wed, Aug 12, 2026 at 6:17 PM Baolin Wang <[email protected]> wrote: > > > > On 8/12/26 2:59 PM, Hui Zhu wrote: > > From: Hui Zhu <[email protected]> > > > > In lru_gen_look_around(), the young counter tracks the number of young > > PTEs. The original folio's contribution is represented by the initial > > value of young: test_and_clear_young_ptes_notify() is called on it at > > function entry, and the function returns early if it is not young. In > > the subsequent loop, the original folio is skipped (its accessed bits > > were already cleared), so it is not double-counted. > > > > However, young is initialized to 1 regardless of the folio size. When > > the original folio is a large folio with nr PTEs, its young count is > > underestimated by nr - 1. This inconsistency can cause > > suitable_to_scan() to return false, preventing the PMD from being added > > to the bloom filter and reducing aging accuracy for mTHP workloads. > > > > Initialize young to nr so the original folio is accounted the same way > > as other young folios in the loop (young += nr). > > > > Signed-off-by: Hui Zhu <[email protected]> > > --- > > Good catch. Please also add the Fixes tag: > > Fixes: 56e5b60b2114 ("mm: support batched checking of the young flag for > MGLRU") > > With that, > Reviewed-by: Baolin Wang <[email protected]> Hi Baolin, Hui, I am not convinced this is the correct patch. test_and_clear_young_ptes_notify() only indicates that there is at least one young PTE among the nr PTEs; it does not mean that all of the PTEs are young. Am I missing something? bool contpte_test_and_clear_young_ptes(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep, unsigned int nr) { ... unsigned long end = addr + nr * PAGE_SIZE; bool young = false; ptep = contpte_align_addr_ptep(&addr, &end, ptep, nr); for (; addr != end; ptep++, addr += PAGE_SIZE) young |= __ptep_test_and_clear_young(vma, addr, ptep); return young; } EXPORT_SYMBOL_GPL(contpte_test_and_clear_young_ptes); > > > mm/vmscan.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/mm/vmscan.c b/mm/vmscan.c > > index bc324e37c5f1..264017850a55 100644 > > --- a/mm/vmscan.c > > +++ b/mm/vmscan.c > > @@ -4192,7 +4192,7 @@ bool lru_gen_look_around(struct page_vma_mapped_walk *pvmw, unsigned int nr) > > unsigned long end; > > struct lru_gen_mm_walk *walk; > > struct folio *last = NULL; > > - int young = 1; > > + int young = nr; > > pte_t *pte = pvmw->pte; > > unsigned long addr = pvmw->address; > > struct vm_area_struct *vma = pvmw->vma; > Thanks Barry