From nobody Mon Sep 28 13:16:51 2026 Received: from mta1.migadu.com (out-73.mta1.migadu.com [95.215.58.73]) (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 64CF8397925 for ; Fri, 21 Aug 2026 08:18:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787300296; cv=none; b=Xf7Wvgn5YldJFhQsMjawksaXdZ6ZeIjNMAJx5eN8d7sMR5WDlHglVdsjIOYMop8wZPD/6YUUp8xtbFAhgKXARWEYHoB7ENh1RN4qBzE32EjGV6hvZvmW/ryxBwgt9zxREbiFYUyV3xQnwJ4CZbhi0erBRL/RtbfNwOWYSXWolAE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787300296; c=relaxed/simple; bh=oOaNAC0BAF0dHeX/TLdwJ+nW9WDxq122HtWUDNIDsqU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=fxyoAfTJ3hYpM0buTOqvnGtzDj0WupQWiKXuLXwXqtCBVE7pBXSgAtpoa2DmJjgQSdz1uLpzerJ0I+toq2j1+/bXDbI/rlpy3xCuJjEc2C1jWIXeDcGvwKqTXDLSRiQani0Ex0BepPYjT7C7YvjffIdyeWsaWmERE9zTJA3vuw4= 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=GG/0Pz/M; arc=none smtp.client-ip=95.215.58.73 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="GG/0Pz/M" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=oOaNAC0BAF0dHeX/TLdwJ+nW9WDxq122HtWUDNIDsqU=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1787300290; v=1; x=1787905090; b=GG/0Pz/MVJq+imhtxEWCZU9fZtdKr8trWjaVkMoLg/Pcx0/u7Mi8cvoO06TZVZtQWZnFibj7 cEgWGIk2yGsBLpulQIgzKJRSn7/hp2xEzvxYS9e5VNrRHiIb6tDg1wBn2xZGYtSRR1epLXXv/cp HiO8KQHFooUpWZav7yqgGvZY= X-Envelope-To: linux-kernel@vger.kernel.org Received: from mi-ThinkCentre-M760t.mioffice.cn (14.29.108.92) by smtp.migadu.com with ESMTPS id 9bdf8f2d2f2975d5; Fri, 21 Aug 2026 08:18:10 +0000 X-Mizu-Trace-ID: 9bdf8f2d2f2975d5 X-Migadu-Flow: FLOW_OUT From: Ridong Chen 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 , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Ridong Chen , Ridong Chen Subject: [RFC PATCH 1/4] mm/vmscan: only reclaim slab in node reclaim when over min_slab_pages Date: Fri, 21 Aug 2026 16:17:38 +0800 Message-Id: <20260821081741.1340277-2-ridong.chen@linux.dev> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260821081741.1340277-1-ridong.chen@linux.dev> References: <20260821081741.1340277-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 Content-Type: text/plain; charset="utf-8" From: Ridong Chen Since commit d8ff6fde8e88 ("mm/vmscan: take min_slab_pages into account when try to call shrink_node"), node reclaim enters shrink_node() when reclaimable slab is over min_slab_pages OR unmapped page cache is over min_unmapped_pages. But the threshold only decides whether to enter shrink_node(), not what it reclaims. min_slab_pages is documented to gate slab reclaim alone: "On Zone reclaim slabs will be reclaimed if more than this percentage of pages in a zone are reclaimable slab pages". Yet once unmapped page cache alone trips the gate, shrink_node() still invokes the slab shrinkers and can drive reclaimable slab below min_slab_pages. Carry the decision into the reclaim path via a scan_control flag and skip the slab shrinkers when reclaimable slab is already at or below min_slab_pages, so the limit gates slab reclaim as documented. The flag defaults to zero, so kswapd, direct reclaim, memcg reclaim, proactive reclaim and drop_caches are unaffected; only the node reclaim path sets it. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Ridong Chen --- mm/vmscan.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index c17ac77b08a4..7e65d0ba4a96 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -114,6 +114,12 @@ struct scan_control { /* zone_reclaim_mode, boost reclaim, cgroup restrictions */ unsigned int may_swap:1; =20 + /* + * When set, the slab shrinkers are not invoked because reclaimable + * slab is already at or below min_slab_pages. + */ + unsigned int skip_slab_reclaim:1; + /* Not allow cache_trim_mode to be turned on as part of reclaim? */ unsigned int no_cache_trim_mode:1; =20 @@ -5120,7 +5126,8 @@ static int shrink_one(struct lruvec *lruvec, struct s= can_control *sc) =20 need_rotate =3D try_to_shrink_lruvec(lruvec, sc); =20 - shrink_slab(sc->gfp_mask, pgdat->node_id, memcg, sc->priority); + if (!sc->skip_slab_reclaim) + shrink_slab(sc->gfp_mask, pgdat->node_id, memcg, sc->priority); =20 if (!sc->proactive) vmpressure(sc->gfp_mask, sc->order, memcg, false, @@ -6237,8 +6244,9 @@ static void shrink_node_memcgs(pg_data_t *pgdat, stru= ct scan_control *sc) =20 shrink_lruvec(lruvec, sc); =20 - shrink_slab(sc->gfp_mask, pgdat->node_id, memcg, - sc->priority); + if (!sc->skip_slab_reclaim) + shrink_slab(sc->gfp_mask, pgdat->node_id, memcg, + sc->priority); =20 /* Record the group's reclaim efficiency */ if (!sc->proactive) @@ -7940,6 +7948,15 @@ unsigned long node_reclaim(struct pglist_data *pgdat= , gfp_t gfp_mask, unsigned i if (test_and_set_bit_lock(PGDAT_RECLAIM_LOCKED, &pgdat->flags)) return 0; =20 + /* + * min_slab_pages only gates slab reclaim: when reclaimable slab is + * already at or below the limit, leave the shrinkers alone even if we + * entered node reclaim to trim unmapped page cache. + */ + sc.skip_slab_reclaim =3D + node_page_state_pages(pgdat, NR_SLAB_RECLAIMABLE_B) <=3D + pgdat->min_slab_pages; + ret =3D __node_reclaim(pgdat, nr_pages, &sc); clear_bit_unlock(PGDAT_RECLAIM_LOCKED, &pgdat->flags); =20 --=20 2.34.1 From nobody Mon Sep 28 13:16:51 2026 Received: from mta1.migadu.com (out-83.mta1.migadu.com [95.215.58.83]) (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 6C23B394464 for ; Fri, 21 Aug 2026 08:18:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.83 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787300303; cv=none; b=G+w33pPBzZsBIIXqmRKJD5RbeuC586zAd4Z7DaxR//cnU2NXMYoieeS7wFUavajY17FqC4THB2im1O0O3Y8HfhbyGZdFHz2+cN56L3+z5C8fxBwZd23UjdWMuX83k72u3GxFQTwSUisKParDHUrCLBMl3x1SdbelhR5hAsIBQOc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787300303; c=relaxed/simple; bh=oF3Xg/TnqDvbGLvbtogk/iCkdQNbS9f5eo1eLB3uyV4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=mGxZBfcKrWivk4s522snZIw+SZ9aS3h2veNKlfqGJSfz/OkeklbFdHCJ+Umkl+L8rQEUHLFZj3OwB8pufeT/x/ZnA7qDRfFrPWkXvpbeERLl6Ljfu4lgKDzrFbaeSLWZY0F6Scnju1QV8u7mgyplsB0yo36FrW/WtDe8CF9WI54= 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=Hc19s1hj; arc=none smtp.client-ip=95.215.58.83 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="Hc19s1hj" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=oF3Xg/TnqDvbGLvbtogk/iCkdQNbS9f5eo1eLB3uyV4=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1787300299; v=1; x=1787905099; b=Hc19s1hj2o0kH6uSVxt2ukZlpqKaUBHjDmSi47JlJWqnWF1ZeIPeCVCeBI6VfnkDke1cY2Tt En4G7PLvA1E+alHNeE6Gi9uxZw/hkcpfpU0EQkc/C0vo6U2SEJLCuNFUCV51iHi1NUfxDc492aX S3Vdskb6J8BnYpNOqTj2oEFQ= X-Envelope-To: linux-kernel@vger.kernel.org Received: from mi-ThinkCentre-M760t.mioffice.cn (14.29.108.92) by smtp.migadu.com with ESMTPS id 9af9ce5e2af12ca6; Fri, 21 Aug 2026 08:18:19 +0000 X-Mizu-Trace-ID: 9af9ce5e2af12ca6 X-Migadu-Flow: FLOW_OUT From: Ridong Chen 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 , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Ridong Chen , Ridong Chen Subject: [RFC PATCH 2/4] mm/vmscan: only reclaim file pages in node reclaim when over min_unmapped_pages Date: Fri, 21 Aug 2026 16:17:39 +0800 Message-Id: <20260821081741.1340277-3-ridong.chen@linux.dev> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260821081741.1340277-1-ridong.chen@linux.dev> References: <20260821081741.1340277-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 Content-Type: text/plain; charset="utf-8" From: Ridong Chen Node reclaim enters shrink_node() when unmapped page cache is over min_unmapped_pages OR reclaimable slab is over min_slab_pages, but the threshold only decides whether to enter shrink_node(), not what it reclaims. min_unmapped_pages is documented to keep a small amount of unmapped page cache around so that file I/O is not immediately thrown out: "Zone reclaim will only occur if more than this percentage of pages are in a state that zone_reclaim_mode allows to be reclaimed." Yet once slab alone trips the gate, shrink_node() still reclaims file pages and can drive unmapped page cache below min_unmapped_pages, defeating the protection. Carry the decision into the reclaim path via a scan_control flag set only on the node reclaim path, and honour it on both reclaim implementations: - traditional LRU: get_scan_count() forces SCAN_ANON, or scans nothing when anon cannot be reclaimed (e.g. no swap), rather than falling back to SCAN_FILE and breaching the floor; - MGLRU: scan_folios() leaves the file type alone, and isolate_folios() falls back to anon. The flag defaults to zero, so kswapd, direct reclaim, memcg reclaim, proactive reclaim and drop_caches are unaffected; only the node reclaim path sets it. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Ridong Chen --- mm/vmscan.c | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 7e65d0ba4a96..1e56973ceb73 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -120,6 +120,12 @@ struct scan_control { */ unsigned int skip_slab_reclaim:1; =20 + /* + * When set, file pages are not reclaimed because unmapped page cache + * is already at or below min_unmapped_pages. + */ + unsigned int skip_file_reclaim:1; + /* Not allow cache_trim_mode to be turned on as part of reclaim? */ unsigned int no_cache_trim_mode:1; =20 @@ -2581,6 +2587,21 @@ static void get_scan_count(struct lruvec *lruvec, st= ruct scan_control *sc, goto out; } =20 + /* + * node_reclaim protects unmapped page cache down to + * min_unmapped_pages: skip file pages and reclaim anon only. As with + * the anon-only case above, if anon cannot be reclaimed there is + * nothing to do without breaching the floor, so scan nothing. + */ + if (sc->skip_file_reclaim) { + 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; @@ -4749,6 +4770,14 @@ static int scan_folios(unsigned long nr_to_scan, str= uct lruvec *lruvec, VM_WARN_ON_ONCE(nr_to_scan > MAX_LRU_BATCH); VM_WARN_ON_ONCE(!list_empty(list)); =20 + /* + * node_reclaim protects unmapped page cache down to min_unmapped_pages, + * so leave the file type alone; isolate_folios() then falls back to + * anon. + */ + if (sc->skip_file_reclaim && type =3D=3D LRU_GEN_FILE) + return 0; + if (get_nr_gens(lruvec, type) =3D=3D MIN_NR_GENS) return 0; =20 @@ -7949,13 +7978,16 @@ unsigned long node_reclaim(struct pglist_data *pgda= t, gfp_t gfp_mask, unsigned i return 0; =20 /* - * min_slab_pages only gates slab reclaim: when reclaimable slab is - * already at or below the limit, leave the shrinkers alone even if we - * entered node reclaim to trim unmapped page cache. + * Each limit only gates its own type of reclaim. When reclaimable + * slab or unmapped page cache is already at or below its limit, leave + * that type alone even if the other type tripped the gate and brought + * us into node reclaim. */ sc.skip_slab_reclaim =3D node_page_state_pages(pgdat, NR_SLAB_RECLAIMABLE_B) <=3D pgdat->min_slab_pages; + sc.skip_file_reclaim =3D + node_pagecache_reclaimable(pgdat) <=3D pgdat->min_unmapped_pages; =20 ret =3D __node_reclaim(pgdat, nr_pages, &sc); clear_bit_unlock(PGDAT_RECLAIM_LOCKED, &pgdat->flags); --=20 2.34.1 From nobody Mon Sep 28 13:16:51 2026 Received: from mta0.migadu.com (out-182.mta0.migadu.com [91.218.175.182]) (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 53AC13B05BC for ; Fri, 21 Aug 2026 08:18:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787300311; cv=none; b=kCALz6eO36welum29d9LJcdWAnKVneJ6qKtWzOgF9PjG452iSXpTl4Z+tuFwqhQkfKnpztTZTfFvQj4A2F3yDHppFcD65DHl0zLMHkTJ3cWml0zeRUTSm9g0yNRU4Zrr21HYTEuEAHE5SG7ZrtU0nT0rf1c4ggwR0xzdEdldWyc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787300311; c=relaxed/simple; bh=ZAscUiHq/rYEWDhnt5RfykoKmzATq1btSoHBcxnZeVk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=pmAXW2UMPHFZgrUg3OI9Eqxqklkc0JyYFN8AdrfLAwskAIDuKYZD2yzSBD5/OBTK3G6PIrKGo4sUihpJexYnZpUhyig3jHRkWjfAdfIxt3naSOWGxQJri57LBQyk3QO8ouxwyMYzXxHTDPuf1dTRRmhI35Hny1vNK+5U1/ibAGI= 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=hJDuNPG/; arc=none smtp.client-ip=91.218.175.182 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="hJDuNPG/" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=ZAscUiHq/rYEWDhnt5RfykoKmzATq1btSoHBcxnZeVk=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1787300308; v=1; x=1787905108; b=hJDuNPG/aIrW3VicCgnYHMPfZFZcSKAzqkrKsTLse2VIpQ+LXI0Lc8Z/t8Kt9/MNARyi+lAO zJxztGQe2GX1ukUqyOoRSYY3f4hvV8TDVqCR2+VZoqYhdeuolzlyU01k5+Aj+nszdlDwxKMx/Ku nPmZFeepM4GaB5y5mUn7Ahk0= X-Envelope-To: linux-kernel@vger.kernel.org Received: from mi-ThinkCentre-M760t.mioffice.cn (14.29.108.92) by smtp.migadu.com with ESMTPS id 9be2503217972ce1; Fri, 21 Aug 2026 08:18:27 +0000 X-Mizu-Trace-ID: 9be2503217972ce1 X-Migadu-Flow: FLOW_OUT From: Ridong Chen 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 , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Ridong Chen , Ridong Chen Subject: [RFC PATCH 3/4] mm/vmscan: drop the combined limit gate in __node_reclaim() Date: Fri, 21 Aug 2026 16:17:40 +0800 Message-Id: <20260821081741.1340277-4-ridong.chen@linux.dev> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260821081741.1340277-1-ridong.chen@linux.dev> References: <20260821081741.1340277-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 Content-Type: text/plain; charset="utf-8" From: Ridong Chen __node_reclaim() only ran shrink_node() when unmapped page cache was over min_unmapped_pages OR reclaimable slab was over min_slab_pages. With slab and file reclaim now gated per type by sc->skip_slab_reclaim and sc->skip_file_reclaim, this combined gate is either redundant or harmful: - for the NUMA node reclaim caller it is always true, since node_reclaim() only calls in when at least one limit is exceeded; - for the per-node proactive reclaim caller (which does not go through node_reclaim()'s checks) it wrongly suppressed all reclaim -- anon included -- whenever both page cache and slab happened to sit at or below their limits, even with plenty of reclaimable anon present. Drop the gate and let the per-type flags decide what to reclaim. The node reclaim path is unchanged; the proactive path can now reclaim anon as requested. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Ridong Chen Acked-by: Johannes Weiner --- mm/vmscan.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 1e56973ceb73..5a3f67b3ba32 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -7906,16 +7906,16 @@ static unsigned long __node_reclaim(struct pglist_d= ata *pgdat, noreclaim_flag =3D memalloc_noreclaim_save(); set_task_reclaim_state(p, &sc->reclaim_state); =20 - if (node_pagecache_reclaimable(pgdat) > pgdat->min_unmapped_pages || - node_page_state_pages(pgdat, NR_SLAB_RECLAIMABLE_B) > pgdat->min_slab= _pages) { - /* - * Free memory by calling shrink node with increasing - * priorities until we have enough memory freed. - */ - do { - shrink_node(pgdat, sc); - } while (sc->nr_reclaimed < nr_pages && --sc->priority >=3D 0); - } + /* + * Free memory by calling shrink node with increasing + * priorities until we have enough memory freed. + * + * What to reclaim is gated per type by sc->skip_slab_reclaim and + * sc->skip_file_reclaim. + */ + do { + shrink_node(pgdat, sc); + } while (sc->nr_reclaimed < nr_pages && --sc->priority >=3D 0); =20 set_task_reclaim_state(p, NULL); memalloc_noreclaim_restore(noreclaim_flag); --=20 2.34.1 From nobody Mon Sep 28 13:16:51 2026 Received: from mta1.migadu.com (out-97.mta1.migadu.com [95.215.58.97]) (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 3F445397925 for ; Fri, 21 Aug 2026 08:18:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.97 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787300320; cv=none; b=D15bQA6IfQhbOuyfM3s+m1w0MCi+Z/hgWSztaNXu0Xa0O0FwXUT0VGFqVtUYxOHPfCtCyinxh0hf3Ba+pgf0heCa3NLcyIOgpJ/73fX3BvCfU3K4dUdk39UpptKXje1ge34Pz8/lXvzN2B90z7gtqj1njVdUUerqYY8gxQnK5FU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787300320; c=relaxed/simple; bh=fJJAB3mxKN0RQHrysuI3TTh1XFgddk39iuxEmKJOrQA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ZEEMkUi1pchSwoMRdcv16uxNtOGY4Ku+JXsw7pKeNxZ+VBnq8/aCFpFkH50nHuuApFPrMh2xDMD3mRyD3j5Xqw9fp9BRbxo0j9u++WM+OHs1VG4362y1Aza6DR8i4cMv6YUxyC0Ezddihgj8AElA0Y5NRdAEhTP6wHgdEZeQNYY= 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=YSaPexXk; arc=none smtp.client-ip=95.215.58.97 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="YSaPexXk" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=fJJAB3mxKN0RQHrysuI3TTh1XFgddk39iuxEmKJOrQA=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1787300317; v=1; x=1787905117; b=YSaPexXkkBbpuiGTT2njGMF5J9pDV9XbBEy0BPn+Lj7OHwpC/pCLQEgTcdUa57r64VBvqk95 GiK74xc1YxFJdQhfhrssN96+e7bENLaCpejk6VAuwyxk12r3HUgBpK3JNlO1tmjyTk31rGrKvGv cgmSr23w/8U64mF+8LNalBnU= X-Envelope-To: linux-kernel@vger.kernel.org Received: from mi-ThinkCentre-M760t.mioffice.cn (14.29.108.92) by smtp.migadu.com with ESMTPS id 69efcddfc4b900a9; Fri, 21 Aug 2026 08:18:36 +0000 X-Mizu-Trace-ID: 69efcddfc4b900a9 X-Migadu-Flow: FLOW_OUT From: Ridong Chen 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 , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Ridong Chen , Ridong Chen Subject: [RFC PATCH 4/4] mm/vmscan: do not skip node reclaim when only anon is reclaimable Date: Fri, 21 Aug 2026 16:17:41 +0800 Message-Id: <20260821081741.1340277-5-ridong.chen@linux.dev> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260821081741.1340277-1-ridong.chen@linux.dev> References: <20260821081741.1340277-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 Content-Type: text/plain; charset="utf-8" From: Ridong Chen node_reclaim() bailed out with "return 0" whenever both unmapped page cache and reclaimable slab were at or below their limits: if (node_pagecache_reclaimable(pgdat) <=3D pgdat->min_unmapped_pages && node_page_state_pages(pgdat, NR_SLAB_RECLAIMABLE_B) <=3D pgdat->min_slab_pages) return 0; But min_unmapped_pages and min_slab_pages only describe file and slab; they say nothing about anonymous memory, which node reclaim is otherwise happy to reclaim (may_swap is set, swappiness applies). So a node with little page cache and slab but plenty of reclaimable anon was skipped entirely, even though there was anon to free. Require in addition that anon cannot be reclaimed before bailing out, so the early return only triggers when none of the three types has anything to reclaim. When anon is reclaimable the per-type flags leave file and slab alone, so shrink_node reclaims anon only; checking can_reclaim_anon_pages() here also avoids entering reclaim just to scan without freeing anything when swap and demotion are both unavailable. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Ridong Chen --- mm/vmscan.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 5a3f67b3ba32..8c706807da44 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -7945,18 +7945,14 @@ unsigned long node_reclaim(struct pglist_data *pgda= t, gfp_t gfp_mask, unsigned i }; =20 /* - * Node reclaim reclaims unmapped file backed pages and - * slab pages if we are over the defined limits. - * - * A small portion of unmapped file backed pages is needed for - * file I/O otherwise pages read by file I/O will be immediately - * thrown out if the node is overallocated. So we do not reclaim - * if less than a specified percentage of the node is used by - * unmapped file backed pages. + * min_unmapped_pages and min_slab_pages only gate file and slab. + * Bail out only when both are under their limits and anon cannot + * be reclaimed either, so we do not skip reclaimable anon. */ if (node_pagecache_reclaimable(pgdat) <=3D pgdat->min_unmapped_pages && node_page_state_pages(pgdat, NR_SLAB_RECLAIMABLE_B) <=3D - pgdat->min_slab_pages) + pgdat->min_slab_pages && + !can_reclaim_anon_pages(NULL, pgdat->node_id, &sc)) return 0; =20 /* --=20 2.34.1