Re: [PATCH v9 06/14] mm: multi-gen LRU: minimal implementation
From: Yu Zhao
Date: Tue Mar 22 2022 - 01:56:11 EST
On Mon, Mar 21, 2022 at 11:27 PM Aneesh Kumar K.V
<aneesh.kumar@xxxxxxxxxxxxx> wrote:
>
> Yu Zhao <yuzhao@xxxxxxxxxx> writes:
>
> > +static void inc_max_seq(struct lruvec *lruvec, unsigned long max_seq)
> > +{
> > + int prev, next;
> > + int type, zone;
> > + struct lru_gen_struct *lrugen = &lruvec->lrugen;
> > +
> > + spin_lock_irq(&lruvec->lru_lock);
> > +
> > + VM_BUG_ON(!seq_is_valid(lruvec));
> > +
> > + if (max_seq != lrugen->max_seq)
> > + goto unlock;
> > +
> > + inc_min_seq(lruvec);
>
> Can this min seq update result in pages considered oldest become young.
> ie, if we had seq value of 0 - 3 and we need ageing, the new min seq and
> max_seq value will now become 1 - 4. What happens to pages in the
> generation value 0 which was oldest generation earlier and is youngest
> now.
If anon pages are not reclaimable, e.g., no swapfile, they won't be
scanned at all. So their coldness/hotness don't matter -- they don't
need to be on lrugen->lists[] at all.
If there is a swapfile but it's full, then yes, the inversion will
happen. This can be handled by moving pages from the oldest generation
to the tail of the second oldest generation, which maintains the LRU
order.
In fact, both were handled in the previous versions [1] [2]. They were
removed in v6 for simplicity.
[1] https://lore.kernel.org/linux-mm/20211111041510.402534-5-yuzhao@xxxxxxxxxx/
[2] https://lore.kernel.org/linux-mm/20211111041510.402534-7-yuzhao@xxxxxxxxxx/
> > +static int evict_folios(struct lruvec *lruvec, struct scan_control *sc, int swappiness)
> > +{
> > + int type;
> > + int scanned;
> > + int reclaimed;
> > + LIST_HEAD(list);
> > + struct folio *folio;
> > + enum vm_event_item item;
> > + struct reclaim_stat stat;
> > + struct mem_cgroup *memcg = lruvec_memcg(lruvec);
> > + struct pglist_data *pgdat = lruvec_pgdat(lruvec);
> > +
> > + spin_lock_irq(&lruvec->lru_lock);
> > +
> > + scanned = isolate_folios(lruvec, sc, swappiness, &type, &list);
> > +
> > + if (try_to_inc_min_seq(lruvec, swappiness))
> > + scanned++;
>
> we are doing this before we shrink the page list. Any reason to do this before?
We have isolated pages from lrugen->lists[], and we might have
exhausted all pages in the oldest generations, i.e.,
lrugen->lists[min_seq] is now empty. Incrementing min_seq after
shrink_page_list() is not wrong. However, it's better we do it ASAP so
that concurrent reclaimers are less likely to see a stale min_seq and
come here under the false impression that they'd make some progress.
(Instead, they will go to the aging path and inc_max_seq() first
before coming here.)