Re: [PATCH v2 3/3] mm: zswap: drop cold writeback folios via swap dropbehind
From: Alexandre Ghiti
Date: Tue Jul 28 2026 - 09:08:57 EST
Hi Yosry,
On Mon, Jul 27, 2026 at 7:05 PM Yosry Ahmed <yosry@xxxxxxxxxx> wrote:
>
> >
> 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?
That's an optimization rather than a real need: since we know we are
in a sleepable context, we can safely drop the folio from the swap
cache here. And since we don't mark the sync folios as dropbehind,
they never enter the list handled by the dropbehind workqueue.
But maybe that's not worth it? I don't even have numbers to back the
optimization claim, so I can drop this in v3.
Thanks,
Alex
>
> >
> > 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
> >
>