Linux Documentation
 help / color / mirror / Atom feed
* [PATCH 0/2] mm/vmscan: remove obsolete offlined memcg reclaim handling
@ 2026-10-28  1:06 T.J. Mercier
  2026-10-28  1:06 ` [PATCH 2/2] mm/mglru: stop rotating offlined memcgs to the old generation T.J. Mercier
  0 siblings, 1 reply; 4+ messages in thread
From: T.J. Mercier @ 2026-10-28  1:06 UTC (permalink / raw)
  To: roman.gushchin, muchun.song, Andrew Morton, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, David Hildenbrand, Lorenzo Stoakes,
	Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Jonathan Corbet, Shuah Khan,
	Randy Dunlap, Johannes Weiner
  Cc: cgroups, T.J. Mercier, linux-mm, linux-doc, linux-kernel

Since commit f1cf8d2f36dc ("mm: memcontrol: eliminate the problem of
dying memory cgroup for LRU folios") and commit 0e0ac326c511 ("memcg:
move LRU size accounting on reparenting instead of copying it"), LRU
folios and their size accounting are reparented to the parent memcg
before a memcg is offlined, leaving the offlined memcg's lruvec
permanently empty.

This series removes the remaining reclaim special-casing for offlined
memcgs that assumed they could still hold LRU folios:
    1. Remove redundant !mem_cgroup_online() checks in vmscan.c
    2. Stop rotating offlined memcgs to the head of the old generation
       (MEMCG_LRU_OLD) in MGLRU.

T.J. Mercier (2):
  mm/vmscan: remove redundant !mem_cgroup_online() checks
  mm/mglru: stop rotating offlined memcgs to the old generation

 Documentation/mm/multigen_lru.rst |  4 +--
 include/linux/mmzone.h            | 22 +++++---------
 mm/memcontrol.c                   |  1 -
 mm/vmscan.c                       | 48 ++++---------------------------
 4 files changed, 14 insertions(+), 61 deletions(-)


base-commit: 2bba28e98578de622ef307d00875aa8f8bca3d10
-- 
2.56.0.307.g5fe7bd680c-goog


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 2/2] mm/mglru: stop rotating offlined memcgs to the old generation
  2026-10-28  1:06 [PATCH 0/2] mm/vmscan: remove obsolete offlined memcg reclaim handling T.J. Mercier
@ 2026-10-28  1:06 ` T.J. Mercier
  2026-10-28  2:42   ` Balbir Singh
  2026-10-28 10:43   ` Kairui Song
  0 siblings, 2 replies; 4+ messages in thread
From: T.J. Mercier @ 2026-10-28  1:06 UTC (permalink / raw)
  To: roman.gushchin, muchun.song, Andrew Morton, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, David Hildenbrand, Lorenzo Stoakes,
	Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Jonathan Corbet, Shuah Khan,
	Randy Dunlap, Johannes Weiner
  Cc: cgroups, T.J. Mercier, linux-mm, linux-doc, linux-kernel

lru_gen_offline_memcg() moves an offlining memcg to the head of the old
generation of the memcg LRU (MEMCG_LRU_OLD), so that global reclaim
visits it first and evicts the folios it left behind.

Since commit f1cf8d2f36dc ("mm: memcontrol: eliminate the problem of
dying memory cgroup for LRU folios"), those folios are reparented to the
parent before lru_gen_offline_memcg() runs, and nothing can be added
back to the offlined memcg's lruvec afterwards. Putting an empty
offlined memcg at the head of the old generation no longer serves any
purpose and only delays reclaim from the memcgs that still have memory
due to additional shrink_many() iteration.

Remove lru_gen_offline_memcg(), so that an offlined memcg is rotated
like any other memcg below the reclaimable size threshold until
lru_gen_release_memcg() takes it off the memcg LRU. MEMCG_LRU_OLD has no
other user, so remove the op and update the memcg LRU comment as well.

Signed-off-by: T.J. Mercier <tjmercier@google.com>
---
 Documentation/mm/multigen_lru.rst |  4 +---
 include/linux/mmzone.h            | 14 +++-----------
 mm/memcontrol.c                   |  1 -
 mm/vmscan.c                       | 20 +-------------------
 4 files changed, 5 insertions(+), 34 deletions(-)

diff --git a/Documentation/mm/multigen_lru.rst b/Documentation/mm/multigen_lru.rst
index 52ed5092022f..b532ce961371 100644
--- a/Documentation/mm/multigen_lru.rst
+++ b/Documentation/mm/multigen_lru.rst
@@ -234,9 +234,7 @@ the active/inactive LRU (of folios):
 1. It has the young and the old (generations), i.e., the counterparts
    to the active and the inactive;
 2. The increment of ``max_seq`` triggers promotion, i.e., the
-   counterpart to activation;
-3. Other events trigger similar operations, e.g., offlining an memcg
-   triggers demotion, i.e., the counterpart to deactivation.
+   counterpart to activation.
 
 In terms of global reclaim, it has two distinct features:
 
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 7f078ff0dd76..542e465ee7a1 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -626,12 +626,10 @@ struct lru_gen_mm_walk {
  * per-node memcg generation counter, whose reminder (mod MEMCG_NR_GENS) indexes
  * the old generation, is incremented when all its bins become empty.
  *
- * There are three operations:
+ * There are two operations:
  * 1. MEMCG_LRU_TAIL, which moves a memcg to the tail of a random bin in its
  *    current generation (old or young) and updates its "seg" to "tail";
- * 2. MEMCG_LRU_OLD, which moves a memcg to the head of a random bin in the old
- *    generation, updates its "gen" to "old" and resets its "seg" to "default";
- * 3. MEMCG_LRU_YOUNG, which moves a memcg to the tail of a random bin in the
+ * 2. MEMCG_LRU_YOUNG, which moves a memcg to the tail of a random bin in the
  *    young generation, updates its "gen" to "young" and resets its "seg" to
  *    "default".
  *
@@ -643,8 +641,7 @@ struct lru_gen_mm_walk {
  * 3. The second attempt to reclaim a memcg below reclaimable size threshold,
  *    which triggers MEMCG_LRU_YOUNG;
  * 4. Attempting to reclaim a memcg below min, which triggers MEMCG_LRU_YOUNG;
- * 5. Finishing the aging on the eviction path, which triggers MEMCG_LRU_YOUNG;
- * 6. Offlining a memcg, which triggers MEMCG_LRU_OLD.
+ * 5. Finishing the aging on the eviction path, which triggers MEMCG_LRU_YOUNG.
  *
  * Notes:
  * 1. Memcg LRU only applies to global reclaim, and the round-robin incrementing
@@ -675,7 +672,6 @@ bool lru_gen_look_around(struct page_vma_mapped_walk *pvmw, unsigned int nr);
 void lru_gen_init_memcg(struct mem_cgroup *memcg);
 void lru_gen_exit_memcg(struct mem_cgroup *memcg);
 void lru_gen_online_memcg(struct mem_cgroup *memcg);
-void lru_gen_offline_memcg(struct mem_cgroup *memcg);
 void lru_gen_release_memcg(struct mem_cgroup *memcg);
 void max_lru_gen_memcg(struct mem_cgroup *memcg, int nid);
 bool recheck_lru_gen_max_memcg(struct mem_cgroup *memcg, int nid);
@@ -709,10 +705,6 @@ static inline void lru_gen_online_memcg(struct mem_cgroup *memcg)
 {
 }
 
-static inline void lru_gen_offline_memcg(struct mem_cgroup *memcg)
-{
-}
-
 static inline void lru_gen_release_memcg(struct mem_cgroup *memcg)
 {
 }
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index a05d9a8baa1b..e2ddf0680e62 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -4475,7 +4475,6 @@ static void mem_cgroup_css_offline(struct cgroup_subsys_state *css)
 	memcg_reparent_objcgs(memcg);
 	reparent_shrinker_deferred(memcg);
 	wb_memcg_offline(memcg);
-	lru_gen_offline_memcg(memcg);
 
 	drain_all_stock(memcg);
 
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 636152d8c94d..45a2c1021f4f 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -4538,7 +4538,6 @@ bool lru_gen_look_around(struct page_vma_mapped_walk *pvmw, unsigned int nr)
 enum {
 	MEMCG_LRU_NOP,
 	MEMCG_LRU_TAIL,
-	MEMCG_LRU_OLD,
 	MEMCG_LRU_YOUNG,
 };
 
@@ -4560,8 +4559,6 @@ static void lru_gen_rotate_memcg(struct lruvec *lruvec, int op)
 	/* see the comment on MEMCG_NR_GENS */
 	if (op == MEMCG_LRU_TAIL)
 		seg = MEMCG_LRU_TAIL;
-	else if (op == MEMCG_LRU_OLD)
-		new = get_memcg_gen(pgdat->memcg_lru.seq);
 	else if (op == MEMCG_LRU_YOUNG)
 		new = get_memcg_gen(pgdat->memcg_lru.seq + 1);
 	else
@@ -4571,11 +4568,7 @@ static void lru_gen_rotate_memcg(struct lruvec *lruvec, int op)
 	WRITE_ONCE(lruvec->lrugen.gen, new);
 
 	hlist_nulls_del_rcu(&lruvec->lrugen.list);
-
-	if (op == MEMCG_LRU_OLD)
-		hlist_nulls_add_head_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[new][bin]);
-	else
-		hlist_nulls_add_tail_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[new][bin]);
+	hlist_nulls_add_tail_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[new][bin]);
 
 	pgdat->memcg_lru.nr_memcgs[old]--;
 	pgdat->memcg_lru.nr_memcgs[new]++;
@@ -4613,17 +4606,6 @@ void lru_gen_online_memcg(struct mem_cgroup *memcg)
 	}
 }
 
-void lru_gen_offline_memcg(struct mem_cgroup *memcg)
-{
-	int nid;
-
-	for_each_node(nid) {
-		struct lruvec *lruvec = get_lruvec(memcg, nid);
-
-		lru_gen_rotate_memcg(lruvec, MEMCG_LRU_OLD);
-	}
-}
-
 void lru_gen_release_memcg(struct mem_cgroup *memcg)
 {
 	int gen;
-- 
2.56.0.307.g5fe7bd680c-goog


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 2/2] mm/mglru: stop rotating offlined memcgs to the old generation
  2026-10-28  1:06 ` [PATCH 2/2] mm/mglru: stop rotating offlined memcgs to the old generation T.J. Mercier
@ 2026-10-28  2:42   ` Balbir Singh
  2026-10-28 10:43   ` Kairui Song
  1 sibling, 0 replies; 4+ messages in thread
From: Balbir Singh @ 2026-10-28  2:42 UTC (permalink / raw)
  To: T.J. Mercier
  Cc: roman.gushchin, muchun.song, Andrew Morton, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, David Hildenbrand, Lorenzo Stoakes,
	Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Jonathan Corbet, Shuah Khan,
	Randy Dunlap, Johannes Weiner, cgroups, linux-mm, linux-doc,
	linux-kernel

On Tue, Oct 27, 2026 at 06:06:06PM -0700, T.J. Mercier wrote:
> lru_gen_offline_memcg() moves an offlining memcg to the head of the old
> generation of the memcg LRU (MEMCG_LRU_OLD), so that global reclaim
> visits it first and evicts the folios it left behind.
> 
> Since commit f1cf8d2f36dc ("mm: memcontrol: eliminate the problem of
> dying memory cgroup for LRU folios"), those folios are reparented to the
> parent before lru_gen_offline_memcg() runs, and nothing can be added
> back to the offlined memcg's lruvec afterwards. Putting an empty
> offlined memcg at the head of the old generation no longer serves any
> purpose and only delays reclaim from the memcgs that still have memory
> due to additional shrink_many() iteration.
> 
> Remove lru_gen_offline_memcg(), so that an offlined memcg is rotated
> like any other memcg below the reclaimable size threshold until
> lru_gen_release_memcg() takes it off the memcg LRU. MEMCG_LRU_OLD has no
> other user, so remove the op and update the memcg LRU comment as well.
> 
> Signed-off-by: T.J. Mercier <tjmercier@google.com>
> ---
>  Documentation/mm/multigen_lru.rst |  4 +---
>  include/linux/mmzone.h            | 14 +++-----------
>  mm/memcontrol.c                   |  1 -
>  mm/vmscan.c                       | 20 +-------------------
>  4 files changed, 5 insertions(+), 34 deletions(-)
> 
> diff --git a/Documentation/mm/multigen_lru.rst b/Documentation/mm/multigen_lru.rst
> index 52ed5092022f..b532ce961371 100644
> --- a/Documentation/mm/multigen_lru.rst
> +++ b/Documentation/mm/multigen_lru.rst
> @@ -234,9 +234,7 @@ the active/inactive LRU (of folios):
>  1. It has the young and the old (generations), i.e., the counterparts
>     to the active and the inactive;
>  2. The increment of ``max_seq`` triggers promotion, i.e., the
> -   counterpart to activation;
> -3. Other events trigger similar operations, e.g., offlining an memcg
> -   triggers demotion, i.e., the counterpart to deactivation.
> +   counterpart to activation.
>  
>  In terms of global reclaim, it has two distinct features:
>  
> diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
> index 7f078ff0dd76..542e465ee7a1 100644
> --- a/include/linux/mmzone.h
> +++ b/include/linux/mmzone.h
> @@ -626,12 +626,10 @@ struct lru_gen_mm_walk {
>   * per-node memcg generation counter, whose reminder (mod MEMCG_NR_GENS) indexes
>   * the old generation, is incremented when all its bins become empty.
>   *
> - * There are three operations:
> + * There are two operations:
>   * 1. MEMCG_LRU_TAIL, which moves a memcg to the tail of a random bin in its
>   *    current generation (old or young) and updates its "seg" to "tail";
> - * 2. MEMCG_LRU_OLD, which moves a memcg to the head of a random bin in the old
> - *    generation, updates its "gen" to "old" and resets its "seg" to "default";
> - * 3. MEMCG_LRU_YOUNG, which moves a memcg to the tail of a random bin in the
> + * 2. MEMCG_LRU_YOUNG, which moves a memcg to the tail of a random bin in the
>   *    young generation, updates its "gen" to "young" and resets its "seg" to
>   *    "default".
>   *
> @@ -643,8 +641,7 @@ struct lru_gen_mm_walk {
>   * 3. The second attempt to reclaim a memcg below reclaimable size threshold,
>   *    which triggers MEMCG_LRU_YOUNG;
>   * 4. Attempting to reclaim a memcg below min, which triggers MEMCG_LRU_YOUNG;
> - * 5. Finishing the aging on the eviction path, which triggers MEMCG_LRU_YOUNG;
> - * 6. Offlining a memcg, which triggers MEMCG_LRU_OLD.
> + * 5. Finishing the aging on the eviction path, which triggers MEMCG_LRU_YOUNG.
>   *
>   * Notes:
>   * 1. Memcg LRU only applies to global reclaim, and the round-robin incrementing
> @@ -675,7 +672,6 @@ bool lru_gen_look_around(struct page_vma_mapped_walk *pvmw, unsigned int nr);
>  void lru_gen_init_memcg(struct mem_cgroup *memcg);
>  void lru_gen_exit_memcg(struct mem_cgroup *memcg);
>  void lru_gen_online_memcg(struct mem_cgroup *memcg);
> -void lru_gen_offline_memcg(struct mem_cgroup *memcg);
>  void lru_gen_release_memcg(struct mem_cgroup *memcg);
>  void max_lru_gen_memcg(struct mem_cgroup *memcg, int nid);
>  bool recheck_lru_gen_max_memcg(struct mem_cgroup *memcg, int nid);
> @@ -709,10 +705,6 @@ static inline void lru_gen_online_memcg(struct mem_cgroup *memcg)
>  {
>  }
>  
> -static inline void lru_gen_offline_memcg(struct mem_cgroup *memcg)
> -{
> -}
> -
>  static inline void lru_gen_release_memcg(struct mem_cgroup *memcg)
>  {
>  }
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index a05d9a8baa1b..e2ddf0680e62 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -4475,7 +4475,6 @@ static void mem_cgroup_css_offline(struct cgroup_subsys_state *css)
>  	memcg_reparent_objcgs(memcg);
>  	reparent_shrinker_deferred(memcg);
>  	wb_memcg_offline(memcg);
> -	lru_gen_offline_memcg(memcg);
>  
>  	drain_all_stock(memcg);
>  
> diff --git a/mm/vmscan.c b/mm/vmscan.c
> index 636152d8c94d..45a2c1021f4f 100644
> --- a/mm/vmscan.c
> +++ b/mm/vmscan.c
> @@ -4538,7 +4538,6 @@ bool lru_gen_look_around(struct page_vma_mapped_walk *pvmw, unsigned int nr)
>  enum {
>  	MEMCG_LRU_NOP,
>  	MEMCG_LRU_TAIL,
> -	MEMCG_LRU_OLD,
>  	MEMCG_LRU_YOUNG,
>  };
>  
> @@ -4560,8 +4559,6 @@ static void lru_gen_rotate_memcg(struct lruvec *lruvec, int op)
>  	/* see the comment on MEMCG_NR_GENS */
>  	if (op == MEMCG_LRU_TAIL)
>  		seg = MEMCG_LRU_TAIL;
> -	else if (op == MEMCG_LRU_OLD)
> -		new = get_memcg_gen(pgdat->memcg_lru.seq);
>  	else if (op == MEMCG_LRU_YOUNG)
>  		new = get_memcg_gen(pgdat->memcg_lru.seq + 1);
>  	else
> @@ -4571,11 +4568,7 @@ static void lru_gen_rotate_memcg(struct lruvec *lruvec, int op)
>  	WRITE_ONCE(lruvec->lrugen.gen, new);
>  
>  	hlist_nulls_del_rcu(&lruvec->lrugen.list);
> -
> -	if (op == MEMCG_LRU_OLD)
> -		hlist_nulls_add_head_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[new][bin]);
> -	else
> -		hlist_nulls_add_tail_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[new][bin]);
> +	hlist_nulls_add_tail_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[new][bin]);
>  
>  	pgdat->memcg_lru.nr_memcgs[old]--;
>  	pgdat->memcg_lru.nr_memcgs[new]++;
> @@ -4613,17 +4606,6 @@ void lru_gen_online_memcg(struct mem_cgroup *memcg)
>  	}
>  }
>  
> -void lru_gen_offline_memcg(struct mem_cgroup *memcg)
> -{
> -	int nid;
> -
> -	for_each_node(nid) {
> -		struct lruvec *lruvec = get_lruvec(memcg, nid);
> -
> -		lru_gen_rotate_memcg(lruvec, MEMCG_LRU_OLD);
> -	}
> -}
> -
>  void lru_gen_release_memcg(struct mem_cgroup *memcg)
>  {
>  	int gen;

Acked-by: Balbir Singh <balbirs@nvidia.com>

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 2/2] mm/mglru: stop rotating offlined memcgs to the old generation
  2026-10-28  1:06 ` [PATCH 2/2] mm/mglru: stop rotating offlined memcgs to the old generation T.J. Mercier
  2026-10-28  2:42   ` Balbir Singh
@ 2026-10-28 10:43   ` Kairui Song
  1 sibling, 0 replies; 4+ messages in thread
From: Kairui Song @ 2026-10-28 10:43 UTC (permalink / raw)
  To: T.J. Mercier
  Cc: roman.gushchin, muchun.song, Andrew Morton, Kairui Song, Qi Zheng,
	Shakeel Butt, Barry Song, Axel Rasmussen, Yuanchu Xie, Wei Xu,
	Baoquan He, Baolin Wang, David Hildenbrand, Lorenzo Stoakes,
	Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Jonathan Corbet, Shuah Khan,
	Randy Dunlap, Johannes Weiner, cgroups, linux-mm, linux-doc,
	linux-kernel

On Tue, Oct 27, 2026 at 06:06:06PM +0800, T.J. Mercier wrote:
> lru_gen_offline_memcg() moves an offlining memcg to the head of the old
> generation of the memcg LRU (MEMCG_LRU_OLD), so that global reclaim
> visits it first and evicts the folios it left behind.
> 
> Since commit f1cf8d2f36dc ("mm: memcontrol: eliminate the problem of
> dying memory cgroup for LRU folios"), those folios are reparented to the
> parent before lru_gen_offline_memcg() runs, and nothing can be added
> back to the offlined memcg's lruvec afterwards. Putting an empty
> offlined memcg at the head of the old generation no longer serves any
> purpose and only delays reclaim from the memcgs that still have memory
> due to additional shrink_many() iteration.
> 
> Remove lru_gen_offline_memcg(), so that an offlined memcg is rotated
> like any other memcg below the reclaimable size threshold until
> lru_gen_release_memcg() takes it off the memcg LRU. MEMCG_LRU_OLD has no
> other user, so remove the op and update the memcg LRU comment as well.
> 
> Signed-off-by: T.J. Mercier <tjmercier@google.com>
> ---
>  Documentation/mm/multigen_lru.rst |  4 +---
>  include/linux/mmzone.h            | 14 +++-----------
>  mm/memcontrol.c                   |  1 -
>  mm/vmscan.c                       | 20 +-------------------
>  4 files changed, 5 insertions(+), 34 deletions(-)
> 

...

> diff --git a/mm/vmscan.c b/mm/vmscan.c
> index 636152d8c94d..45a2c1021f4f 100644
> --- a/mm/vmscan.c
> +++ b/mm/vmscan.c
> @@ -4538,7 +4538,6 @@ bool lru_gen_look_around(struct page_vma_mapped_walk *pvmw, unsigned int nr)
>  enum {
>  	MEMCG_LRU_NOP,
>  	MEMCG_LRU_TAIL,
> -	MEMCG_LRU_OLD,
>  	MEMCG_LRU_YOUNG,
>  };

I think there could be other usage of this LRU_OLD macro, but indeed
offline is the only user currently, removing it is cleaner.

And everything looks good to me, thanks!

Reviewed-by: Kairui Song <kasong@tencent.com>

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-10-28 10:43 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-28  1:06 [PATCH 0/2] mm/vmscan: remove obsolete offlined memcg reclaim handling T.J. Mercier
2026-10-28  1:06 ` [PATCH 2/2] mm/mglru: stop rotating offlined memcgs to the old generation T.J. Mercier
2026-10-28  2:42   ` Balbir Singh
2026-10-28 10:43   ` Kairui Song

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox