* FAILED: patch "[PATCH] mm: memcontrol: raise MEMCG_MAX for charges that fail without reclaiming" failed to apply to 6.6-stable tree
@ 2026-11-07 10:32 Sasha Levin
2026-11-10 17:30 ` [PATCH 6.6.y] mm: memcontrol: raise MEMCG_MAX for charges that fail without reclaiming Sasha Levin
0 siblings, 1 reply; 2+ messages in thread
From: Sasha Levin @ 2026-11-07 10:32 UTC (permalink / raw)
To: joe, akpm, shakeel.butt, hannes, mhocko, muchun.song,
roman.gushchin; +Cc: stable
The patch below does not apply to the 6.6-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.6.y
git checkout FETCH_HEAD
git cherry-pick -x 374f65b1481992eb6b9c6bffd53f3afa5c2e94cf
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '20261107053206-failed-6.6-374f65b14819@kernel.org' --subject-prefix 'PATCH 6.6.y' 'HEAD^..'
Thanks,
Sasha
------------------ original commit in Linus's tree ------------------
From 374f65b1481992eb6b9c6bffd53f3afa5c2e94cf Mon Sep 17 00:00:00 2001
From: Joe Damato <joe@dama.to>
Date: Mon, 31 Aug 2026 10:48:35 -0700
Subject: [PATCH] mm: memcontrol: raise MEMCG_MAX for charges that fail without
reclaiming
Charges that exceed memory.max and return through the nomem label can
raise no event and simply return -ENOMEM.
A non-blocking charge can hit the limit, get rejected, but is not visible
in memory.events.
This was noticed in a production setting where bpf_mem_alloc() attempted
to refill its per-cpu freelists, which triggered a non-blocking charge
while at the limit.
Commit d6e103a757fa ("mm: memcontrol: do not miss MEMCG_MAX events for
enforced allocations") added raised_max_event to cover charges that are
force charged without ever reaching reclaim, but charges that are rejected
outright were left out. Getting an allocation failure without the
corresponding MEMCG_MAX event is unexpected and makes debugging and
monitoring harder.
Raise the event on the way out for rejected charges as well, by routing
the -ENOMEM return through the same exit path that already covers forced
charges. The existing behavior of raising a MEMCG_MAX event on every
charge/reclaim/retry iteration is left unchanged.
Tested with a module that performs accounted GFP_NOWAIT page allocations
from a task in a cgroup at its memory.max, and measures the resulting
memory.events:max delta. Without this patch the rejected charges raise no
event at all; with it the delta matches the number of rejected charges
exactly. A GFP_KERNEL|__GFP_NORETRY control, which reaches reclaim,
raises the same two events per failed charge before and after, confirming
the existing charge/reclaim/retry accounting is unchanged.
Link: https://lore.kernel.org/20260831174836.3102406-1-joe@dama.to
Fixes: d6e103a757fa ("mm: memcontrol: do not miss MEMCG_MAX events for enforced allocations")
Signed-off-by: Joe Damato <joe@dama.to>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Suggested-by: Shakeel Butt <shakeel.butt@linux.dev>
Acked-by: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: <stable@vger.kernel.org>
---
mm/memcontrol.c | 28 ++++++++++++++++------------
1 file changed, 16 insertions(+), 12 deletions(-)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index d5ebe83eae3ef..aeaa09e01d70e 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2685,10 +2685,11 @@ static int try_charge_memcg(struct mem_cgroup *memcg, gfp_t gfp_mask,
bool raised_max_event = false;
unsigned long pflags;
bool allow_spinning = gfpflags_allow_spinning(gfp_mask);
+ int ret = 0;
retry:
if (consume_stock(memcg, nr_pages))
- return 0;
+ return ret;
if (!allow_spinning)
/* Avoid the refill and flush of the older stock */
@@ -2799,16 +2800,11 @@ static int try_charge_memcg(struct mem_cgroup *memcg, gfp_t gfp_mask,
* put the burden of reclaim on regular allocation requests
* and let these go through as privileged allocations.
*/
- if (!(gfp_mask & (__GFP_NOFAIL | __GFP_HIGH)))
- return -ENOMEM;
+ if (!(gfp_mask & (__GFP_NOFAIL | __GFP_HIGH))) {
+ ret = -ENOMEM;
+ goto out;
+ }
force:
- /*
- * If the allocation has to be enforced, don't forget to raise
- * a MEMCG_MAX event.
- */
- if (!raised_max_event)
- __memcg_memory_event(mem_over_limit, MEMCG_MAX, allow_spinning);
-
/*
* The allocation either can't fail or will lead to more memory
* being freed very soon. Allow memory usage go over the limit
@@ -2818,7 +2814,15 @@ static int try_charge_memcg(struct mem_cgroup *memcg, gfp_t gfp_mask,
if (do_memsw_account())
page_counter_charge(&memcg->memsw, nr_pages);
- return 0;
+out:
+ /*
+ * Don't forget to raise a MEMCG_MAX event for forced or rejected
+ * requests.
+ */
+ if (!raised_max_event)
+ __memcg_memory_event(mem_over_limit, MEMCG_MAX, allow_spinning);
+
+ return ret;
done_restock:
if (batch > nr_pages)
@@ -2877,7 +2881,7 @@ static int try_charge_memcg(struct mem_cgroup *memcg, gfp_t gfp_mask,
!(current->flags & PF_MEMALLOC) &&
gfpflags_allow_blocking(gfp_mask))
__mem_cgroup_handle_over_high(gfp_mask);
- return 0;
+ return ret;
}
static inline int try_charge(struct mem_cgroup *memcg, gfp_t gfp_mask,
--
2.53.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* [PATCH 6.6.y] mm: memcontrol: raise MEMCG_MAX for charges that fail without reclaiming
2026-11-07 10:32 FAILED: patch "[PATCH] mm: memcontrol: raise MEMCG_MAX for charges that fail without reclaiming" failed to apply to 6.6-stable tree Sasha Levin
@ 2026-11-10 17:30 ` Sasha Levin
0 siblings, 0 replies; 2+ messages in thread
From: Sasha Levin @ 2026-11-10 17:30 UTC (permalink / raw)
To: stable
Cc: Joe Damato, Andrew Morton, Shakeel Butt, Johannes Weiner,
Michal Hocko, Muchun Song, Roman Gushchin, Sasha Levin
From: Joe Damato <joe@dama.to>
[ Upstream commit 374f65b1481992eb6b9c6bffd53f3afa5c2e94cf ]
Charges that exceed memory.max and return through the nomem label can
raise no event and simply return -ENOMEM.
A non-blocking charge can hit the limit, get rejected, but is not visible
in memory.events.
This was noticed in a production setting where bpf_mem_alloc() attempted
to refill its per-cpu freelists, which triggered a non-blocking charge
while at the limit.
Commit d6e103a757fa ("mm: memcontrol: do not miss MEMCG_MAX events for
enforced allocations") added raised_max_event to cover charges that are
force charged without ever reaching reclaim, but charges that are rejected
outright were left out. Getting an allocation failure without the
corresponding MEMCG_MAX event is unexpected and makes debugging and
monitoring harder.
Raise the event on the way out for rejected charges as well, by routing
the -ENOMEM return through the same exit path that already covers forced
charges. The existing behavior of raising a MEMCG_MAX event on every
charge/reclaim/retry iteration is left unchanged.
Tested with a module that performs accounted GFP_NOWAIT page allocations
from a task in a cgroup at its memory.max, and measures the resulting
memory.events:max delta. Without this patch the rejected charges raise no
event at all; with it the delta matches the number of rejected charges
exactly. A GFP_KERNEL|__GFP_NORETRY control, which reaches reclaim,
raises the same two events per failed charge before and after, confirming
the existing charge/reclaim/retry accounting is unchanged.
Link: https://lore.kernel.org/20260831174836.3102406-1-joe@dama.to
Fixes: d6e103a757fa ("mm: memcontrol: do not miss MEMCG_MAX events for enforced allocations")
Signed-off-by: Joe Damato <joe@dama.to>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Suggested-by: Shakeel Butt <shakeel.butt@linux.dev>
Acked-by: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: <stable@vger.kernel.org>
[ sashal: Changed __memcg_memory_event(..., allow_spinning) to memcg_memory_event(...) to match the existing API. ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
mm/memcontrol.c | 28 ++++++++++++++++------------
1 file changed, 16 insertions(+), 12 deletions(-)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 852fa93efe1be..34920b31e456c 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2682,10 +2682,11 @@ static int try_charge_memcg(struct mem_cgroup *memcg, gfp_t gfp_mask,
bool drained = false;
bool raised_max_event = false;
unsigned long pflags;
+ int ret = 0;
retry:
if (consume_stock(memcg, nr_pages))
- return 0;
+ return ret;
if (!do_memsw_account() ||
page_counter_try_charge(&memcg->memsw, batch, &counter)) {
@@ -2797,16 +2798,11 @@ static int try_charge_memcg(struct mem_cgroup *memcg, gfp_t gfp_mask,
* put the burden of reclaim on regular allocation requests
* and let these go through as privileged allocations.
*/
- if (!(gfp_mask & (__GFP_NOFAIL | __GFP_HIGH)))
- return -ENOMEM;
+ if (!(gfp_mask & (__GFP_NOFAIL | __GFP_HIGH))) {
+ ret = -ENOMEM;
+ goto out;
+ }
force:
- /*
- * If the allocation has to be enforced, don't forget to raise
- * a MEMCG_MAX event.
- */
- if (!raised_max_event)
- memcg_memory_event(mem_over_limit, MEMCG_MAX);
-
/*
* The allocation either can't fail or will lead to more memory
* being freed very soon. Allow memory usage go over the limit
@@ -2816,7 +2812,15 @@ static int try_charge_memcg(struct mem_cgroup *memcg, gfp_t gfp_mask,
if (do_memsw_account())
page_counter_charge(&memcg->memsw, nr_pages);
- return 0;
+out:
+ /*
+ * Don't forget to raise a MEMCG_MAX event for forced or rejected
+ * requests.
+ */
+ if (!raised_max_event)
+ memcg_memory_event(mem_over_limit, MEMCG_MAX);
+
+ return ret;
done_restock:
if (batch > nr_pages)
@@ -2869,7 +2873,7 @@ static int try_charge_memcg(struct mem_cgroup *memcg, gfp_t gfp_mask,
gfpflags_allow_blocking(gfp_mask)) {
mem_cgroup_handle_over_high(gfp_mask);
}
- return 0;
+ return ret;
}
static inline int try_charge(struct mem_cgroup *memcg, gfp_t gfp_mask,
--
2.53.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-11-10 17:30 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-07 10:32 FAILED: patch "[PATCH] mm: memcontrol: raise MEMCG_MAX for charges that fail without reclaiming" failed to apply to 6.6-stable tree Sasha Levin
2026-11-10 17:30 ` [PATCH 6.6.y] mm: memcontrol: raise MEMCG_MAX for charges that fail without reclaiming Sasha Levin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.