Re: [PATCH v10 0/6] mm/swap, memcg: Introduce swap tiers for cgroup based swap control
From: Yosry Ahmed
Date: Wed Jul 15 2026 - 12:29:02 EST
On Tue, Jul 14, 2026 at 10:45 PM Youngjun Park <youngjun.park@xxxxxxx> wrote:
>
> On Tue, Jul 14, 2026 at 01:44:28PM -0700, Shakeel Butt wrote:
> > Hi Youngjun,
> >
> > Thanks for keep pushing this effort.
>
> Hi Shakeel
> Huge thanks again for suggestion.
>
> > > Right, that's the plan.
> > >
> > > > but I would check all
> > > > user-visible behaviors related to zswap (e.g. interaction with other
> > > > zswap interfaces) to make sure nothing breaks or changes in a
> > > > meaningful way when zswap is introduced as a tier later.
>
> At now, the answer is there are nothing breaks or changes as a first review.
> I think it'll be better to introduce zswap tier after this patch.
> (Details are going on the below)
>
> > > Fair point. Let me review this more and get back to you!
> >
> > Please do report back what you find.
> >
> > Yosry, what is needed to enable zswap as a swap tier? What will be the minimum
> > requirements for that? If that is not too much, we can make that part of this
> > series.
> >
> > Shakeel
>
> I tried to verify what changes once the zswap tier is introduced.
> Please correct me if I'm wrong!
>
> First observation: before the zswap tier is introduced, some of this
> is already possible today:
>
> - a "zswap-only" tier equivalent on cgroup: memory.zswap.writeback = 0
> - disabling zswap entirely on cgroup: memory.zswap.max = 0
> - disabling swap (and zswap) entirely on cgroup: memory.swap.max = 0
>
> Given that, my take is that introducing the tier concept itself
> doesn't change any user-visible zswap behavior, since on/off control
> for the zswap tier is basically already possible today through other
> knobs. So this isn't really a user-facing problem; it's more
> something we need to think through carefully in the patch that
> introduces the tier concept itself. That's what the points below are
> about.
>
> The cgroup interface knobs and the zswap-global knobs need a
> different kind of review, so let's start with the global ones. The
> zswap-global knobs (compressor, max_pool_percent,
> accept_threshold_percent, shrinker_enabled) look fine with tiers.
> They're zswap-internal tuning, orthogonal to the tier concept, so
> tiers shouldn't change their behavior. The remaining one, "enabled",
> does overlap in spirit with the tier on/off knob: enabled = false is
> basically the same as disabling zswap for every cgroup. But like the
> other overlaps below, this doesn't look like a real problem.
Agreed, I don't think there's a problem there.
>
> The part that needs more thought is the overlap between
> memory.zswap.max / memory.zswap.writeback, memory.swap.max, and the
> new tier on/off knob. Since all of the above is already possible
> today, adding a tier on top means we should make sure it doesn't
> create confusing overlap.
>
> 1) memory.swap.max vs. tier on/off
>
> memory.swap.max = 0 disables swap (and zswap) entirely, and
> memory.swap.max = max leaves everything enabled, so one knob can
> make the other a no-op. I don't think this is confusing in
> practice; they're just two independent ways to reach the same end
> state.
>
> Conceptually, the tier knob controls on/off/auto-scale, while
> memory.swap.max controls pure quantity, so they cover different
> concerns and can coexist. Even if the tier knob later takes a
> numeric value, that number would apply per tier, while swap.max is
> a total budget that doesn't care how the tiers split it up, so
> they still shouldn't step on each other.
The memory.swap.max interaction with tier on/off would be the same as
memory.max with memory tiers AFAICT. We just need to make sure we
remain consistent.
> 2) memory.zswap.max vs. zswap tier on/off
>
> memory.zswap.max = 0 looks semantically equivalent to turning the
> zswap tier off. Could memory.zswap.max simply be folded into
> memory.<zswap_tier_name>.max?
>
> Yosry pointed out:
>
> > > memory.zswap.max integrates naturally (it's
> > > memory.<tier_name>.max).
> > Not really. memory.zswap.max is in terms of memory usage
> > (compressed size), not swap usage (uncompressed size).
>
> I'm not sure where the tier limit would actually apply here: is it
> checked in zswap_store() against the pre-compression size, while
> memory.zswap.max keeps tracking the compressed size?
As the tier limit can only be 0 or max for now, I don't think this is
a problem. zswap_store() would just check that the tier is not
disabled.
> If so, once you give the tier limit a number, wouldn't its usage end up
> meaning basically the same thing as memory.zswap.max?
If we allow values other than 0/max, I think for zswap that would be
the limit on the uncompressed size to remain consistent with other
swap tiers. So it would be different from memory.zswap.max.
> For limit = 0 the two already look identical to me (both just block zswap
> usage). I'd like to understand what benefit a non-zero tier limit
> (uncompressed) gives us over the existing memory.zswap.max
> (compressed), once tiers exist. Let me know if I'm missing
> something here.
Yeah limit=0 and limit=max would behave similarly for both. If we do
support other limits, the meaning would be different. Since most usage
of zswap.max is either setting it to 0/max, we can check if we can
deprecate that interface once we add zswap as a tier.
> Also note the mixed states this creates:
>
> - memory.zswap.max has room, but the tier is off, so zswap can't
> be used.
> - memory.zswap.max = 0, but the tier is on, so zswap still can't
> be used.
>
> Both knobs can independently block zswap usage, which seems worth
> flagging even if it's not harmful by itself.
>
> On top of that, the tier knob is likely to stay on/off/auto-scale
> without a numeric limit, while memory.zswap.max only handles the
> numeric side, so the two should coexist as is. If the tier ever
> gains its own numeric limit, we'd need to revisit unifying it with
> memory.zswap.max.
>
> 3) memory.zswap.writeback vs. a "zswap-only" tier
>
> memory.zswap.writeback = 0 can act like a zswap-only tier today,
> because zswap still borrows a slot from the real swap device to
> store data; writeback = 0 just skips writing that data out to the
> device . A tier restriction works differently: it applies at
> allocation time, so a zswap-only tier would block allocating any
> slot from another device. Since zswap currently depends on that
> very slot to store anything, this would break zswap instead of
> giving us a working zswap-only mode, so the tier restriction can't
> substitute for memory.zswap.writeback here.
Yes, the semantics of zswap.writeback would be different than using
zswap as the only tier, but we shouldn't allow zswap as the only tier
anyway as I mentioned.
> With vswap, this changes: tier off and writeback = 0 converge to
> the same effect(right now the pure zswap only tier),
Yes.
> since zswap no longer needs to borrow a slot from
> another device. Even so, memory.zswap.writeback still needs to
> stay, since vswap itself can be disabled at compile time or
> runtime, and we'd still need a way to express zswap-only behavior
> without it. I'd like to unify the two eventually, but for now they
> have to stay separate. I'll keep thinking about it.
The goal is to eventually make zswap depend on vswap. Once we have
that, we can deprecate zswap.writeback in favor of the tiering
interface.
>
> How do you think?
>
> thanks
> Youngjun