memcg-dont-call-schedule_work-when-no-spinning-is-allowed.patch removed from -mm tree
The quilt patch titled
Subject: memcg: don't call schedule_work when no spinning is allowed
has been removed from the -mm tree. Its filename was
memcg-dont-call-schedule_work-when-no-spinning-is-allowed.patch
This patch was dropped because it was merged into the mm-stable branch of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
------------------------------------------------------
From: David Stevens <[email protected]>
Subject: memcg: don't call schedule_work when no spinning is allowed
Date: Fri, 4 Sep 2026 10:31:45 -0700
Memcg charging can be done from any context, but calling schedule_work() isn't safe from an NMI. If memory.high is breached from a context where spinning isn't allowed, use irq_work to schedule the reclaim work.
Found this via code inspection. I spent a little bit trying to trigger it for real, but the only way I managed was by writing a hacky driver absuing alloc_pages_nolock().
---
include/linux/memcontrol.h | 2 ++ mm/memcontrol.c | 13 ++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-)
include/linux/memcontrol.h renamed from include/linux/memcontrol.h~memcg-dont-call-schedule_work-when-no-spinning-is-allowed +2 -0
@@ -23,6 +23,7 @@#include <linux/writeback.h> #include <linux/page-flags.h> #include <linux/shrinker.h> +#include <linux/irq_work_types.h> struct mem_cgroup ;struct obj_cgroup ;
@@ -233,6 +234,7 @@ struct mem_cgroup {#endif /* Range enforcement for interrupt charges */ +struct irq_work high_irq_work;struct work_struct high_work;__cacheline_group_end_aligned (memcg_write_hot);
mm/memcontrol.c renamed from mm/memcontrol.c~memcg-dont-call-schedule_work-when-no-spinning-is-allowed +12 -1
@@ -62,6 +62,7 @@#include <linux/seq_buf.h> #include <linux/sched/isolation.h> #include <linux/kmemleak.h> +#include <linux/irq_work.h> #include "internal.h" #include "swap.h" #include "swap_table.h"
@@ -2424,6 +2425,11 @@ static void high_work_func(struct work_sreclaim_high (memcg,MEMCG_CHARGE_BATCH ,GFP_KERNEL ); } +static void high_irq_work_func (struct irq_work *work) +{ + schedule_work(&container_of(work, struct mem_cgroup, high_irq_work)->high_work); +} +/* * Clamp the maximum sleep time per allocation batch to 2 seconds. This is * enough to still cause a significant slowdown in most cases, while still
@@ -2832,7 +2838,10 @@ done_restock:/* Don't bother a random interrupted task */ if (!in_task ()) {if (mem_high) { -schedule_work (&memcg->high_work); +if (allow_spinning) +schedule_work (&memcg->high_work); +else +irq_work_queue (&memcg->high_irq_work);break ; }continue ;
@@ -4207,6 +4216,7 @@ static struct mem_cgroup *mem_cgroup_all goto fail;INIT_WORK (&memcg->high_work, high_work_func); +init_irq_work (&memcg->high_irq_work, high_irq_work_func);vmpressure_init (&memcg->vmpressure);INIT_LIST_HEAD (&memcg->memory_peaks);INIT_LIST_HEAD (&memcg->swap_peaks);
@@ -4415,6 +4425,7 @@ static void mem_cgroup_css_free(struct cstatic_branch_dec (&memcg_bpf_enabled_key);vmpressure_cleanup (&memcg->vmpressure); +irq_work_sync (&memcg->high_irq_work);cancel_work_sync (&memcg->high_work);free_shrinker_info (memcg);mem_cgroup_free (memcg);
_
Patches currently in -mm which might be from [email protected] are