From nobody Sat Feb 7 21:24:40 2026 Received: from out-180.mta0.migadu.com (out-180.mta0.migadu.com [91.218.175.180]) (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 D0B3548166B; Wed, 21 Jan 2026 12:40:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768999221; cv=none; b=tPwoxBKVKar5bR2qiMOXisAtzGampz2bDcZyIogUNfvJQgLzAy1RJlI9yVsAjklEXVF5DlwkBmiwKG1ECGEErXvFoJ8y69812hxSSQZtYVLKDn8gfSYSd0gC+e/AYJD43Saw+aBskVd7Sro35reKtCydpsUoa0BPf9K47/nrAdw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768999221; c=relaxed/simple; bh=o2PQazJGiOOsfBalbp7C2mvB9kNuqvABUGRvq8ihU8c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KIhmXZOXzqrghwE9S9uQBCWGx78t1aVGd7YvPvUbPEmF8McdYweJWFPjEwY/zX3E0Y+9h7+816Kf+wVV6cjkQVAi+algbx6GRCwbmD9JxXlm/HXEgKu5iFggaeTXtmGLFn+ysJBbj+DaJKthm8U8wQqM554mgxCPiscmnFPrhXY= 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=FXaeL+YP; arc=none smtp.client-ip=91.218.175.180 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="FXaeL+YP" 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=1768999215; 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=T/OqE0ydtm9JkTAiuYuoK4hbHLjWKG5nWVyw4vzq10Y=; b=FXaeL+YPA/JmFJNJXBNvEweyQrlFdOfXe48axrvpijrU//10I6yRcz2r0gEpEw/qP/JWeW t8KRG2OxI5b5PhB9BBxnR1zwPG6G2ieHEW46c6c6HTk0bz9Etrn9GRQi4P1dm8p1saIdJu YNOBF1YssN94gM/XXAVWojOZGtqtIdI= From: Jiayuan Chen To: linux-mm@kvack.org Cc: Jiayuan Chen , Tejun Heo , Johannes Weiner , =?UTF-8?q?Michal=20Koutn=C3=BD?= , Jonathan Corbet , Andrew Morton , David Hildenbrand , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Axel Rasmussen , Yuanchu Xie , Wei Xu , Roman Gushchin , Shakeel Butt , Muchun Song , Qi Zheng , cgroups@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 1/3] mm/lru_gen: refactor to extract helper functions Date: Wed, 21 Jan 2026 20:39:47 +0800 Message-ID: <20260121123955.84806-2-jiayuan.chen@linux.dev> In-Reply-To: <20260121123955.84806-1-jiayuan.chen@linux.dev> References: <20260121123955.84806-1-jiayuan.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: Jiayuan Chen Extract helper functions from debugfs interface for code reuse: - lru_gen_print_lruvec(): Print generations for a single lruvec, extracted from lru_gen_seq_show(). - __run_cmd(): Core command execution logic, extracted from run_cmd(). These helpers will be used by the upcoming memcg interface. No functional change. Signed-off-by: Jiayuan Chen --- mm/vmscan.c | 82 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 34 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 619691aa4393..8ea5b67daa36 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -5397,29 +5397,13 @@ static void lru_gen_seq_show_full(struct seq_file *= m, struct lruvec *lruvec, seq_putc(m, '\n'); } =20 -/* see Documentation/admin-guide/mm/multigen_lru.rst for details */ -static int lru_gen_seq_show(struct seq_file *m, void *v) +/* Print generations for a single lruvec - helper for debugfs and memcg */ +static void lru_gen_print_lruvec(struct seq_file *m, struct lruvec *lruvec, + unsigned long max_seq, unsigned long *min_seq, + bool full) { unsigned long seq; - bool full =3D debugfs_get_aux_num(m->file); - struct lruvec *lruvec =3D v; struct lru_gen_folio *lrugen =3D &lruvec->lrugen; - int nid =3D lruvec_pgdat(lruvec)->node_id; - struct mem_cgroup *memcg =3D lruvec_memcg(lruvec); - DEFINE_MAX_SEQ(lruvec); - DEFINE_MIN_SEQ(lruvec); - - if (nid =3D=3D first_memory_node) { - const char *path =3D memcg ? m->private : ""; - -#ifdef CONFIG_MEMCG - if (memcg) - cgroup_path(memcg->css.cgroup, m->private, PATH_MAX); -#endif - seq_printf(m, "memcg %5hu %s\n", mem_cgroup_id(memcg), path); - } - - seq_printf(m, " node %5d\n", nid); =20 if (!full) seq =3D evictable_min_seq(min_seq, MAX_SWAPPINESS / 2); @@ -5431,7 +5415,7 @@ static int lru_gen_seq_show(struct seq_file *m, void = *v) for (; seq <=3D max_seq; seq++) { int type, zone; int gen =3D lru_gen_from_seq(seq); - unsigned long birth =3D READ_ONCE(lruvec->lrugen.timestamps[gen]); + unsigned long birth =3D READ_ONCE(lrugen->timestamps[gen]); =20 seq_printf(m, " %10lu %10u", seq, jiffies_to_msecs(jiffies - birth)); =20 @@ -5450,7 +5434,31 @@ static int lru_gen_seq_show(struct seq_file *m, void= *v) if (full) lru_gen_seq_show_full(m, lruvec, max_seq, min_seq, seq); } +} + +/* see Documentation/admin-guide/mm/multigen_lru.rst for details */ +static int lru_gen_seq_show(struct seq_file *m, void *v) +{ + bool full =3D debugfs_get_aux_num(m->file); + struct lruvec *lruvec =3D v; + int nid =3D lruvec_pgdat(lruvec)->node_id; + struct mem_cgroup *memcg =3D lruvec_memcg(lruvec); + DEFINE_MAX_SEQ(lruvec); + DEFINE_MIN_SEQ(lruvec); + + if (nid =3D=3D first_memory_node) { + const char *path =3D memcg ? m->private : ""; + +#ifdef CONFIG_MEMCG + if (memcg) + cgroup_path(memcg->css.cgroup, m->private, PATH_MAX); +#endif + seq_printf(m, "memcg %5hu %s\n", mem_cgroup_id(memcg), path); + } =20 + seq_printf(m, " node %5d\n", nid); + + lru_gen_print_lruvec(m, lruvec, max_seq, min_seq, full); return 0; } =20 @@ -5501,6 +5509,24 @@ static int run_eviction(struct lruvec *lruvec, unsig= ned long seq, struct scan_co return -EINTR; } =20 +/* Core command execution - helper for debugfs and memcg */ +static int __run_cmd(char cmd, struct lruvec *lruvec, unsigned long seq, + struct scan_control *sc, int swappiness, unsigned long opt) +{ + if (swappiness < MIN_SWAPPINESS) + swappiness =3D get_swappiness(lruvec, sc); + else if (swappiness > SWAPPINESS_ANON_ONLY) + return -EINVAL; + + switch (cmd) { + case '+': + return run_aging(lruvec, seq, swappiness, opt); + case '-': + return run_eviction(lruvec, seq, sc, swappiness, opt); + } + return -EINVAL; +} + static int run_cmd(char cmd, int memcg_id, int nid, unsigned long seq, struct scan_control *sc, int swappiness, unsigned long opt) { @@ -5530,19 +5556,7 @@ static int run_cmd(char cmd, int memcg_id, int nid, = unsigned long seq, sc->target_mem_cgroup =3D memcg; lruvec =3D get_lruvec(memcg, nid); =20 - if (swappiness < MIN_SWAPPINESS) - swappiness =3D get_swappiness(lruvec, sc); - else if (swappiness > SWAPPINESS_ANON_ONLY) - goto done; - - switch (cmd) { - case '+': - err =3D run_aging(lruvec, seq, swappiness, opt); - break; - case '-': - err =3D run_eviction(lruvec, seq, sc, swappiness, opt); - break; - } + err =3D __run_cmd(cmd, lruvec, seq, sc, swappiness, opt); done: mem_cgroup_put(memcg); =20 --=20 2.43.0 From nobody Sat Feb 7 21:24:40 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 A783848AE22 for ; Wed, 21 Jan 2026 12:40:26 +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=1768999229; cv=none; b=UJMrk6dXfzSqxNKtyf2sv4opAcRPvTDez5ZRWOfSugbKDguzYlNuJmNlcHZ2GQd3X6eS0w9XJkbdnrFjGcikelr7YCBdyj2uTEOVm8aA6zhxdz/HOypOGdIaKl1kRf9EpuuhXtgeOo+dzWuwKkso++L3ypW3dyjFeNPgV0bOoNM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768999229; c=relaxed/simple; bh=zew5EPs717atHyJFUgxBnAkH6NyfFZa2MuxiI/3qqLA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QfgnINSbDmXX/M3SGt4AKPaUUtVo4bqk++M8HKGk2u/3gyfTOR4QiaTuHmM9i6Uxc6IBl+upDYlgfQb8wJjZHZ2lcjzQyWOxdF8bD+H93pLHCnsS2CNfb5Gx8veVcRJg08s2th4QXlqsoLTusFrbw8LpZgeynuFxHsm9ukacrOo= 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=H8Is8c8I; 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="H8Is8c8I" 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=1768999223; 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=ub1o/UU9lFxzM8mJWX00aqCeT1WEF1iMiFUlWX3OVEs=; b=H8Is8c8IaHPnOwad/rRTj56YFZ8Ms799UmTCQhh71bj3jzuRNfese7/hBIpKIhBgFRgVdG TBwbsDV3zHmS/E+2KoQrQ7t9wPO+SfdsIzGqtes5hBe2I/CaZUBNA85ELYcUt4ULAcYZq0 StruNHCC2ipA6tBTOIqK5AlfM9tYtr4= From: Jiayuan Chen To: linux-mm@kvack.org Cc: Jiayuan Chen , Tejun Heo , Johannes Weiner , =?UTF-8?q?Michal=20Koutn=C3=BD?= , Jonathan Corbet , Andrew Morton , David Hildenbrand , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Axel Rasmussen , Yuanchu Xie , Wei Xu , Roman Gushchin , Shakeel Butt , Muchun Song , Qi Zheng , cgroups@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 2/3] mm/lru_gen: add memory.lru_gen interface for cgroup v2 Date: Wed, 21 Jan 2026 20:39:48 +0800 Message-ID: <20260121123955.84806-3-jiayuan.chen@linux.dev> In-Reply-To: <20260121123955.84806-1-jiayuan.chen@linux.dev> References: <20260121123955.84806-1-jiayuan.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: Jiayuan Chen Add a memory.lru_gen interface to cgroup v2 that allows users to interact with MGLRU directly on a specific cgroup without needing to know the internal memcg_id. Read (cat memory.lru_gen): Display lru_gen information for this memcg across all NUMA nodes. Write (echo to memory.lru_gen): Execute aging or eviction commands. Format: cmd nid seq [swappiness] [opt] cmd: '+' for aging, '-' for eviction nid: node id seq: generation sequence number swappiness: optional, or 'max' for anonymous memory only opt: force_scan for aging, nr_to_reclaim for eviction Example: # Show lru_gen info cat /sys/fs/cgroup/mygroup/memory.lru_gen # Run aging on node 0 with seq 100 echo '+ 0 100' > /sys/fs/cgroup/mygroup/memory.lru_gen # Run eviction on node 0 with seq 99, swappiness 50, reclaim 1000 pages echo '- 0 99 50 1000' > /sys/fs/cgroup/mygroup/memory.lru_gen Test result: cgcreate -g memory:test_group // create 1GB page cache, loop access 200MB as hot pages. cgexec -g memory:test_group ./cache_sim & cat /sys/fs/cgroup/test_group/memory.lru_gen node 0 (min_seq=3D0/0, max_seq=3D3) 0 48744 0 4 1 48744 0 0 2 48744 24 262144 3 48744 0 0 node 1 (min_seq=3D0/0, max_seq=3D3) 0 48744 0 0 1 48744 0 0 2 48744 1 0 3 48744 0 0 // age echo '+ 0 3' > /sys/fs/cgroup/test_group/memory.lru_gen cat /sys/fs/cgroup/test_group/memory.lru_gen memcg 35 /test_group node 0 (min_seq=3D1/1, max_seq=3D4) 1 216564 0 3 2 216564 24 262144 3 216564 0 1 4 14936 0 0 node 1 (min_seq=3D0/0, max_seq=3D3) 0 216564 0 0 1 216564 0 0 2 216564 1 0 3 216564 0 0 // age echo '+ 0 4' > /sys/fs/cgroup/test_group/memory.lru_gen cat /sys/fs/cgroup/test_group/memory.lru_gen memcg 35 /test_group node 0 (min_seq=3D2/2, max_seq=3D5) 2 266880 23 210947 3 266880 0 1 4 65252 1 51200 5 9320 0 0 node 1 (min_seq=3D0/0, max_seq=3D3) 0 266880 0 0 1 266880 0 0 2 266880 1 0 3 266880 0 0 // age echo '+ 0 5' > /sys/fs/cgroup/test_group/memory.lru_gen node 0 (min_seq=3D3/3, max_seq=3D6) 3 318384 0 210948 4 116756 0 0 5 60824 1 51200 6 3408 23 0 node 1 (min_seq=3D0/0, max_seq=3D3) 0 318384 0 0 1 318384 0 0 2 318384 1 0 3 318384 0 0 // reclaim 200000 pages echo '- 0 3 0 200000' > /sys/fs/cgroup/test_group/memory.lru_gen cat /sys/fs/cgroup/test_group/memory.lru_gen node 0 (min_seq=3D3/3, max_seq=3D6) 3 760308 0 10884 4 558680 0 0 5 502748 1 51200 6 445332 23 0 node 1 (min_seq=3D0/0, max_seq=3D3) 0 760308 0 0 1 760308 0 0 2 760308 1 0 3 760308 0 0 // reclaim 20000 pages echo '- 0 3 0 20000' > /sys/fs/cgroup/test_group/memory.lru_gen cat /sys/fs/cgroup/test_group/memory.lru_gen node 0 (min_seq=3D3/5, max_seq=3D6) 3 826864 0 0 4 625236 0 0 5 569304 1 51201 6 511888 23 0 node 1 (min_seq=3D0/0, max_seq=3D3) 0 826864 0 0 1 826864 0 0 2 826864 1 0 3 826864 0 0 Signed-off-by: Jiayuan Chen --- include/linux/mmzone.h | 16 +++++++ mm/memcontrol.c | 31 ++++++++++++++ mm/vmscan.c | 94 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index fc5d6c88d2f0..8edb9549b435 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -625,6 +625,11 @@ void lru_gen_offline_memcg(struct mem_cgroup *memcg); void lru_gen_release_memcg(struct mem_cgroup *memcg); void lru_gen_soft_reclaim(struct mem_cgroup *memcg, int nid); =20 +/* memcg interface */ +struct seq_file; +void lru_gen_seq_show_memcg(struct seq_file *m, struct mem_cgroup *memcg); +int lru_gen_seq_write_memcg(struct mem_cgroup *memcg, char *buf); + #else /* !CONFIG_LRU_GEN */ =20 static inline void lru_gen_init_pgdat(struct pglist_data *pgdat) @@ -664,6 +669,17 @@ static inline void lru_gen_soft_reclaim(struct mem_cgr= oup *memcg, int nid) { } =20 +struct seq_file; +static inline void lru_gen_seq_show_memcg(struct seq_file *m, + struct mem_cgroup *memcg) +{ +} + +static inline int lru_gen_seq_write_memcg(struct mem_cgroup *memcg, char *= buf) +{ + return -EOPNOTSUPP; +} + #endif /* CONFIG_LRU_GEN */ =20 struct lruvec { diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 75fc22a33b28..e2f13a69b891 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -4565,6 +4565,30 @@ static ssize_t memory_oom_group_write(struct kernfs_= open_file *of, return nbytes; } =20 +#ifdef CONFIG_LRU_GEN +static int memory_lru_gen_show(struct seq_file *m, void *v) +{ + struct mem_cgroup *memcg =3D mem_cgroup_from_seq(m); + + lru_gen_seq_show_memcg(m, memcg); + return 0; +} + +static ssize_t memory_lru_gen_write(struct kernfs_open_file *of, char *buf, + size_t nbytes, loff_t off) +{ + struct mem_cgroup *memcg =3D mem_cgroup_from_css(of_css(of)); + int ret; + + buf =3D strstrip(buf); + ret =3D lru_gen_seq_write_memcg(memcg, buf); + if (ret) + return ret; + + return nbytes; +} +#endif + static ssize_t memory_reclaim(struct kernfs_open_file *of, char *buf, size_t nbytes, loff_t off) { @@ -4649,6 +4673,13 @@ static struct cftype memory_files[] =3D { .flags =3D CFTYPE_NS_DELEGATABLE, .write =3D memory_reclaim, }, +#ifdef CONFIG_LRU_GEN + { + .name =3D "lru_gen", + .seq_show =3D memory_lru_gen_show, + .write =3D memory_lru_gen_write, + }, +#endif { } /* terminate */ }; =20 diff --git a/mm/vmscan.c b/mm/vmscan.c index 8ea5b67daa36..43f38f9f43c5 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -5668,6 +5668,100 @@ static const struct file_operations lru_gen_ro_fops= =3D { .release =3D seq_release, }; =20 +/*************************************************************************= ***** + * memcg interface + *************************************************************************= *****/ + +void lru_gen_seq_show_memcg(struct seq_file *m, struct mem_cgroup *memcg) +{ + int nid; + char *path; + + path =3D kvmalloc(PATH_MAX, GFP_KERNEL); +#ifdef CONFIG_MEMCG + if (memcg && path) + cgroup_path(memcg->css.cgroup, path, PATH_MAX); +#endif + seq_printf(m, "memcg %5hu %s\n", mem_cgroup_id(memcg), + (memcg && path) ? path : ""); + kvfree(path); + + for_each_node_state(nid, N_MEMORY) { + struct lruvec *lruvec =3D get_lruvec(memcg, nid); + DEFINE_MAX_SEQ(lruvec); + DEFINE_MIN_SEQ(lruvec); + + seq_printf(m, " node %5d (min_seq=3D%lu/%lu, max_seq=3D%lu)\n", + nid, min_seq[LRU_GEN_ANON], min_seq[LRU_GEN_FILE], max_seq); + lru_gen_print_lruvec(m, lruvec, max_seq, min_seq, false); + } +} + +int lru_gen_seq_write_memcg(struct mem_cgroup *memcg, char *buf) +{ + char *cur, *next; + unsigned int flags; + struct blk_plug plug; + int err =3D -EINVAL; + struct scan_control sc =3D { + .may_writepage =3D true, + .may_unmap =3D true, + .may_swap =3D true, + .reclaim_idx =3D MAX_NR_ZONES - 1, + .gfp_mask =3D GFP_KERNEL, + .proactive =3D true, + .target_mem_cgroup =3D memcg, + }; + + set_task_reclaim_state(current, &sc.reclaim_state); + flags =3D memalloc_noreclaim_save(); + blk_start_plug(&plug); + if (!set_mm_walk(NULL, true)) { + err =3D -ENOMEM; + goto done; + } + + next =3D buf; + while ((cur =3D strsep(&next, ",;\n"))) { + int n, end; + char cmd, swap_str[5]; + unsigned int nid, swappiness =3D -1; + unsigned long seq, opt =3D -1; + struct lruvec *lruvec; + + cur =3D skip_spaces(cur); + if (!*cur) + continue; + + n =3D sscanf(cur, "%c %u %lu %n %4s %n %lu %n", &cmd, &nid, + &seq, &end, swap_str, &end, &opt, &end); + if (n < 3 || cur[end]) { + err =3D -EINVAL; + break; + } + if (n > 3 && strcmp("max", swap_str) =3D=3D 0) + swappiness =3D SWAPPINESS_ANON_ONLY; + else if (n > 3 && kstrtouint(swap_str, 0, &swappiness)) + break; + + if (nid >=3D MAX_NUMNODES || !node_state(nid, N_MEMORY)) { + err =3D -EINVAL; + break; + } + + lruvec =3D get_lruvec(memcg, nid); + err =3D __run_cmd(cmd, lruvec, seq, &sc, swappiness, opt); + if (err) + break; + } +done: + clear_mm_walk(); + blk_finish_plug(&plug); + memalloc_noreclaim_restore(flags); + set_task_reclaim_state(current, NULL); + return err; +} + /*************************************************************************= ***** * initialization *************************************************************************= *****/ --=20 2.43.0 From nobody Sat Feb 7 21:24:40 2026 Received: from out-178.mta0.migadu.com (out-178.mta0.migadu.com [91.218.175.178]) (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 A70EB481FAC for ; Wed, 21 Jan 2026 12:40:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768999238; cv=none; b=fYJ0Zk6cNcuc5eEdH3SFpjjzaXI/LXio6SaTAsFsYFeQFllwD3c+G1RfJJ5UWWa4txd4szP+fUTZjcHsiRvqYYl1KTw4P7nnswOQK1aHH1G4ehq7znDNW62sDHNNhujYLVFgXBS39nwYWPgq6ovqEY3YbrJ9O3aNC4MnrIiDQSU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768999238; c=relaxed/simple; bh=KX0jdUNzXru7m+7hjkqbLQeZGOGKF1Jq6B5UtBA/uVA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PkH03FoIkUe7QR6PoWPkaljJutBKWIzD9dZjUSCgYfFN74Iy7/IeQ7jBGrscdtWd39zUvj4Qmum4n7l6nHvuwa/lslgSOB4JZMPoScI2B1JO8PFbCBAzsEosE2IHhpMF9u4MB5K7cyWrBPLMYhRlgGVLHdHmT7cNlH/WIppjf04= 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=vYegVE80; arc=none smtp.client-ip=91.218.175.178 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="vYegVE80" 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=1768999233; 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=P/QIycmg/Rp660OZ1P92MK5kFHPJosNCmQKo3uxOY+w=; b=vYegVE80q2P99aKNiXmOPWPUQvsIvoabN/PTHj4Kum0jSGe4HmwxKwWaVgP+XTxQLU9Vc+ xDL3GVtpm/ae90vlif6u21ElxIQ6gqwqm9oy1I8eyEFB4UGCb5zfTqhGJgQigxRYLi34D1 Ueac4zqmHjZtQ1v/IRwv8W4qr+aZYv4= From: Jiayuan Chen To: linux-mm@kvack.org Cc: Jiayuan Chen , Tejun Heo , Johannes Weiner , =?UTF-8?q?Michal=20Koutn=C3=BD?= , Jonathan Corbet , Andrew Morton , Axel Rasmussen , Yuanchu Xie , Wei Xu , David Hildenbrand , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Roman Gushchin , Shakeel Butt , Muchun Song , Qi Zheng , cgroups@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 3/3] docs/cgroup: document memory.lru_gen interface Date: Wed, 21 Jan 2026 20:39:49 +0800 Message-ID: <20260121123955.84806-4-jiayuan.chen@linux.dev> In-Reply-To: <20260121123955.84806-1-jiayuan.chen@linux.dev> References: <20260121123955.84806-1-jiayuan.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: Jiayuan Chen Add documentation for the memory.lru_gen interface in cgroup v2. For detailed information about MGLRU and the command format, refer to the multi-gen LRU documentation. Signed-off-by: Jiayuan Chen --- Documentation/admin-guide/cgroup-v2.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-= guide/cgroup-v2.rst index 7f5b59d95fce..bb3ca7ffd600 100644 --- a/Documentation/admin-guide/cgroup-v2.rst +++ b/Documentation/admin-guide/cgroup-v2.rst @@ -1426,6 +1426,23 @@ PAGE_SIZE multiple when read back. This means that the networking layer will not adapt based on reclaim induced by memory.reclaim. =20 + memory.lru_gen + A read-write file that exists when CONFIG_LRU_GEN is enabled. + + Reading this file displays the multi-gen LRU information for + this memcg, including generation numbers, page counts for + anonymous and file pages across all NUMA nodes. + + Writing to this file allows performing aging or eviction + operations on this memcg. The format is:: + + echo ' [ []]' > memory.lru_gen + + This interface provides the same functionality as the debugfs + lru_gen interface but operates directly on the cgroup without + requiring the memcg_id. For detailed documentation of the + command format and MGLRU, see Documentation/admin-guide/mm/multigen_lru.r= st. + The following nested keys are defined. =20 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --=20 2.43.0