Re: [PATCH] mm/zswap: flush dcache in the compressed decompression path
From: Yosry Ahmed
Date: Fri Jul 10 2026 - 14:23:36 EST
On Fri, Jul 10, 2026 at 1:28 AM Song Hu <husong@xxxxxxxxxx> wrote:
>
> Both branches of zswap_decompress() write the destination folio through a
> kernel mapping: the incompressible branch via kmap_local_folio() and the
> compressed branch via the crypto scatterwalk. Yet only the incompressible
> branch calls flush_dcache_folio(); the compressed branch was missed. On
> aliasing D-cache architectures this can leave stale cache lines visible to
> userland after a zswap load.
Adding Herbert here.
Doesn't the Crypto API take care of this for the decompression path?
Maybe in scomp_acomp_comp_decomp()?
>
> zram flushes in the same situation (zram_bio_read()). Hoist a single
> flush_dcache_folio() out of the incompressible branch so both paths are
> covered.
>
> Fixes: e2c3b6b21c77 ("mm: zswap: use SG list decompression APIs from zsmalloc")
> Signed-off-by: Song Hu <husong@xxxxxxxxxx>
> ---
> mm/zswap.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/mm/zswap.c b/mm/zswap.c
> index b5a17ea20237..bb0c16d102d5 100644
> --- a/mm/zswap.c
> +++ b/mm/zswap.c
> @@ -943,7 +943,6 @@ static bool zswap_decompress(struct zswap_entry *entry, struct folio *folio)
> memcpy_from_sglist(dst, input, 0, PAGE_SIZE);
> dlen = PAGE_SIZE;
> kunmap_local(dst);
> - flush_dcache_folio(folio);
> } else {
> sg_init_table(&output, 1);
> sg_set_folio(&output, folio, PAGE_SIZE, 0);
> @@ -954,6 +953,9 @@ static bool zswap_decompress(struct zswap_entry *entry, struct folio *folio)
> dlen = acomp_ctx->req->dlen;
> }
>
> + /* Both branches write the folio through a kernel alias. */
> + flush_dcache_folio(folio);
> +
> zs_obj_read_sg_end(pool->zs_pool, entry->handle);
> mutex_unlock(&acomp_ctx->mutex);
>
> --
> 2.43.0
>