Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
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?



      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