Re: [PATCH RFC v3 3/3] mm/zswap: reference the pool by index to shrink struct zswap_entry

From: Jianyue Wu

Date: Wed Aug 26 2026 - 12:10:54 EST


On Wed, Aug 26, 2026 at 1:17 AM Yosry Ahmed <yosry@xxxxxxxxxx> wrote:
>
> On Fri, Aug 14, 2026 at 11:54 PM Jianyue Wu <wujianyue000@xxxxxxxxx> wrote:
> >
> > struct zswap_entry is allocated once per stored page, so any reduction in
> > its size is multiplied across every entry zswap holds. It currently
> > embeds an 8-byte pool pointer, even though the live pools now sit in a
> > small fixed array indexed by a u8 slot number.
> >
> > Replace the per-entry pool pointer with that u8 slot index and resolve it
> > through a small helper that indexes the pools array. The entry holds a
> > reference to its pool, which keeps the pool alive and its slot occupied,
> > so the lookup is safe without any lock or RCU read-side section.
> >
> > The u8 fits in the padding after the bool referenced field, shrinking the
> > entry from 56 to 48 bytes on x86_64. This raises objs_per_slab from 73
> > to 85 and saves about 2MiB of metadata per 1GiB of data held in zswap.
> >
> > Suggested-by: Chris Li <chrisl@xxxxxxxxxx>
> > Signed-off-by: Jianyue Wu <wujianyue000@xxxxxxxxx>
> > ---
> > mm/zswap.c | 33 ++++++++++++++++++++++++++-------
> > 1 file changed, 26 insertions(+), 7 deletions(-)
> >
> > diff --git a/mm/zswap.c b/mm/zswap.c
> > index 603fdc418041..3974fca40a4a 100644
> > --- a/mm/zswap.c
> > +++ b/mm/zswap.c
> > @@ -213,7 +213,7 @@ static struct shrinker *zswap_shrinker;
> > * writeback logic. The entry is only reclaimed by the writeback
> > * logic if referenced is unset. See comments in the shrinker
> > * section for context.
> > - * pool - the zswap_pool the entry's data is in
> > + * pool_idx - slot of the zswap_pool that the entry's data is in.
> > * handle - zsmalloc allocation handle that stores the compressed page data
> > * objcg - the obj_cgroup that the compressed memory is charged to
> > * lru - handle to the pool's lru used to evict pages.
> > @@ -222,12 +222,24 @@ struct zswap_entry {
> > swp_entry_t swpentry;
> > unsigned int length;
> > bool referenced;
> > - struct zswap_pool *pool;
> > + u8 pool_idx;
> > unsigned long handle;
> > struct obj_cgroup *objcg;
> > struct list_head lru;
> > };
> >
> > +static struct zswap_pool *zswap_entry_pool(struct zswap_entry *entry)
> > +{
> > + /*
> > + * The entry holds a reference to its pool, so the slot cannot be
> > + * cleared or reused while the entry is alive: the read is stable
> > + * without the pools lock or an RCU read-side section. Non-zero
> > + * pool_idx (slot 0 is unused) also marks a live entry for lockdep.
> > + */
> > + return rcu_dereference_protected(zswap_pools[entry->pool_idx],
> > + entry->pool_idx != 0);
>
> Please align the second parameter with the first as long as it doesn't
> exceed 100 chars.

Sure, I will fix the alignment in the next version.

Best regards,
Jianyue