From: Longlong Xia <xialonglong2025@163.com>
To: Kairui Song <ryncsn@gmail.com>,
Kemeng Shi <shikemeng@huaweicloud.com>,
Youngjun Park <youngjun.park@lge.com>
Cc: Andrew Morton <akpm@linux-foundation.org>,
Chris Li <chrisl@kernel.org>, Kairui Song <kasong@tencent.com>,
linux-mm@kvack.org, Longlong Xia <xialonglong@kylinos.cn>,
stable@vger.kernel.org
Subject: Re: [PATCH] mm/swap: publish cluster tables after full initialization
Date: Fri, 14 Aug 2026 10:55:09 +0800 [thread overview]
Message-ID: <44eb0883-c49a-4d02-b330-914cd167840c@163.com> (raw)
In-Reply-To: <an3xnGPBCASWuS1w@KASONG-MC4>
Hi Kairui, Youngjun, Kemeng,
Thanks for the comments.
I missed Kemeng's earlier patch and the follow-up discussion. Sorry for the
noise and for the incomplete Cc list.
Since this issue is already being discussed there, I will step back and let
Kemeng continue with the updated version.
Thanks,
Longlong
在 2026/8/14 10:35, Kairui Song 写道:
> On Thu, Aug 13, 2026 at 11:03:16PM +0800, Longlong Xia wrote:
>> From: Longlong Xia <xialonglong@kylinos.cn>
>>
>> swap_cluster_populate() drops the local, global, and cluster locks
>> before its sleeping allocation. The allocation helper publishes ci->table
>> before allocating the memcg table and, on some 32-bit configurations, the
>> zero bitmap.
>>
>> A stale per-CPU or global cluster cursor can reach the isolated cluster in
>> that window. Since CLUSTER_FLAG_NONE and a non-NULL table make the cluster
>> appear usable, it can allocate a slot without the auxiliary state. An
>> auxiliary allocation failure can then tear down a table which is already in
>> use.
>>
>> Allocate the complete set of tables into a private carrier. Install the
>> auxiliary pointers and publish the main table only while holding ci->lock;
>> the slow path does this after reacquiring all allocator locks. Allocation
>> failures now free only unpublished resources.
>>
>> Fixes: b197d41462c2 ("mm/memcg, swap: store cgroup id in cluster table directly")
>> Cc: stable@vger.kernel.org
>> Assisted-by: Codex:gpt-5.6-sol
>> Signed-off-by: Longlong Xia <xialonglong@kylinos.cn>
>> ---
>> mm/swapfile.c | 167 +++++++++++++++++++++++++++++++++++---------------
>> 1 file changed, 117 insertions(+), 50 deletions(-)
>>
> Hi Longlong, thanks for the patch and report.
>
>> diff --git a/mm/swapfile.c b/mm/swapfile.c
>> index 78b49b0658ad..2ca947c540e9 100644
>> --- a/mm/swapfile.c
>> +++ b/mm/swapfile.c
>> @@ -410,6 +410,99 @@ static inline unsigned int cluster_offset(struct swap_info_struct *si,
>> return cluster_index(si, ci) * SWAPFILE_CLUSTER;
>> }
>>
>> +struct swap_cluster_tables {
>> + struct swap_table *table;
>> +#ifdef CONFIG_MEMCG
>> + struct swap_memcg_table *memcg_table;
>> +#endif
>> +#if !SWAP_TABLE_HAS_ZEROFLAG
>> + unsigned long *zero_bitmap;
>> +#endif
>> +};
>> +
>> +static void swap_cluster_tables_free(struct swap_cluster_tables *tables)
>> +{
>> +#ifdef CONFIG_MEMCG
>> + kfree(tables->memcg_table);
>> + tables->memcg_table = NULL;
>> +#endif
>> +
>> +#if !SWAP_TABLE_HAS_ZEROFLAG
>> + kfree(tables->zero_bitmap);
>> + tables->zero_bitmap = NULL;
>> +#endif
>> +
>> + if (!tables->table)
>> + return;
>> +
>> + if (SWP_TABLE_USE_PAGE)
>> + folio_put(virt_to_folio(tables->table));
>> + else
>> + kmem_cache_free(swap_table_cachep, tables->table);
>> + tables->table = NULL;
>> +}
>> +
>> +static int swap_cluster_tables_alloc(struct swap_cluster_tables *tables,
>> + gfp_t gfp)
>> +{
>> + struct folio *folio;
>> +
>> + if (SWP_TABLE_USE_PAGE) {
>> + folio = folio_alloc(gfp | __GFP_ZERO, 0);
>> + if (folio)
>> + tables->table = folio_address(folio);
>> + } else {
>> + tables->table = kmem_cache_zalloc(swap_table_cachep, gfp);
>> + }
>> + if (!tables->table)
>> + return -ENOMEM;
>> +
>> +#ifdef CONFIG_MEMCG
>> + if (!mem_cgroup_disabled()) {
>> + tables->memcg_table = kzalloc_obj(*tables->memcg_table, gfp);
>> + if (!tables->memcg_table)
>> + goto free_tables;
>> + }
>> +#endif
>> +
>> +#if !SWAP_TABLE_HAS_ZEROFLAG
>> + tables->zero_bitmap = bitmap_zalloc(SWAPFILE_CLUSTER, gfp);
>> + if (!tables->zero_bitmap)
>> + goto free_tables;
>> +#endif
>> +
>> + return 0;
>> +
>> +#if defined(CONFIG_MEMCG) || !SWAP_TABLE_HAS_ZEROFLAG
>> +free_tables:
>> + swap_cluster_tables_free(tables);
>> + return -ENOMEM;
>> +#endif
>> +}
>> +
>> +static void swap_cluster_tables_install(struct swap_cluster_info *ci,
>> + struct swap_cluster_tables *tables)
>> +{
>> + lockdep_assert_held(&ci->lock);
>> + VM_WARN_ON_ONCE(ci->flags || !cluster_is_empty(ci));
>> + VM_WARN_ON_ONCE(rcu_access_pointer(ci->table));
>> +
>> +#ifdef CONFIG_MEMCG
>> + VM_WARN_ON_ONCE(ci->memcg_table);
>> + ci->memcg_table = tables->memcg_table;
>> + tables->memcg_table = NULL;
>> +#endif
>> +
>> +#if !SWAP_TABLE_HAS_ZEROFLAG
>> + VM_WARN_ON_ONCE(ci->zero_bitmap);
>> + ci->zero_bitmap = tables->zero_bitmap;
>> + tables->zero_bitmap = NULL;
>> +#endif
>> +
>> + rcu_assign_pointer(ci->table, tables->table);
>> + tables->table = NULL;
>> +}
>> +
> You don't need to shuffle all the code for a simple bug fix, you can use
> forward declaration if some functions are needed earlier.
>
> ...
>
>> /*
>> * Back to atomic context. We might have migrated to a new CPU with a
>> @@ -568,11 +621,19 @@ swap_cluster_populate(struct swap_info_struct *si,
>> spin_lock(&si->global_cluster_lock);
>> spin_lock(&ci->lock);
>>
>> + /* Nothing except this helper should populate an isolated cluster. */
>> + if (WARN_ON_ONCE(cluster_table_is_alloced(ci))) {
>> + swap_cluster_tables_free(&tables);
>> + return ci;
>> + }
>> +
>> if (ret) {
>> move_cluster(si, ci, &si->free_clusters, CLUSTER_FLAG_FREE);
>> spin_unlock(&ci->lock);
>> return NULL;
>> }
>> +
>> + swap_cluster_tables_install(ci, &tables);
> It seems the same fix with Kemeng's patch? Youngjun have notice this too.
> https://lore.kernel.org/linux-mm/20260720071342.50742-2-shikemeng@huaweicloud.com/
>
> And I think you missed some Cc, maybe you can try tools like b4 which
> automatically generate the Cc list for you.
>
> Hello Kemeng, can you help check and see if an updated can be sent?
prev parent reply other threads:[~2026-08-14 2:55 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-13 15:03 [PATCH] mm/swap: publish cluster tables after full initialization Longlong Xia
2026-08-13 19:23 ` Andrew Morton
2026-08-14 1:46 ` Youngjun Park
2026-08-14 2:35 ` Kairui Song
2026-08-14 2:55 ` Longlong Xia [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=44eb0883-c49a-4d02-b330-914cd167840c@163.com \
--to=xialonglong2025@163.com \
--cc=akpm@linux-foundation.org \
--cc=chrisl@kernel.org \
--cc=kasong@tencent.com \
--cc=linux-mm@kvack.org \
--cc=ryncsn@gmail.com \
--cc=shikemeng@huaweicloud.com \
--cc=stable@vger.kernel.org \
--cc=xialonglong@kylinos.cn \
--cc=youngjun.park@lge.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox