Re: [RFC PATCH v5 2/4] mm: distinguish large folio swap allocation failures

From: Yosry Ahmed

Date: Fri Aug 07 2026 - 16:12:59 EST


On Fri, Aug 07, 2026 at 04:29:17PM +0800, Kairui Song wrote:
> On Thu, Jul 30, 2026 at 08:23:02PM +0800, Xueyuan Chen wrote:
> > folio_alloc_swap() reports most allocation failures with a generic
> > negative error code. Reclaim cannot tell whether splitting a large folio
> > could make progress or whether there is no backing space at all.
> >
> > Keep the global free swap count and the remaining hierarchical memcg swap
> > margin as separate inputs. The memcg charge path reports only its own
> > margin; folio_alloc_swap() combines the two layers when classifying an
> > allocation failure.
> >
> > Return -E2BIG for large folios when a smaller allocation might still fit,
> > -ENOSPC when no global swap space is available, and -ENOMEM when the
> > failure is not helped by splitting.
> >
> > For early large-folio rejections, check global and memcg swap availability
> > instead of returning -E2BIG unconditionally. On a memcg charge failure,
> > swap slot allocation has already succeeded, so use the remaining memcg
> > margin to decide whether a smaller charge might fit.
> >
> > This only refines folio_alloc_swap() return codes. The reclaim callers are
> > updated separately.
> >
> > Suggested-by: Barry Song <baohua@xxxxxxxxxx>
> > Suggested-by: Youngjun Park <youngjun.park@xxxxxxx>
> > Signed-off-by: Xueyuan Chen <xueyuan.chen21@xxxxxxxxx>
> > ---
> > include/linux/swap.h | 16 ++++++++++++----
> > mm/memcontrol.c | 32 +++++++++++++++++++++++++++++++-
> > mm/swapfile.c | 32 ++++++++++++++++++++++++--------
> > 3 files changed, 67 insertions(+), 13 deletions(-)
> >
>
> Hello Xueyuan,
>
> Thanks for the patch!
>
> > diff --git a/include/linux/swap.h b/include/linux/swap.h
> > index 0544b2ec4c56..7d12058174ae 100644
> > --- a/include/linux/swap.h
> > +++ b/include/linux/swap.h
> > @@ -509,12 +509,13 @@ static inline void folio_throttle_swaprate(struct folio *folio, gfp_t gfp)
> > #endif
> >
> > #if defined(CONFIG_MEMCG) && defined(CONFIG_SWAP)
> > -int __mem_cgroup_try_charge_swap(struct folio *folio);
> > -static inline int mem_cgroup_try_charge_swap(struct folio *folio)
> > +int __mem_cgroup_try_charge_swap(struct folio *folio, long *swap_margin);
> > +static inline int mem_cgroup_try_charge_swap(struct folio *folio,
> > + long *swap_margin)
>
> Am I the only one that feel this returning argument is a bit ugly? See below..

No :)