Integrate the ZRAM-Reclaim module with core VM paths to enable real-time refault tracking and dynamic scan balance adjustments. Three key hooks are added: 1) Anonymous refault tracking in do_swap_page(): When a swapped-out anonymous page is faulted back in, record a cost event for anonymous pages. This indicates that anonymous memory is actively being used and reclaiming it would incur a decompression cost on refault. 2) File refault tracking in workingset_refault(): When a file page is reactivated from the shadow entries, record a cost event for file pages. This indicates file cache pressure and helps detect when file pages are being thrashed. 3) Scan balance integration in get_scan_count(): Call zram_reclaim_balance_scan() before making scan balance decisions. If the function returns true, skip the default balance logic and set scan_balance = SCAN_ANON. The function may also modify swappiness internally when overload conditions are detected. The tracking uses zram_reclaim_refault_cost() (named lru_note_cost in the original implementation) to update the per-lruvec anon_cost and file_cost counters. These counters are then used by the policy logic introduced in patch 1 to determine if anonymous refault pressure exceeds thresholds. Implementation notes: - The workingset_refault and do_swap_page hooks are guarded by CONFIG_ZRAM_RECLAIM to avoid overhead when the feature is disabled - Each swap-in or refault operation records a cost of 1 page - The lruvec and memcg are looked up from the page and pgdat Signed-off-by: Ze Zuo <zuoze1@huawei.com> Signed-off-by: Nanyong Sun <sunnanyong@huawei.com> --- mm/memory.c | 8 ++++++++ mm/vmscan.c | 6 ++++++ mm/workingset.c | 3 +++ 3 files changed, 17 insertions(+) diff --git a/mm/memory.c b/mm/memory.c index a54204f0f..737ec36ac 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -71,6 +71,7 @@ #include <linux/oom.h> #include <linux/ktask.h> #include <linux/share_pool.h> +#include <linux/zram_reclaim.h> #include <asm/io.h> #include <asm/mmu_context.h> @@ -3068,6 +3069,13 @@ skip_uswap: goto out_page; } +#ifdef CONFIG_ZRAM_RECLAIM + if (memcg) + zram_reclaim_refault_cost(memcg, + mem_cgroup_lruvec(page_pgdat(page), memcg), + false, 1); +#endif + /* * Back out if somebody else already faulted in this pte. */ diff --git a/mm/vmscan.c b/mm/vmscan.c index fa08ffd04..e29b1fe67 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -57,6 +57,7 @@ #include <linux/swapops.h> #include <linux/balloon_compaction.h> #include <linux/mem_reliable.h> +#include <linux/zram_reclaim.h> #include "internal.h" @@ -2379,6 +2380,11 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg, goto out; } + if (zram_reclaim_scan_balance(lruvec, memcg, &swappiness)) { + scan_balance = SCAN_ANON; + goto out; + } + /* * Prevent the reclaimer from falling into the cache trap: as * cache pages start out inactive, every cache fault will tip diff --git a/mm/workingset.c b/mm/workingset.c index a1f61b3a0..8e74fea40 100644 --- a/mm/workingset.c +++ b/mm/workingset.c @@ -15,6 +15,7 @@ #include <linux/dax.h> #include <linux/fs.h> #include <linux/mm.h> +#include <linux/zram_reclaim.h> /* * Double CLOCK lists @@ -291,6 +292,8 @@ bool workingset_refault(void *shadow) inc_lruvec_state(lruvec, WORKINGSET_REFAULT); + zram_reclaim_refault_cost(memcg, lruvec, true, 1); + if (refault_distance <= active_file) { inc_lruvec_state(lruvec, WORKINGSET_ACTIVATE); rcu_read_unlock(); -- 2.33.0