All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Nhat Pham" <nphamcs@gmail.com>, akpm@linux-foundation.org
Cc: chrisl@kernel.org, kasong@tencent.com, hannes@cmpxchg.org,
	mhocko@kernel.org, roman.gushchin@linux.dev,
	shakeel.butt@linux.dev, yosry@kernel.org, david@kernel.org,
	muchun.song@linux.dev, shikemeng@huaweicloud.com,
	baoquan.he@linux.dev, baohua@kernel.org, youngjun.park@lge.com,
	chengming.zhou@linux.dev, ljs@kernel.org, liam@infradead.org,
	vbabka@kernel.org, rppt@kernel.org, surenb@google.com,
	qi.zheng@linux.dev, axelrasmussen@google.com, yuanchu@google.com,
	weixugc@google.com, riel@surriel.com, gourry@gourry.net,
	haowenchao22@gmail.com, corbet@lwn.net, hughd@google.com,
	baolin.wang@linux.alibaba.com, tj@kernel.org, mkoutny@suse.com,
	skhan@linuxfoundation.org, rdunlap@infradead.org,
	kunwu.chan@linux.dev, kernel-team@meta.com, linux-mm@kvack.org
Subject: Re: [PATCH v6 06/12] mm, swap: write back vswap zswap entries to physical swap
Date: Thu, 22 Oct 2026 06:19:17 +0000	[thread overview]
Message-ID: <sashiko-outbox-181080@kernel.org> (raw)
In-Reply-To: <20261021060323.553433-7-nphamcs@gmail.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] mm: zswap: corrupted swap accounting and shadow on vswap writeback failure
--

commit 790470c2c322c0c4b7b975b139e54f69bf472f15
Author: Nhat Pham <nphamcs@gmail.com>

mm, swap: write back vswap zswap entries to physical swap

This commit adds support for writing back zswap-backed vswap entries to
physical swap by allocating physical swap slots on demand during writeback.
It also updates the zswap shrinker to only skip vswap entries when no
physical swap space is available.

> diff --git a/mm/zswap.c b/mm/zswap.c
> index 1b91dba992aba..fd0c2f126b570 100644
> --- a/mm/zswap.c
> +++ b/mm/zswap.c
> @@ -1076,12 +1076,13 @@ static bool zswap_decompress(struct zswap_entry *entry, struct folio *folio)
>  static int zswap_writeback_entry(struct zswap_entry *entry,
>  				 swp_entry_t swpentry)
>  {
> -	struct xarray *tree;
>  	pgoff_t offset = swp_offset(swpentry);
>  	struct folio *folio;
>  	struct mempolicy *mpol;
>  	struct swap_info_struct *si;
>  	struct swap_io_ctx ctx = {};
> +	swp_entry_t phys = {};
> +	bool is_vswap;
>  	int ret = 0;
>  
>  	/* try to allocate swap cache folio */
> @@ -1089,12 +1090,7 @@ static int zswap_writeback_entry(struct zswap_entry *entry,
>  	if (IS_ERR_OR_NULL(si))
>  		return -ENOENT;
>  
> -	/* Vswap entries have no physical backing to write to. */
> -	if (swap_is_vswap(si)) {
> -		put_swap_device(si);
> -		return -EINVAL;
> -	}
> -
> +	is_vswap = swap_is_vswap(si);
>  	mpol = get_task_policy(current);
>  	folio = __swap_cache_alloc_folio(swpentry, GFP_KERNEL, BIT(0), NULL, mpol,
>  					 NO_INTERLEAVE_INDEX);
> @@ -1115,24 +1111,44 @@ static int zswap_writeback_entry(struct zswap_entry *entry,
>  	/*
>  	 * folio is locked, and the swapcache is now secured against
>  	 * concurrent swapping to and from the slot, and concurrent
> -	 * swapoff so we can safely dereference the zswap tree here.
> +	 * swapoff so we can safely dereference the zswap tree (or vswap
> +	 * vtable) here.
>  	 * Verify that the swap entry hasn't been invalidated and recycled
>  	 * behind our backs, to avoid overwriting a new swap folio with
>  	 * old compressed data. Only when this is successful can the entry
>  	 * be dereferenced.
>  	 */
> -	tree = swap_zswap_tree(swpentry);
> -	if (entry != xa_load(tree, offset)) {
> +	if (entry != zswap_entry_load(swpentry)) {
>  		ret = -ENOMEM;
>  		goto err;
>  	}
>  
> +	if (is_vswap) {
> +		/*
> +		 * Allocate physical backing before decompress so a failure
> +		 * wastes no work.
> +		 */
> +		phys = folio_realloc_swap(folio);
> +		if (!phys.val) {
> +			ret = -ENOMEM;
> +			goto err;
> +		}
> +	}

[Severity: Medium]
What happens to the swap_table shadow and cgroup v1 swap accounting when
folio_realloc_swap() fails here and jumps to err?

Earlier in zswap_writeback_entry(), __swap_cache_alloc_folio() calls
__swap_cache_alloc(), which consumes the existing workingset shadow and
memcg_id from the cluster, replaces the swap_table slot with the folio, and
runs memcg1_swapin() and workingset_refault():

mm/swap_state.c:__swap_cache_alloc() {
	...
	ci = swap_cluster_lock(si, offset);
	if (ci)
		err = __swap_cache_add_check(ci, targ_entry, nr_pages, &shadow, &memcg_id);
	...
	__swap_cache_do_add_folio(ci, folio, entry);
	swap_cluster_unlock(ci);
	...
	/* memsw uncharges swap when folio is added to swap cache */
	memcg1_swapin(folio);
	if (shadow)
		workingset_refault(folio, shadow);
	...
}

Under cgroup v1 (do_memsw_account()), memcg1_swapin() clears the slot's
memcg_table entry, uncharges memcg->memsw, and decrements MEMCG_SWAP and
MEMCG_VSWAP.

When folio_realloc_swap() returns !phys.val (for example, if physical swap
space or cgroup swap margin runs out mid-shrink), the error path in
zswap_writeback_entry() cleans up via swap_cache_del_folio() and folio_put():

err:
	swap_cache_del_folio(folio);
	folio_unlock(folio);
	folio_put(folio);

Because swap_cache_del_folio() calls __swap_cache_del_folio(ci, folio, entry,
NULL, false):

1. Passing NULL for shadow overwrites the swap_table slot with an empty
   shadow, losing the workingset eviction shadow for the entry that remains
   swapped out in zswap.
2. Passing false for swapout skips __memcg1_swapout(folio, ci), so when
   folio_put() frees the folio, __mem_cgroup_uncharge() uncharges
   memcg->memsw a second time while leaving ci->memcg_table cleared to 0
   and MEMCG_SWAP / MEMCG_VSWAP decremented for the still-live swap entry.
   A subsequent writeback attempt on that entry will see memcg_id == 0 and
   mm == NULL in mem_cgroup_swapin_charge_folio().

In addition, zswap_writeback_entry() returns -ENOMEM when !phys.val, which
shrink_memcg_cb() treats as LRU_RETRY:

mm/zswap.c:shrink_memcg_cb() {
	...
	writeback_result = zswap_writeback_entry(entry, swpentry);

	if (writeback_result) {
		zswap_reject_reclaim_fail++;
		ret = LRU_RETRY;
	...
}

If physical swap fills up during a shrink pass, won't the shrinker continue
scanning the rest of its budget (SWAP_CLUSTER_MAX per node in shrink_memcg()
or sc->nr_to_scan in zswap_shrinker_scan()), clearing entry->referenced on
referenced entries and repeating the __swap_cache_alloc_folio() and
swap_cache_del_folio() cycle on every unreferenced vswap entry?

[ ... ]

>
> -- 
> 2.51.0

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261021060323.553433-1-nphamcs@gmail.com?part=6


  reply	other threads:[~2026-10-22  6:19 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-21  6:03 [PATCH v6 00/12] Virtual Swap Space (Swap Table Edition) Nhat Pham
2026-10-21  6:03 ` [PATCH v6 01/12] mm, swap: add virtual swap device infrastructure Nhat Pham
2026-10-21  6:03 ` [PATCH v6 02/12] mm, swap: support zswap and zero-filled swap pages as vswap backends Nhat Pham
2026-10-21  6:03 ` [PATCH v6 03/12] mm, swap: prepare the swap IO path for vswap Nhat Pham
2026-10-21  6:03 ` [PATCH v6 04/12] mm, swap: support physical swap as a vswap backend Nhat Pham
2026-10-22  6:19   ` sashiko-bot
2026-10-23 22:30     ` Nhat Pham
2026-10-25 12:37   ` kernel test robot
2026-10-25 13:28   ` kernel test robot
2026-10-27 17:16     ` Nhat Pham
2026-10-21  6:03 ` [PATCH v6 05/12] mm, swap: enable THP swapin for vswap entries Nhat Pham
2026-10-22  6:19   ` sashiko-bot
2026-10-21  6:03 ` [PATCH v6 06/12] mm, swap: write back vswap zswap entries to physical swap Nhat Pham
2026-10-22  6:19   ` sashiko-bot [this message]
2026-10-21  6:03 ` [PATCH v6 07/12] mm, swap: reclaim physical slots backing cache-only vswap entries Nhat Pham
2026-10-22  6:19   ` sashiko-bot
2026-10-21  6:03 ` [PATCH v6 08/12] mm, swap: only charge physical swap entries Nhat Pham
2026-10-22  6:19   ` sashiko-bot
2026-10-21  6:03 ` [PATCH v6 09/12] mm, swap: add debugfs counters for vswap Nhat Pham
2026-10-21  6:18 ` [PATCH v6 10/12] mm, swap: defer memcg_table allocation for physical swap clusters Nhat Pham
2026-10-22  6:19   ` sashiko-bot
2026-10-21  6:18 ` [PATCH v6 11/12] mm, swap: add vmstat and memcg counters for vswap Nhat Pham
2026-10-21  6:18 ` [RFC PATCH v6 12/12] mm, swap: back vswap clusters with a VM_SPARSE array Nhat Pham
2026-10-22  6:19   ` sashiko-bot
2026-10-22  2:36 ` [PATCH v6 00/12] Virtual Swap Space (Swap Table Edition) Gregory Price (Meta)
2026-10-22 17:03   ` Nhat Pham

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=sashiko-outbox-181080@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=axelrasmussen@google.com \
    --cc=baohua@kernel.org \
    --cc=baolin.wang@linux.alibaba.com \
    --cc=baoquan.he@linux.dev \
    --cc=chengming.zhou@linux.dev \
    --cc=chrisl@kernel.org \
    --cc=corbet@lwn.net \
    --cc=david@kernel.org \
    --cc=gourry@gourry.net \
    --cc=hannes@cmpxchg.org \
    --cc=haowenchao22@gmail.com \
    --cc=hughd@google.com \
    --cc=kasong@tencent.com \
    --cc=kernel-team@meta.com \
    --cc=kunwu.chan@linux.dev \
    --cc=liam@infradead.org \
    --cc=linux-mm@kvack.org \
    --cc=ljs@kernel.org \
    --cc=mhocko@kernel.org \
    --cc=mkoutny@suse.com \
    --cc=muchun.song@linux.dev \
    --cc=nphamcs@gmail.com \
    --cc=qi.zheng@linux.dev \
    --cc=rdunlap@infradead.org \
    --cc=riel@surriel.com \
    --cc=roman.gushchin@linux.dev \
    --cc=rppt@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=shakeel.butt@linux.dev \
    --cc=shikemeng@huaweicloud.com \
    --cc=skhan@linuxfoundation.org \
    --cc=surenb@google.com \
    --cc=tj@kernel.org \
    --cc=vbabka@kernel.org \
    --cc=weixugc@google.com \
    --cc=yosry@kernel.org \
    --cc=youngjun.park@lge.com \
    --cc=yuanchu@google.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.