From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mta1.migadu.com (out-113.mta1.migadu.com [95.215.58.113]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 37DA630499A for ; Fri, 21 Aug 2026 01:54:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.113 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787277293; cv=none; b=UXkXRSXTslWhmz6JmHa8s3yBQew/OucEAjX6CQY6FcKON6MjM1CR8YPeCNGIn9tizj1pDe44tgfb/IlZ4FZS8pycFvIKz60LGw0qfDlcdsk7NrbJueY7ENum1wztQbx41EqQXSMyxJplH4RJJ2WWJebt65utC61LJgpeBeJ3aro= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787277293; c=relaxed/simple; bh=9222hT0hYb3f7vr5tolxWX9+QXMW0+zV3IKz4ky1kFA=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=nxMnaGpzMZNgsyH8NGYxKOqzGISnK0B4kVP2XzPKoOnKMC5En0oGIF/Q+N50XT6SLW+OGYckHPAkwlCv3R1cMZX91ZKkpRHUGCwukl8kUcFv9euQF1kOACrUVc+eO9+phyGimLGHqVIxKnvhSnyNWcG3dW+I+hY2uk2pWUIsHNo= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=i1moms9R; arc=none smtp.client-ip=95.215.58.113 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="i1moms9R" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=9222hT0hYb3f7vr5tolxWX9+QXMW0+zV3IKz4ky1kFA=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1787277288; v=1; x=1787882088; b=i1moms9RWlP5YSy1UNEEH0F4bNFfCqd6uQOdO2temUnUzaUslJfWCbcCeozf89reeqFlpbFy c4yQN8r3bOog46o6W8+8419cjE0AWeMudCMK7s++vaiaZCWNWTeh2srFIN1JymqFFUD0XNPJLpv GS4wwO6JKiEajFk1J4c6Pbek= X-Envelope-To: linux-kernel@vger.kernel.org Received: from [10.63.107.123] (14.29.108.92) by smtp.migadu.com with ESMTPS id 4ef687fe756c6a11; Fri, 21 Aug 2026 01:54:48 +0000 X-Mizu-Trace-ID: 4ef687fe756c6a11 X-Migadu-Flow: FLOW_OUT Message-ID: <3fb795db-e7e9-415b-9a27-a99bdd34b090@linux.dev> Date: Fri, 21 Aug 2026 09:54:38 +0800 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH] mm/mglru: preserve inactive placement when enabling MGLRU To: Barry Song Cc: Andrew Morton , Johannes Weiner , David Hildenbrand , Michal Hocko , Qi Zheng , Shakeel Butt , Lorenzo Stoakes , Kairui Song , Axel Rasmussen , Yuanchu Xie , Wei Xu , Steven Barrett , "Jan Alexander Steffens (heftig)" , Yu Zhao , Oleksandr Natalenko , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Ridong Chen References: <20260820072641.253591-1-ridong.chen@linux.dev> From: Ridong Chen In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit On 8/20/2026 3:50 PM, Barry Song wrote: > On Thu, Aug 20, 2026 at 3:27 PM Ridong Chen wrote: >> >> From: Ridong Chen >> >> When the LRU is switched to MGLRU (echo y > /sys/kernel/mm/lru_gen/ >> enabled), fill_evictable() re-inserts every folio via >> lru_gen_add_folio(..., false). With reclaiming hardcoded to false, an >> inactive anonymous folio (no PG_active, not in the swapcache) takes the >> "gen = MIN_NR_GENS" branch in lru_gen_folio_seq() and is seeded at >> seq = max_seq - 1, which lru_gen_is_active() treats as active. Its >> inactive placement is lost and NR_INACTIVE_ANON is folded into >> NR_ACTIVE_ANON. >> >> Pass reclaiming=!active so a folio from an inactive list is seeded into >> an older generation. Folios from the active list carry PG_active and >> hit the first branch either way, so they are unchanged. >> >> reclaiming also selects the insertion end in lru_gen_add_folio(): >> list_add_tail() for inactive folios, list_add() for active ones. Both >> the legacy LRU and a MGLRU generation keep the hottest folios at the >> head and the coldest at the tail, and reclaim takes from the tail. To >> preserve that order the folio must be taken from the end matching the >> insertion end, so take inactive folios from the head and active folios >> from the tail; otherwise hot/cold would be reversed within the >> generation. >> >> Tested on x86_64, next-20260812, 2G VM + 1G swap, ~1.5G anon pushed onto >> the inactive list before enabling MGLRU: >> >> Active(anon) Inactive(anon) >> before switch (legacy) 2952 1548792 kB >> after `echo y`, unpatched 1552052 0 kB >> after `echo y`, patched 15144 1536636 kB >> >> Inactive file folios stay inactive either way (NR_INACTIVE_FILE is >> preserved). >> >> Fixes: 354ed5974429 ("mm: multi-gen LRU: kill switch") >> Suggested-by: Barry Song >> Assisted-by: Claude:claude-opus-4-8 >> Signed-off-by: Ridong Chen >> --- >> mm/vmscan.c | 29 +++++++++++++++++++++++++++-- >> 1 file changed, 27 insertions(+), 2 deletions(-) >> >> diff --git a/mm/vmscan.c b/mm/vmscan.c >> index 94fc4f25e99f..7be4cec9a838 100644 >> --- a/mm/vmscan.c >> +++ b/mm/vmscan.c >> @@ -5311,7 +5311,23 @@ static bool fill_evictable(struct lruvec *lruvec) >> >> while (!list_empty(head)) { >> bool success; >> - struct folio *folio = lru_to_folio(head); >> + struct folio *folio; >> + >> + /* >> + * Both the legacy LRU and a MGLRU generation keep the >> + * hottest folios at the head and the coldest at the >> + * tail, and reclaim takes from the tail. To preserve >> + * that order, the end we take from must match the end >> + * lru_gen_add_folio() inserts at: inactive folios use >> + * reclaiming=true (list_add_tail), so take from the >> + * head; active folios use reclaiming=false (list_add), >> + * so take from the tail. Taking from the wrong end >> + * would reverse hot/cold within the generation. >> + */ > > too many words, maybe just: > > lru_gen_add_folio() uses list_add_tail() rather than list_add() > when reclaiming is true. Match its ordering to avoid cold/hot > Inversion. > >> + if (active) >> + folio = lru_to_folio(head); >> + else >> + folio = list_first_entry(head, struct folio, lru); >> >> VM_WARN_ON_ONCE_FOLIO(folio_test_unevictable(folio), folio); >> VM_WARN_ON_ONCE_FOLIO(folio_test_active(folio) != active, folio); >> @@ -5319,7 +5335,16 @@ static bool fill_evictable(struct lruvec *lruvec) >> VM_WARN_ON_ONCE_FOLIO(folio_lru_gen(folio) != -1, folio); >> >> lruvec_del_folio(lruvec, folio); >> - success = lru_gen_add_folio(lruvec, folio, false); >> + /* >> + * With reclaiming=false, lru_gen_folio_seq() would seed >> + * an inactive folio near max_seq, which >> + * lru_gen_is_active() reports as active, so its inactive >> + * placement would be lost. Pass reclaiming=!active to >> + * seed it into the oldest generation instead. This >> + * reuses reclaiming beyond its folio_rotate_reclaimable() >> + * meaning; it also picks list_add_tail() above. >> + */ > > Maybe that's too verbose. How about: > > "Borrow reclaiming=true to place inactive folios in the older gens" > >> + success = lru_gen_add_folio(lruvec, folio, !active); >> VM_WARN_ON_ONCE(!success); >> >> if (!--remaining) > > This is admittedly a bit ugly, but it seems to be the simplest > approach. Since switching MGLRU on and off is not a common scenario, > we probably don't want to over-engineer it. So, with the above change: > > Acked-by: Barry Song Thanks. Will update. -- Best regards Ridong