All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lian Wang <lianux.mm@gmail.com>
To: "Barry Song (Xiaomi)" <baohua@kernel.org>
Cc: akpm@linux-foundation.org, lianux.mm@gmail.com,
	axelrasmussen@google.com, baolin.wang@linux.alibaba.com,
	baoquan.he@linux.dev, chenridong@xiaomi.com, david@kernel.org,
	hannes@cmpxchg.org, kasong@tencent.com,
	linux-kernel@vger.kernel.org, linux-mm@kvack.org, ljs@kernel.org,
	lyugaofei@xiaomi.com, mhocko@kernel.org, qi.zheng@linux.dev,
	shakeel.butt@linux.dev, stevensd@chromium.org,
	wangzicheng@honor.com, weixugc@google.com, yuanchu@google.com,
	zhangbo56@xiaomi.com, Xueyuan Chen <xueyuan.chen21@gmail.com>
Subject: Re: [PATCH v2 7/7] mm/mglru: batch move folios to the second-oldest gen's LRU
Date: Sun, 30 Aug 2026 15:45:17 +0800	[thread overview]
Message-ID: <20260830074531.79967-1-lianux.mm@gmail.com> (raw)
In-Reply-To: <20260827234704.63163-8-baohua@kernel.org>

On Fri, 28 Aug 2026 07:47:04 +0800 "Barry Song (Xiaomi)" <baohua@kernel.org> wrote:

> Detect folios that need to move from the oldest generation to
> the second-oldest generation, and batch-move them together.
> This can significantly reduce the sys time of inc_min_seq(),
> especially when the other type is significantly behind the
> preferred type.
>
> Assisted-by: gemini:gemini-3.6-flash
> Signed-off-by: Barry Song (Xiaomi) <baohua@kernel.org>
> Reviewed-by: Baoquan He <baoquan.he@linux.dev>
> Tested-by: Xueyuan Chen <xueyuan.chen21@gmail.com>
> ---
>  mm/vmscan.c | 20 +++++++++++++++++++-
>  1 file changed, 19 insertions(+), 1 deletion(-)
>
> diff --git a/mm/vmscan.c b/mm/vmscan.c
> index 17524e96fe64..2b6f3f05ce60 100644
> --- a/mm/vmscan.c
> +++ b/mm/vmscan.c
> @@ -3931,6 +3931,19 @@ static void clear_mm_walk(void)
>  		kfree(walk);
>  }
>
> +static inline void flush_lru_batch(struct list_head *head, struct list_head **batch_end,
> +				   struct list_head *dst)
> +{
> +	LIST_HEAD(movable);
> +
> +	if (!*batch_end)
> +		return;
> +
> +	list_cut_position(&movable, head, *batch_end);
> +	list_splice_tail_init(&movable, dst);
> +	*batch_end = NULL;
> +}

This is safe because `batch_end` always marks a contiguous prefix of `head`:
the loop walks from head to tail and flushes the prefix before moving any folio
that was already promoted by aging.

> +
>  static bool inc_min_seq(struct lruvec *lruvec, int type, int swappiness)
>  {
>  	int zone;
> @@ -3953,8 +3966,10 @@ static bool inc_min_seq(struct lruvec *lruvec, int type, int swappiness)
>  			lru_gen_is_active(lruvec, target_gen));
>  	/* prevent cold/hot inversion if the type is evictable */
>  	for (zone = 0; zone < MAX_NR_ZONES; zone++) {
> +		struct list_head *target_list = &lrugen->folios[target_gen][type][zone];
>  		struct list_head *head = &lrugen->folios[old_gen][type][zone];
>  		struct list_head *pos = head->next;
> +		struct list_head *batch_end = NULL;
>  		long delta = 0;
>
>  		while (pos != head) {
> @@ -3974,7 +3989,7 @@ static bool inc_min_seq(struct lruvec *lruvec, int type, int swappiness)
>  			new_gen = __folio_inc_gen(folio, old_gen, &gen_increased);
>  			if (gen_increased) {
>  				delta += nr_pages;
> -				list_move_tail(&folio->lru, &lrugen->folios[new_gen][type][zone]);
> +				batch_end = &folio->lru;
>
>  				/* don't count the workingset being lazily promoted */
>  				if (refs + workingset != BIT(LRU_REFS_WIDTH) + 1) {
> @@ -3984,11 +3999,14 @@ static bool inc_min_seq(struct lruvec *lruvec, int type, int swappiness)
>  						   lrugen->protected[hist][type][tier] + nr_pages);
>  				}
>  			} else {
> +				flush_lru_batch(head, &batch_end, target_list);
>  				list_move(&folio->lru, &lrugen->folios[new_gen][type][zone]);
>  			}
>  			if (!--remaining)
>  				break;
>  		}
> +		flush_lru_batch(head, &batch_end, target_list);

The flush in the `else` keeps every already-promoted folio ahead of the
normal old-to-target batch. This final flush also covers the batch-limit exit
before the counters are updated and the lock can be dropped.

> +
>  		WRITE_ONCE(lrugen->nr_pages[old_gen][type][zone],
>  			   lrugen->nr_pages[old_gen][type][zone] - delta);
>  		WRITE_ONCE(lrugen->nr_pages[target_gen][type][zone],
> --
> 2.34.1

The moved list entries and `delta` therefore cover the same folios, while the
relative order of each normal-folio run is preserved. Looks good to me.

Reviewed-by: Lian Wang <lianux.mm@gmail.com>


      parent reply	other threads:[~2026-08-30  7:45 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-27 23:46 [PATCH v2 0/7] mm/mglru: speed up inc_min_seq() and fix cold/hot inversions Barry Song (Xiaomi)
2026-08-27 23:46 ` [PATCH v2 1/7] mm/mglru: separate folio generation update from LRU accounting Barry Song (Xiaomi)
2026-08-30  7:26   ` Lian Wang
2026-08-27 23:46 ` [PATCH v2 2/7] mm/mglru: batch update lrugen->nr_pages in inc_min_seq() Barry Song (Xiaomi)
2026-08-30  3:58   ` Kunwu Chan
2026-08-30  4:26     ` Barry Song
2026-08-30  4:47       ` KunWu Chan
2026-08-30  7:01   ` Lian Wang
2026-08-27 23:47 ` [PATCH v2 3/7] mm/mglru: enhance cold/hot inversion handling " Barry Song (Xiaomi)
2026-08-30  2:43   ` Ridong Chen
2026-08-30  4:28     ` Barry Song
2026-08-30  7:02   ` Lian Wang
2026-08-27 23:47 ` [PATCH v2 4/7] mm/mglru: exclude folios promoted by aging from protected " Barry Song (Xiaomi)
2026-08-30  6:13   ` Ridong Chen
2026-08-30  7:03   ` Lian Wang
2026-08-27 23:47 ` [PATCH v2 5/7] mm/mglru: make LRU folio prefetch helper an inline function Barry Song (Xiaomi)
2026-08-30  7:43   ` Lian Wang
2026-08-27 23:47 ` [PATCH v2 6/7] mm/mglru: move folios from oldest gen to second-oldest gen from head to tail Barry Song (Xiaomi)
2026-08-30  7:44   ` Lian Wang
2026-08-27 23:47 ` [PATCH v2 7/7] mm/mglru: batch move folios to the second-oldest gen's LRU Barry Song (Xiaomi)
2026-08-28  3:29   ` Barry Song
2026-08-30  7:45   ` Lian Wang [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260830074531.79967-1-lianux.mm@gmail.com \
    --to=lianux.mm@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=axelrasmussen@google.com \
    --cc=baohua@kernel.org \
    --cc=baolin.wang@linux.alibaba.com \
    --cc=baoquan.he@linux.dev \
    --cc=chenridong@xiaomi.com \
    --cc=david@kernel.org \
    --cc=hannes@cmpxchg.org \
    --cc=kasong@tencent.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=ljs@kernel.org \
    --cc=lyugaofei@xiaomi.com \
    --cc=mhocko@kernel.org \
    --cc=qi.zheng@linux.dev \
    --cc=shakeel.butt@linux.dev \
    --cc=stevensd@chromium.org \
    --cc=wangzicheng@honor.com \
    --cc=weixugc@google.com \
    --cc=xueyuan.chen21@gmail.com \
    --cc=yuanchu@google.com \
    --cc=zhangbo56@xiaomi.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.