Re: [RFC PATCH v3 2/6] mm: mglru: let scan_folios() scan both reclaimable generations

Barry Song <[email protected]>
Newsgroups org.kvack.linux-mm,org.kernel.vger.linux-kernel
Message-ID <CAGsJ_4xxO-yAxcynYHdbR-PcYUtKQXKMxq9W2xnm7QasEqg75A@mail.gmail.com>
On Fri, Jul 31, 2026 at 4:39 PM Barry Song (Xiaomi) <[email protected]> wrote:
>
> When we have four generations, and scan_folios() exhausts the oldest
> one while the second-oldest still contains reclaimable folios, the
> current implementation doesn't move on to scan the second-oldest
> generation. Instead, it returns, leaving that generation with no
> chance to be scanned at the current sc->priority.
>
> This doesn't seem right. Rather than breaking out and starting a
> larger next iteration, let's let scan_folios() continue scanning the
> second-oldest generation directly.
>
> Signed-off-by: Barry Song (Xiaomi) <[email protected]>
> ---
>  mm/vmscan.c | 13 +++++++++++--
>  1 file changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/mm/vmscan.c b/mm/vmscan.c
> index ce027c271e9b..31947fa60f18 100644
> --- a/mm/vmscan.c
> +++ b/mm/vmscan.c
> @@ -4718,6 +4718,7 @@ static int scan_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
>         int skipped = 0;
>         unsigned long remaining = nr_to_scan;
>         struct lru_gen_folio *lrugen = &lruvec->lrugen;
> +       unsigned long min_seq = lrugen->min_seq[type];
>
>         VM_WARN_ON_ONCE(nr_to_scan > MAX_LRU_BATCH);
>         VM_WARN_ON_ONCE(!list_empty(list));
> @@ -4725,8 +4726,8 @@ static int scan_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
>         if (get_nr_gens(lruvec, type) == MIN_NR_GENS)
>                 return 0;
>
> -       gen = lru_gen_from_seq(lrugen->min_seq[type]);
> -
> +next_gen:
> +       gen = lru_gen_from_seq(min_seq);
>         for (i = MAX_NR_ZONES; i > 0; i--) {
>                 LIST_HEAD(moved);
>                 int skipped_zone = 0;
> @@ -4768,6 +4769,14 @@ static int scan_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
>                         break;
>         }
>
> +       /*
> +        * This generation is exhausted across all zones, but the scan
> +        * target has not been reached yet. Continue with the next
> +        * reclaimable generation.
> +        */
> +       if (i == 0 && ++min_seq + MIN_NR_GENS <= lrugen->max_seq)
> +               goto next_gen;

https://sashiko.dev/#/patchset/20260731083843.37811-1-baohua%40kernel.org

“Does this cause all folios from the next generation to be skipped?
When we increment the local min_seq and jump to next_gen, the global
lrugen->min_seq[type] remains unchanged. When sort_folio() is called for
these newer-generation folios, won't it misidentify them as concurrently
promoted?
mm/vmscan.c:sort_folio() {
...
/* promoted */
if (gen != lru_gen_from_seq(lrugen->min_seq[type])) {
     list_move(&folio->lru, &lrugen->folios[gen][type][zone]);
    return true;
}
...
}
Because gen now differs from the global lrugen->min_seq[type], won't this
unconditionally return true, moving the folio to the head of the list instead
of isolating it, and wasting CPU cycles while falsely inflating the sorted
metric?”

Good catch. One way to fix it is to update
lrugen->min_seq[type] as well in scan_folios():

       /*
        * This generation is exhausted across all zones, but the scan
        * target has not been reached yet. Continue with the next
        * reclaimable generation.
        */
       if (!reached_scan_target && ++min_seq + MIN_NR_GENS <= lrugen->max_seq) {
               reset_ctrl_pos(lruvec, type, true);
               WRITE_ONCE(lrugen->min_seq[type], min_seq);
               goto next_gen;
       }

But this seems overly complicated, so I'd like to drop this patch
in RFC v4 and instead rely on the outer loop to retry the remaining
reclaimable generations.

The current issue is that when a reclaim type has four generations,
scan_folios() may finish scanning the oldest generation while the
second-oldest generation still contains reclaimable folios.
However, it won't continue scanning that generation in the same
reclaim round.

Thanks
Barry
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.