From nobody Fri Jul 24 05:21:23 2026 Received: from out-171.mta0.migadu.com (out-171.mta0.migadu.com [91.218.175.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 51B4F3812DA for ; Thu, 23 Jul 2026 04:57:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784782678; cv=none; b=gxjO7ivm2+7Vlj7YlaYkO/U3vdE34/a+40HcjXnzhxpkQpYMRJPlSPkPLlyQIUnnwcbcftMCIGFdVJXJnYqu4GyopBZHw8VHtY5eXePCSlfP6z6NzaP3zMOlq75DKO+vqazinfojtNfssQQ5rBLEm0qPWfrs1gv123cwIZNd6Kw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784782678; c=relaxed/simple; bh=nopkLGQjxyCvDc5NWUmj3PpMHMg9QQc4M01a5XIRBgc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=cbDgglgMxj8eMm2xo104OROW9BcrsjaoJeHo+2ZImif6MXhiqDYgbIsfzQuf5332/gyz0+f82fX0H09nhwqmWp2qYxnXPvT5GfpSTs8Cu69OeFuKRpF8wrssGCeq3rjRYO6ml+MNGC7eOamj2TvJ19X0uX708n9LUeRP15EGxPo= 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=PVYGstw7; arc=none smtp.client-ip=91.218.175.171 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="PVYGstw7" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1784782666; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+M31gX24/lXdo/71mKqeb9yMjPYP0lhEdBSZm1x7d2Y=; b=PVYGstw7O1AshQlF7Vggr7tyf7t6fBgn/m1/RtemzMXcw63/0ICwW4qp8tqDCErm59X7+q WMgJrDtEtc6OS2rQPuc/BSRn45sRy+z+XeiJwIiDqGsX72W0torSudl1fHn/gkEzoM1upD uzVrvWaG2LLwEZoO5GDLy4Wz2EAlZ+Y= From: Ridong To: Andrew Morton , Johannes Weiner Cc: David Hildenbrand , Michal Hocko , Qi Zheng , Shakeel Butt , Lorenzo Stoakes , Kairui Song , Barry Song , Axel Rasmussen , Yuanchu Xie , Wei Xu , Zhongkun He , Muchun Song , Davidlohr Bueso , Roman Gushchin , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Ridong Chen , Ridong Chen Subject: [PATCH v3 1/4] mm/vmscan: fix anon-only reclaim evicting file pages when swappiness=max Date: Thu, 23 Jul 2026 12:57:15 +0800 Message-Id: <20260723045718.2052070-2-ridong.chen@linux.dev> In-Reply-To: <20260723045718.2052070-1-ridong.chen@linux.dev> References: <20260723045718.2052070-1-ridong.chen@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Ridong Chen As Qi mentioned [1], when swappiness=3Dmax (SWAPPINESS_ANON_ONLY) is set, the reclaim logic is expected to reclaim anonymous pages exclusively. However, due to the current ordering of checks in get_scan_count(), file pages may still be evicted if can_reclaim_anon_pages() returns false, which contradicts the semantics of SWAPPINESS_ANON_ONLY. Reproducer in a cgroup holding 64M of file cache, with no swap configured: Before (file cache is wrongly evicted): # cat memory.stat anon 196608 file 67178496 pgscan_proactive 0 # echo "64M swappiness=3Dmax" > memory.reclaim # cat memory.stat anon 208896 file 4096 <- page cache evicted pgsteal_proactive 16400 pgscan_proactive 16400 After (file cache is left intact): # cat memory.stat anon 200704 file 67178496 pgscan_proactive 0 # echo "64M swappiness=3Dmax" > memory.reclaim -bash: echo: write error: Resource temporarily unavailable # cat memory.stat anon 208896 file 67178496 <- page cache untouched pgsteal_proactive 0 pgscan_proactive 0 Fix this by bailing out early when SWAPPINESS_ANON_ONLY is set and no anonymous pages are reclaimable, before falling back to file reclaim. [1] https://lore.kernel.org/cgroups/7ddf3eee-5fe2-45f7-8614-c8936a039e04@li= nux.dev/ Fixes: 68a1436bde00 ("mm: add swappiness=3Dmax arg to memory.reclaim for on= ly anon reclaim") Suggested-by: Qi Zheng Acked-by: Shakeel Butt Acked-by: Johannes Weiner Reviewed-by: Muchun Song Reviewed-by: Qi Zheng Reviewed-by: Barry Song Signed-off-by: Ridong Chen --- mm/vmscan.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 35c3bb15ae96..2c689682b952 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2501,6 +2501,23 @@ static void get_scan_count(struct lruvec *lruvec, st= ruct scan_control *sc, enum scan_balance scan_balance; enum lru_list lru; =20 + /* + * Proactive reclaim initiated by userspace for anonymous memory only. + * SWAPPINESS_ANON_ONLY is set only on the proactive reclaim path, so + * warn if it shows up elsewhere. When anon cannot be reclaimed (e.g. + * no swap), bail out instead of falling back to evicting file pages, + * which would violate the anon-only semantics. + */ + if (swappiness =3D=3D SWAPPINESS_ANON_ONLY) { + WARN_ON_ONCE(!sc->proactive); + if (!can_reclaim_anon_pages(memcg, pgdat->node_id, sc)) { + memset(nr, 0, sizeof(*nr) * NR_LRU_LISTS); + return; + } + scan_balance =3D SCAN_ANON; + goto out; + } + /* If we have no swap space, do not bother scanning anon folios. */ if (!sc->may_swap || !can_reclaim_anon_pages(memcg, pgdat->node_id, sc)) { scan_balance =3D SCAN_FILE; @@ -2519,13 +2536,6 @@ static void get_scan_count(struct lruvec *lruvec, st= ruct scan_control *sc, goto out; } =20 - /* Proactive reclaim initiated by userspace for anonymous memory only */ - if (swappiness =3D=3D SWAPPINESS_ANON_ONLY) { - WARN_ON_ONCE(!sc->proactive); - scan_balance =3D SCAN_ANON; - goto out; - } - /* * Do not apply any pressure balancing cleverness when the * system is close to OOM, scan both anon and file equally --=20 2.34.1 From nobody Fri Jul 24 05:21:23 2026 Received: from out-188.mta0.migadu.com (out-188.mta0.migadu.com [91.218.175.188]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9D2C639C637 for ; Thu, 23 Jul 2026 04:58:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.188 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784782689; cv=none; b=X4hC92kyMjNTbYxnoNyVaebcgm3L9w4jfKWWmRnlLjJarGso4r/452Zc/ApDGWEuLT/ZLlAnh4dAz7LIQP/bjBVg1brXSrZ3X4q6vdjOB5hzNgAA6sLZXpR6IQLbAn9htpolQJIt5a3B0moxXMhVuTaQ8ek8VN7gzdzrKtrO2u8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784782689; c=relaxed/simple; bh=jfgLBeJ5mPfMtL7e/zlITyczBImKqjao9yUWNpolcnU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=pq7BM1MbNh1GRiLEzT8ctKkUQ72MS81kNDypPa4odRj19eYx8HMSxeBncBYaSNYYhXr8OGBIvsoew7MRZ3VkGIaU/M4ifsGZQ17YkGBQRUK1LzPrxdeB/krtfygPqj3FI4sI9FawSGfNbiB5It3pJkGzGVV5wamrJBrIjPh9ke4= 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=qZ8jpXD9; arc=none smtp.client-ip=91.218.175.188 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="qZ8jpXD9" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1784782674; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WLiqeUO9mMdZaSq28GFh6cxKKnMxg3tJr/8P87fRsfA=; b=qZ8jpXD9Z/jiKzsINhUHsr9GRrPLHvZDhSSdFCyPpq39qCSswGPIY/vbjTFRxB63umQj0X eP/zls4gT9lgtuJb9rkufCjPnF5bbDeJMpJfqLzf8zWvV1IYen2aDuRCBzjrE1AycRy/Kx TS+ADgWXFrKBTwRmrrIMr9+IxT+Lwek= From: Ridong To: Andrew Morton , Johannes Weiner Cc: David Hildenbrand , Michal Hocko , Qi Zheng , Shakeel Butt , Lorenzo Stoakes , Kairui Song , Barry Song , Axel Rasmussen , Yuanchu Xie , Wei Xu , Zhongkun He , Muchun Song , Davidlohr Bueso , Roman Gushchin , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Ridong Chen , Ridong Chen Subject: [PATCH v3 2/4] mm: vmscan: propagate real error code from per-node proactive reclaim Date: Thu, 23 Jul 2026 12:57:16 +0800 Message-Id: <20260723045718.2052070-3-ridong.chen@linux.dev> In-Reply-To: <20260723045718.2052070-1-ridong.chen@linux.dev> References: <20260723045718.2052070-1-ridong.chen@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Ridong Chen It has been observed that per-node proactive reclaim always returns -EAGAIN when any error occurs. As discussed in the mailing list [1], the interface should distinguish between cases where no reclaimable memory is left and where another entity is concurrently using the same interface. Propagate the real error code, consistent with how memcg proactive reclaim handles errors. [1] https://lore.kernel.org/all/20250717235604.2atyx2aobwowpge3@offworld/T/= #m3514718be82a31b05726a49da9b61fbfc69a589e Fixes: b980077899ea ("mm: introduce per-node proactive reclaim interface") Reviewed-by: Muchun Song Acked-by: Johannes Weiner Acked-by: Shakeel Butt Reviewed-by: Qi Zheng Reviewed-by: Barry Song Signed-off-by: Ridong Chen --- mm/vmscan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 2c689682b952..4b62d6304c49 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -8023,7 +8023,7 @@ static ssize_t reclaim_store(struct device *dev, int ret, nid =3D dev->id; =20 ret =3D user_proactive_reclaim((char *)buf, NULL, NODE_DATA(nid)); - return ret ? -EAGAIN : count; + return ret ? ret : count; } =20 static DEVICE_ATTR_WO(reclaim); --=20 2.34.1 From nobody Fri Jul 24 05:21:23 2026 Received: from out-186.mta0.migadu.com (out-186.mta0.migadu.com [91.218.175.186]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 741C139CCE9 for ; Thu, 23 Jul 2026 04:58:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.186 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784782700; cv=none; b=EeZubNJlK9yyZGhOJwZH/JuCKbnuy8j38E46wD5V/hqAxqm6B6Nw/t0UdKbRRknxOaT0ms1kFmHFKgaLNjN7SpXA47GqRs3larVAQcFaHI3JywEtDPJdDT92aokIb1aqRfG7/NOh0rhotWj1m0QEFMGeD/HOFW2BAuIY4Ue20Oo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784782700; c=relaxed/simple; bh=54sAy2sJKVv+DV6jvU2/V+KJvNRbfDAZ3Do8FJzl+OE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=nibYL4b0J+gfUxZ94s2F+IUQwHTtzakSWEiNN+W/E6Gaqv/Q5xlQI3NpA8BJI072fkMkjoLM8Dk5h09gtIQNQc+Tl16scRNSzbENmtjgRrgmrET8zJDX4otjJORrBEk8MbFjR+3hpa/gLdWLLQIYd6vVXgQyoBXFr7gb++OXWhA= 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=KmCcYRhu; arc=none smtp.client-ip=91.218.175.186 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="KmCcYRhu" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1784782684; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=prRkJ8J9CasuULDtKNoROjKzd5fvtcvvTAb4zEJwJM4=; b=KmCcYRhu5anAL/i/DX+v0R13XjAs/VaCS4vCeyb8Azi3l4pPu79amO/blrjC9wBfZXozpK kqExUkwMVYAJub9MC9wIPSjENjY0EYPJwQ+sG3C1ODonhgLFznY23i/IJ+gFoQSAVNjY0B mnL00RCS7jFQoHjgYudO/BhyJNiirvs= From: Ridong To: Andrew Morton , Johannes Weiner Cc: David Hildenbrand , Michal Hocko , Qi Zheng , Shakeel Butt , Lorenzo Stoakes , Kairui Song , Barry Song , Axel Rasmussen , Yuanchu Xie , Wei Xu , Zhongkun He , Muchun Song , Davidlohr Bueso , Roman Gushchin , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Ridong Chen , Ridong Chen Subject: [PATCH v3 3/4] mm: vmscan: drop unused gfp_mask parameter from __node_reclaim() Date: Thu, 23 Jul 2026 12:57:17 +0800 Message-Id: <20260723045718.2052070-4-ridong.chen@linux.dev> In-Reply-To: <20260723045718.2052070-1-ridong.chen@linux.dev> References: <20260723045718.2052070-1-ridong.chen@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Ridong Chen Commit 57972c78e678 ("mm/vmscan: make __node_reclaim() more generic") moved the scan_control construction out to the callers and passed the struct in by pointer. After that change every use of the gfp mask inside __node_reclaim() goes through sc->gfp_mask, leaving the gfp_mask parameter unused. Just remove the dead parameter and update the callers accordingly. No functional change. Acked-by: Shakeel Butt Acked-by: Johannes Weiner Reviewed-by: Muchun Song Reviewed-by: Barry Song Reviewed-by: Qi Zheng Signed-off-by: Ridong Chen --- mm/vmscan.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 4b62d6304c49..859655fcf60d 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -7748,7 +7748,7 @@ static unsigned long node_pagecache_reclaimable(struc= t pglist_data *pgdat) /* * Try to free up some pages from this node through reclaim. */ -static unsigned long __node_reclaim(struct pglist_data *pgdat, gfp_t gfp_m= ask, +static unsigned long __node_reclaim(struct pglist_data *pgdat, unsigned long nr_pages, struct scan_control *sc) { @@ -7840,7 +7840,7 @@ int node_reclaim(struct pglist_data *pgdat, gfp_t gfp= _mask, unsigned int order) if (test_and_set_bit_lock(PGDAT_RECLAIM_LOCKED, &pgdat->flags)) return NODE_RECLAIM_NOSCAN; =20 - ret =3D __node_reclaim(pgdat, gfp_mask, nr_pages, &sc) >=3D nr_pages; + ret =3D __node_reclaim(pgdat, nr_pages, &sc) >=3D nr_pages; clear_bit_unlock(PGDAT_RECLAIM_LOCKED, &pgdat->flags); =20 if (ret) @@ -7853,7 +7853,7 @@ int node_reclaim(struct pglist_data *pgdat, gfp_t gfp= _mask, unsigned int order) =20 #else =20 -static unsigned long __node_reclaim(struct pglist_data *pgdat, gfp_t gfp_m= ask, +static unsigned long __node_reclaim(struct pglist_data *pgdat, unsigned long nr_pages, struct scan_control *sc) { @@ -7955,8 +7955,7 @@ int user_proactive_reclaim(char *buf, &pgdat->flags)) return -EBUSY; =20 - reclaimed =3D __node_reclaim(pgdat, gfp_mask, - batch_size, &sc); + reclaimed =3D __node_reclaim(pgdat, batch_size, &sc); clear_bit_unlock(PGDAT_RECLAIM_LOCKED, &pgdat->flags); } =20 --=20 2.34.1 From nobody Fri Jul 24 05:21:23 2026 Received: from out-177.mta0.migadu.com (out-177.mta0.migadu.com [91.218.175.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5D3D939AD34 for ; Thu, 23 Jul 2026 04:58:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784782702; cv=none; b=WX5qxMZy6Zt98cm/l+3lCE+sJOeSHrFvoSqPz38accBsu0fZodzc/Tds2NFh8PyL2rA3cGeIH0ejRrAOyAlcyj8EB8iYRhnrHzsrng8kRjPeQTwj6KAibK9ioL5Sp/HM45Pudc69dxFUpTKIvyIFmCybqRtVqmA3ILHMrJVwsZQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784782702; c=relaxed/simple; bh=4SIdt8gcZYgmAjPe1iTh2g2VN+Fc4FTcz5r0cjppUaU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=nVzVANXAUaNFIxOyLDzuFpu1Pqg3heb5+r2TcOme6uNN5i2805qi40FYhSYRVKVYXGTaWv+PTP72uIbPUTgtkyFp8ulr28DnioVS0tDlrPRmet577AoAiDRE89b9EvIGtdMuJKhr6xynWt7RIjsUEllsUOzUI1X+ALVtPGAkSus= 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=iKpDd6OM; arc=none smtp.client-ip=91.218.175.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="iKpDd6OM" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1784782691; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=tFTqvoKbwMWTXDnYGsKcqBttpTGihYLNyhVUcDk1sMs=; b=iKpDd6OMt2Ad+zyPxrYsQASJgE94Gpi9OqU2Wzp2irDu8KbfmMKkwyX1FwDdqBYjwZ2mMK 65qfiTc2sYQEQ1O/U+f9ijSBssMYOzcrY1SjrQChaE7OQxnWfC9RagIDCFGJebJ5PW6VZF omyQRZser7Eyngef9o0vXHPwKFTAQnA= From: Ridong To: Andrew Morton , Johannes Weiner Cc: David Hildenbrand , Michal Hocko , Qi Zheng , Shakeel Butt , Lorenzo Stoakes , Kairui Song , Barry Song , Axel Rasmussen , Yuanchu Xie , Wei Xu , Zhongkun He , Muchun Song , Davidlohr Bueso , Roman Gushchin , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Ridong Chen , Ridong Chen Subject: [PATCH v3 4/4] mm/mglru: fix anon-only reclaim evicting file pages when swappiness=max Date: Thu, 23 Jul 2026 12:57:18 +0800 Message-Id: <20260723045718.2052070-5-ridong.chen@linux.dev> In-Reply-To: <20260723045718.2052070-1-ridong.chen@linux.dev> References: <20260723045718.2052070-1-ridong.chen@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Ridong Chen The previous patch fixed this issue for the traditional LRU. The same problem exists in MGLRU [1]: when swappiness=3Dmax (SWAPPINESS_ANON_ONLY) is set, reclaim is expected to evict anonymous pages exclusively, but file pages can still be reclaimed when anonymous pages cannot be reclaimed (e.g. no swap and no demotion target). With SWAPPINESS_ANON_ONLY, get_type_to_scan() always returns LRU_GEN_ANON and for_each_evictable_type() only iterates the anon type. But if get_nr_to_scan() does not bail out, evict_folios() still runs and isolate_folios() falls back to scanning file pages in the !scanned case: shrink_one try_to_shrink_lruvec get_swappiness // returns SWAPPINESS_ANON_ONLY for swappiness=3Dmax get_nr_to_scan evict_folios isolate_folios // falls back to file type when !scanned This wrongly evicts file pages, violating the anon-only semantics. Fix it the same way as the traditional LRU: keep returning SWAPPINESS_ANON_ONLY in get_swappiness(), and return 0 from get_nr_to_scan() when SWAPPINESS_ANON_ONLY is set but anon pages cannot be reclaimed. This protects file pages from being reclaimed, and as a side effect avoids the useless scan work. The test result: Before fix: # cat /sys/kernel/mm/lru_gen/enabled 0x0007 # cat memory.stat anon 204800 file 67108864 ... pgsteal_proactive 0 pgscan_proactive 0 # echo "64M swappiness=3Dmax" > memory.reclaim # cat memory.stat anon 208896 file 0 ... pgsteal_proactive 16384 pgscan_proactive 16384 After fix: # cat memory.stat anon 188416 file 67215360 kernel 1970176 ... pgsteal_proactive 0 pgscan_proactive 0 # echo "64M swappiness=3Dmax" > memory.reclaim -bash: echo: write error: Resource temporarily unavailable # cat memory.stat anon 204800 file 67215360 ... pgsteal_proactive 0 pgscan_proactive 0 [1] https://sashiko.dev/#/patchset/20260717113300.214717-1-ridong.chen@linu= x.dev Fixes: 68a1436bde00 ("mm: add swappiness=3Dmax arg to memory.reclaim for on= ly anon reclaim") Acked-by: Qi Zheng Signed-off-by: Ridong Chen --- mm/vmscan.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 859655fcf60d..20cb93fd3da8 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2708,6 +2708,10 @@ static int get_swappiness(struct lruvec *lruvec, str= uct scan_control *sc) { struct mem_cgroup *memcg =3D lruvec_memcg(lruvec); struct pglist_data *pgdat =3D lruvec_pgdat(lruvec); + int swappiness =3D sc_swappiness(sc, memcg); + + if (swappiness =3D=3D SWAPPINESS_ANON_ONLY) + return swappiness; =20 if (!sc->may_swap) return 0; @@ -2716,7 +2720,7 @@ static int get_swappiness(struct lruvec *lruvec, stru= ct scan_control *sc) mem_cgroup_get_nr_swap_pages(memcg) < MIN_LRU_BATCH) return 0; =20 - return sc_swappiness(sc, memcg); + return swappiness; } =20 static int get_nr_gens(struct lruvec *lruvec, int type) @@ -4921,6 +4925,19 @@ static long get_nr_to_scan(struct lruvec *lruvec, st= ruct scan_control *sc, struct mem_cgroup *memcg, int swappiness) { unsigned long nr_to_scan, evictable; + struct pglist_data *pgdat =3D lruvec_pgdat(lruvec); + /* + * Proactive reclaim initiated by userspace for anonymous memory only. + * SWAPPINESS_ANON_ONLY is set only on the proactive reclaim path, so + * warn if it shows up elsewhere. When anon cannot be reclaimed (e.g. + * no swap), return 0 instead of falling through and evicting file + * pages, which would violate the anon-only semantics. + */ + if (swappiness =3D=3D SWAPPINESS_ANON_ONLY && + !can_reclaim_anon_pages(memcg, pgdat->node_id, sc)) { + WARN_ON_ONCE(!sc->proactive); + return 0; + } =20 evictable =3D lruvec_evictable_size(lruvec, swappiness); =20 --=20 2.34.1