Re: [PATCH v2 3/3] mm: zswap: drop cold writeback folios via swap dropbehind
From: Yosry Ahmed
Date: Mon Jul 27 2026 - 13:12:21 EST
On Mon, Jul 27, 2026 at 7:39 AM Alexandre Ghiti <alex@xxxxxxxx> wrote:
>
> zswap writeback decompresses an entry into a fresh swap cache folio and
> writes it back. The folio is cold by construction, yet it is left on the
> LRU for reclaim to find and free later, wasting a reclaim scan and keeping
> cold memory resident longer than necessary.
>
> Allocate the folio off the LRU and drop it as soon as writeback completes:
> mark it PG_dropbehind so the swap dropbehind path frees it once writeback
> ends. Synchronous-IO devices complete writeback in this context, so there
> the folio is dropped inline instead.
Why does this need to be handled in zswap? Doesn't writeback from sync
devices still call folio_end_writeaback() and do the dropbehind
handling?
>
> Suggested-by: Johannes Weiner <hannes@xxxxxxxxxxx>
> Suggested-by: Nhat Pham <nphamcs@xxxxxxxxx>
> Signed-off-by: Alexandre Ghiti <alex@xxxxxxxx>
> ---
> mm/zswap.c | 13 ++++++++++---
> 1 file changed, 10 insertions(+), 3 deletions(-)
>
> diff --git a/mm/zswap.c b/mm/zswap.c
> index 8163e6c5f76c..e37828e02938 100644
> --- a/mm/zswap.c
> +++ b/mm/zswap.c
> @@ -992,6 +992,7 @@ static int zswap_writeback_entry(struct zswap_entry *entry,
> struct folio *folio;
> struct mempolicy *mpol;
> struct swap_info_struct *si;
> + bool sync;
> int ret = 0;
>
> /* try to allocate swap cache folio */
> @@ -999,6 +1000,8 @@ static int zswap_writeback_entry(struct zswap_entry *entry,
> if (!si)
> return -EEXIST;
>
> + sync = data_race(si->flags & SWP_SYNCHRONOUS_IO);
> +
> mpol = get_task_policy(current);
> folio = __swap_cache_alloc_folio(swpentry, GFP_KERNEL, BIT(0), NULL, mpol,
> NO_INTERLEAVE_INDEX);
> @@ -1013,7 +1016,6 @@ static int zswap_writeback_entry(struct zswap_entry *entry,
> */
> if (IS_ERR(folio))
> return PTR_ERR(folio);
> - folio_add_lru(folio);
>
> /*
> * folio is locked, and the swapcache is now secured against
> @@ -1046,12 +1048,17 @@ static int zswap_writeback_entry(struct zswap_entry *entry,
> /* folio is up to date */
> folio_mark_uptodate(folio);
>
> - /* move it to the tail of the inactive list after end_writeback */
> - folio_set_reclaim(folio);
> + if (!sync)
> + folio_set_dropbehind(folio);
>
> /* start writeback */
> __swap_writepage(folio, NULL);
>
> + if (sync) {
> + swap_dropbehind_free_one_folio(folio);
> + return 0;
> + }
> +
> out:
> if (ret) {
> swap_cache_del_folio(folio);
> --
> 2.53.0-Meta
>