Re: [RFC PATCH v5 02/14] mm/mglru: extract lruvec_populated_min_seq() helper

From: KunWu Chan

Date: Tue Oct 27 2026 - 05:43:41 EST


On Fri, Oct 23, 2026 at 6:02 AM Barry Song (Xiaomi) <baohua@xxxxxxxxxx> wrote:
>
> From: Kairui Song <kasong@xxxxxxxxxxx>
>
> The search for the oldest populated generation of a type, previously
> embedded in try_to_inc_min_seq(), is extracted into the new
> lruvec_populated_min_seq() helper. It returns the oldest populated seq
> of a given type, bounded by the given max_seq so the search never goes
> beyond it.
>
> No functional change.
>
> Signed-off-by: Kairui Song <kasong@xxxxxxxxxxx>
> Signed-off-by: Barry Song (Xiaomi) <baohua@xxxxxxxxxx>
> ---
> mm/vmscan.c | 43 +++++++++++++++++++++++++++++--------------
> 1 file changed, 29 insertions(+), 14 deletions(-)
>
> diff --git a/mm/vmscan.c b/mm/vmscan.c
> index 3be0d6c04a82..500ef23949fd 100644
> --- a/mm/vmscan.c
> +++ b/mm/vmscan.c
> @@ -4131,30 +4131,45 @@ static bool inc_min_seq(struct lruvec *lruvec, int type, int swappiness)
> return true;
> }
>
> +/* Similar to lruvec_evictable_size, return the oldest populated seq of the type */
> +static unsigned long lruvec_populated_min_seq(struct lruvec *lruvec, int type,
> + unsigned long max_seq)
> +{
> + int gen, zone;
> + unsigned long min_seq;
> + struct lru_gen_folio *lrugen = &lruvec->lrugen;
> +
> + lockdep_assert_held(&lruvec->lru_lock);
> +
> + min_seq = READ_ONCE(lrugen->min_seq[type]);
> + while (min_seq <= max_seq) {
> + gen = lru_gen_from_seq(min_seq);
> + for (zone = 0; zone < MAX_NR_ZONES; zone++) {
> + if (!list_empty(&lrugen->folios[gen][type][zone]))
> + return min_seq;
> + }
> + min_seq++;
> + }
> +
> + return max_seq;
> +}
> +
> static void try_to_inc_min_seq(struct lruvec *lruvec, int swappiness)
> {
> - int gen, type, zone;
> + int type;
> bool seq_inc_flag = false;
> struct lru_gen_folio *lrugen = &lruvec->lrugen;
> DEFINE_MIN_SEQ(lruvec);
> + unsigned long seq;
>
> VM_WARN_ON_ONCE(!seq_is_valid(lruvec));
>
> - /* find the oldest populated generation */
> + /* Requires at least MIN_NR_GENS gens for basic functionality */
> + seq = lrugen->max_seq - MIN_NR_GENS;
> for_each_evictable_type(type, swappiness) {
> - while (min_seq[type] + MIN_NR_GENS <= lrugen->max_seq) {
> - gen = lru_gen_from_seq(min_seq[type]);
> -
> - for (zone = 0; zone < MAX_NR_ZONES; zone++) {
> - if (!list_empty(&lrugen->folios[gen][type][zone]))
> - goto next;
> - }
> -
> - min_seq[type]++;
> + min_seq[type] = lruvec_populated_min_seq(lruvec, type, seq + 1);
> + if (min_seq[type] > lrugen->min_seq[type])
> seq_inc_flag = true;
> - }
> -next:
> - ;
> }
>
> /*
> --
> 2.34.1
>

The helper preserves the original search result, including the
terminal sequence when no populated generation is found.

Reviewed-by: Kunwu Chan <kunwu.chan@xxxxxxxxx>

Thanks,
Kunwu