Re: [PATCH v5 1/6] mm/zswap: Fix global shrinker when memory cgroup is disabled

From: Yosry Ahmed

Date: Tue Jun 30 2026 - 12:09:13 EST


> How about something like this? If there are no objections, I'll fold
> this into the next version.
>
> mm/zswap: Fix global shrinker when memory cgroup is disabled
>
> When memory cgroup is disabled, mem_cgroup_iter() always returns NULL.
> Therefore, the global shrinker shrink_worker() always takes the !memcg
> branch. After MAX_RECLAIM_RETRIES empty walks, the worker simply
> gives up,
> so it fails to write back anything.
>
> Therefore, when memory cgroup is disabled, fall through with the !memcg
> branch and shrink the root memcg directly.
>
> With memcg disabled, shrink_memcg() only returns -ENOENT when the root
> LRU is empty, which means the total pages are already below thr.
> The loop
> then safely bails out via the zswap_total_pages() <= thr check. For any
> other return value from shrink_memcg(), the loop is guaranteed to
> terminate,
> either after MAX_RECLAIM_RETRIES failures or once the threshold is met.
>
> Fixes: a65b0e7607cc ("zswap: make shrinking memcg-aware")
> Cc: stable@xxxxxxxxxxxxxxx
> Reported-by: Yosry Ahmed <yosry@xxxxxxxxxx>
> Closes:
> https://lore.kernel.org/all/CAO9r8zPVzMKFbCixxD-qgtRrkFxWVrHiZZeLc=eyTPKPVQgX4g@xxxxxxxxxxxxxx
> Signed-off-by: Hao Jia <jiahao1@xxxxxxxxxxx>

Feel free to add:

Acked-by: Yosry Ahmed <yosry@xxxxxxxxxx>

A small nit below.

>
> diff --git a/mm/zswap.c b/mm/zswap.c
> index 4b5149173b0e..9d4f19fc440e 100644
> --- a/mm/zswap.c
> +++ b/mm/zswap.c
> @@ -1361,11 +1361,12 @@ static void shrink_worker(struct work_struct *w)
> } while (memcg && !mem_cgroup_tryget_online(memcg));
> spin_unlock(&zswap_shrink_lock);
>
> - if (!memcg) {
> - /*
> - * Continue shrinking without incrementing
> failures if
> - * we found candidate memcgs in the last tree walk.
> - */
> + /*
> + * A NULL memcg ends a full hierarchy pass (except when
> memcg is
> + * disabled, where it is always NULL: fall through to
> the root LRU).
> + * Count a failure only if the pass found no candidates.

I think "last pass" is clearer than just "pass" here?

> + */
> + if (!memcg && !mem_cgroup_disabled()) {
> if (!attempts && ++failures == MAX_RECLAIM_RETRIES)
> break;
>
> Thanks,
> Hao