From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mta1.migadu.com (out-177.mta1.migadu.com [95.215.58.177]) (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 F2CC638D686 for ; Fri, 14 Aug 2026 02:22:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.177 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786674153; cv=none; b=NSZjTSu2sBhs6WmO2MTEQbi8VD0lX32OPRTCT9RDMWHjK98rB0naoWZjcm0fPdhdw7e/mmSJvuETuUKt9YCxTCF247ESMK5Av+XvlD6RF8L+19BE6j6FtUhutSFCHZNYYNfui4FpSOCtAF6zps0lqVnmdblZDkJk4fuTTP0mW+E= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786674153; c=relaxed/simple; bh=JU6xpogHPmDMSlDtNSPKwKSCuJrjX9ZxEFdYEDJQdKs=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=SOeCfeKSLt6zAH/ERb8Dym31KC6vPGPnZqqdBRPjsP2fatVg5QEjkAMXa5y9pdgNd4BeQL3ZqQl2LqhifrqGwt6LzOQukAppkCisDnPz8tefEyxEFbkeS7OEOkX6a3pmrho2bd4OC7+wHlX4+CqurQNnU91vh1p3u3jYhzYGWYU= 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=wmUdRuOF; arc=none smtp.client-ip=95.215.58.177 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="wmUdRuOF" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=JU6xpogHPmDMSlDtNSPKwKSCuJrjX9ZxEFdYEDJQdKs=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1786674149; v=1; x=1787278949; b=wmUdRuOFtZOAiPR7pj9Csu+BIU8qJRGZXvPpQ2QBErQGauGiKHzP6SACPvRTFapxDDlB/7ZN fqxriC2ul5fp7eG2PaN4Ydel1Yy6dAEln1AG6e7oZ/auTBqe9dZuUXyAn/hJ2x+7O6W2wPu2nne W7ERz/+aZtg4fNZbf16czdu8= X-Envelope-To: linux-kernel@vger.kernel.org Received: from [10.63.123.245] (14.29.108.90) by smtp.migadu.com with ESMTPS id 1d9bbf50f91c581b; Fri, 14 Aug 2026 02:22:29 +0000 X-Migadu-Flow: FLOW_OUT Message-ID: Date: Fri, 14 Aug 2026 10:22:23 +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: [RFC 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 , Brian Geffon , "Jan Alexander Steffens (heftig)" , Steven Barrett , Yu Zhao , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Ridong Chen References: <20260813110230.2124785-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/13/2026 7:37 PM, Barry Song wrote: > On Thu, Aug 13, 2026 at 7:24 PM Barry Song wrote: >> >> On Thu, Aug 13, 2026 at 7:02 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. >>> >>> 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") >>> Assisted-by: Claude:claude-opus-4-8 >>> Signed-off-by: Ridong Chen >>> --- >>> mm/vmscan.c | 7 ++++++- >>> 1 file changed, 6 insertions(+), 1 deletion(-) >>> >>> diff --git a/mm/vmscan.c b/mm/vmscan.c >>> index 94fc4f25e99f..2befc8d7dd3f 100644 >>> --- a/mm/vmscan.c >>> +++ b/mm/vmscan.c >>> @@ -5319,7 +5319,12 @@ 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); >>> + /* >>> + * Keep a folio from the inactive list inactive: >>> + * pass reclaiming=!active so it is not seeded as >>> + * active. See lru_gen_folio_seq(). >>> + */ >>> + success = lru_gen_add_folio(lruvec, folio, !active); >> Hi Barry, Thank you for your reply. >> This is a very interesting use of the reclaim argument, as it is not >> intended to serve this MGLRU switch purpose. It is really only meant >> for `folio_rotate_reclaimable()`. >> Yeah, I realize tying the reclaim argument to the MGLRU switch is a bit of a hack, since it was really only designed for folio_rotate_reclaimable(). That said, I'm not blind to it, I just posted an RFC patch to get the discussion rolling and see what people think. >> However, the change itself seems to be *partially* correct and >> *partially* wrong. >> >> One real issue is that inactive is always placed in the oldest >> generation, while we have two old generations. Maybe we can ignore >> this for now. >> >> but somehow, are we also inverting the cold/hot ordering in the >> inactive list? >> >> `lru_to_folio(head)` always takes the tail, but now we are putting the >> tail before the head folios. >> >> Because reclaim == true will use list_add_tail(). >> >> if (reclaiming) >> list_add_tail(&folio->lru, &lrugen->folios[gen][type][zone]); > > I guess we can fix this by iterating in `fill_evictable()` from head > to tail order. > > struct list_head *pos = head->next; > > while (pos != head) { > struct folio *folio = list_entry(pos, struct folio, lru); > ... > } > > Then the oldest generation will maintain the same folio order as the > inactive list. > Thanks for the suggestion. Traversing head to tail does fix the inversion, but we need to distinguish active from inactive during iteration, because they are inserted differently: list_add_tail() when reclaiming, and list_add() otherwise. That said, the reclaim argument usage still feels off to me—I'd like to hear if others have a better idea before we proceed with further changes. -- Best regards Ridong