* [PATCH RFC 0/4] memcg,slab: kmalloc_nolock() fixes
@ 2026-06-24 13:11 Harry Yoo (Oracle)
2026-06-24 13:11 ` [PATCH RFC 1/4] mm/memcontrol: do not drain objcg stock when spinning is not allowed Harry Yoo (Oracle)
` (4 more replies)
0 siblings, 5 replies; 9+ messages in thread
From: Harry Yoo (Oracle) @ 2026-06-24 13:11 UTC (permalink / raw)
To: Johannes Weiner, Michal Hocko, Roman Gushchin, Shakeel Butt,
Muchun Song, Andrew Morton, Vlastimil Babka, Hao Li,
Christoph Lameter, David Rientjes, Alexei Starovoitov,
Pedro Falcato
Cc: cgroups, linux-mm, linux-kernel, bpf
Apologies for posting another series during the merge window.
But these are bug fixes and there are other features that need to be
rebased on top, so...
Overview
========
This patchset tries to fix three kmalloc_nolock() bugs.
1. obj_cgroup_put() takes a spinlock in the release path
when it is holding the last reference.
(This needs some thoughts from the memcg folks)
2. A spinlock may be taken in the following path and may lead
to deadlock:
kmalloc_nolock()
-> slab_post_alloc_hook()
-> memcg_slab_post_alloc_hook()
-> memcg_alloc_abort_single().
3. irq_work_sync() is called without synchronization for rcuwait
(on PREEMPT_RT or some architectures), potentially causing a
hang.
Bug 1 was reported by lockdep, and bugs 2 [2] and 3 [3] were
reported by Sashiko.
To MEMCG folks: obj_cgroup_put() is not safe in unknown context
===============================================================
I tried to fix the bug 1 in the __refill_obj_stock() path in patch 1.
Patch 1 considers correctness aspect only, and performance may
degrade because we have to fall back to per-objcg atomics unless
some else drains it for us.
Ouch, while writing the cover letter, I realized that two paths need
some attention:
1. __memcg_slab_free_hook() -> obj_cgroup_put() and
2. current_obj_cgroup() -> current_objcg_update() -> obj_cgroup_put()
An easy solution would be to somehow defer obj_cgroup_put() or
obj_cgroup_release(). I would like to hear thoughts from the memcg folks
on which is the preferred way.
To BPF folks: do we need to backport kmalloc_nolock() support
for architectures without __CMPXCHG_DOUBLE to v6.18?
=============================================================
Originally I intended to fix this as part of this series.
However, the issue reported by Levi Zim [1] was on kernel v6.19,
(Thanks to Vlastimil for mentioning this), and v6.18 does not use
kmalloc_nolock() for BPF local storage.
There are still few users in v6.18, but I can't tell whether it is
necessary to backport it to v6.18 (hopefully not as urgent as other
bugfixes).
Thoughts?
[1] https://lore.kernel.org/linux-mm/9bea1536-534a-4a59-9b5f-92389fb05688@kxxt.dev
[2] https://sashiko.dev/#/patchset/20260610-slab_alloc_flags-v2-0-7190909db118%40kernel.org?part=9
[3] https://sashiko.dev/#/patchset/20260615-kfree_rcu_nolock-v3-0-70a54f3775bb%40kernel.org?part=5
Signed-off-by: Harry Yoo (Oracle) <harry@kernel.org>
---
Harry Yoo (Oracle) (4):
mm/memcontrol: do not drain objcg stock when spinning is not allowed
mm/slab: handle allow_spin in slab_free_hook() instead of open coding
mm/slab: fix a deadlock in memcg_alloc_abort_single()
mm/slab: serialize defer_free_barrier()
mm/memcontrol.c | 34 ++++++++-----
mm/slab.h | 3 +-
mm/slab_common.c | 5 +-
mm/slub.c | 148 +++++++++++++++++++++++++++++++------------------------
4 files changed, 111 insertions(+), 79 deletions(-)
---
base-commit: 892a7864730775c3dbee2a39e9ead4fa8d4256e7
change-id: 20260624-kmalloc-nolock-fixes-c97675328773
Best regards,
--
Harry Yoo (Oracle) <harry@kernel.org>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH RFC 1/4] mm/memcontrol: do not drain objcg stock when spinning is not allowed
2026-06-24 13:11 [PATCH RFC 0/4] memcg,slab: kmalloc_nolock() fixes Harry Yoo (Oracle)
@ 2026-06-24 13:11 ` Harry Yoo (Oracle)
2026-06-24 13:28 ` sashiko-bot
2026-06-24 13:11 ` [PATCH RFC 2/4] mm/slab: handle allow_spin in slab_free_hook() instead of open coding Harry Yoo (Oracle)
` (3 subsequent siblings)
4 siblings, 1 reply; 9+ messages in thread
From: Harry Yoo (Oracle) @ 2026-06-24 13:11 UTC (permalink / raw)
To: Johannes Weiner, Michal Hocko, Roman Gushchin, Shakeel Butt,
Muchun Song, Andrew Morton, Vlastimil Babka, Hao Li,
Christoph Lameter, David Rientjes, Alexei Starovoitov,
Pedro Falcato
Cc: cgroups, linux-mm, linux-kernel, bpf
When kmalloc_nolock() drains objcg stock, the stock might be holding
the last reference to the objcg. Since obj_cgroup_release() is a
callback for percpu refcount and does not know whether spinning is
allowed, it is not safe to invoke obj_cgroup_put().
This was caught by lockdep on PREEMPT_RT because acquiring
a sleeping lock (objcg_lock) violates lock nesting rules:
kernel: BUG: sleeping function called from invalid context at kernel/locking/spinlock_rt.c:48
kernel: in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 1267, name: systemd-resolve
preempt_count: 1, expected: 0
RCU nest depth: 3, expected: 3
6 locks held by systemd-resolve/1267:
#0: ffff888a8165fa20 ((&pcs->lock)){+.+.}-{3:3}, at: kmem_cache_alloc_noprof+0x185/0xa20
#1: ffffffff9658a4c0 (rcu_read_lock){....}-{1:3}, at: rt_spin_trylock+0x74/0x2a0
#2: ffff888a81648598 ((lock)#4){+.+.}-{3:3}, at: trylock_stock+0x118/0x380
#3: ffffffff9658a4c0 (rcu_read_lock){....}-{1:3}, at: rt_spin_trylock+0x74/0x2a0
#4: ffffffff9658a4c0 (rcu_read_lock){....}-{1:3}, at: percpu_ref_put_many.constprop.0+0x40/0x270
#5: ffffffff96af11d8 (objcg_lock){+.+.}-{3:3}, at: obj_cgroup_release+0x8a/0x410
[...]
Call Trace:
<TASK>
dump_stack_lvl+0x8a/0xe0
dump_stack+0x14/0x1c
__might_resched.cold+0x233/0x2bb
rt_spin_lock+0xd3/0x410
obj_cgroup_release+0x8a/0x410
percpu_ref_put_many.constprop.0+0x226/0x270
drain_obj_stock_slot+0x27e/0x8d0
__refill_obj_stock+0x409/0x6d0
__memcg_slab_post_alloc_hook+0xa45/0x1500
__kmalloc_nolock_noprof+0x988/0xc40
[...]
However, this is illegal in !RT kernels too because the objcg release
callback acquires a spinlock even when spinning is not allowed.
To fix this issue, fall back to atomics when the cached objcg doesn't
match, but it is unsafe to drain because spinning is not allowed.
This is expected to affect performance of kmalloc_nolock() since
it can no longer drain and refill the stock and falls back to a
per-objcg atomic counter (objcg->nr_charged_bytes).
Fixes: af92793e52c3 ("slab: Introduce kmalloc_nolock() and kfree_nolock().")
Cc: stable@vger.kernel.org
Signed-off-by: Harry Yoo (Oracle) <harry@kernel.org>
---
mm/memcontrol.c | 34 +++++++++++++++++++++++-----------
mm/slab.h | 3 ++-
mm/slub.c | 29 +++++++++++++++++++----------
3 files changed, 44 insertions(+), 22 deletions(-)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 29390ba13baa..5bb5e75ef5b0 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -3316,18 +3316,19 @@ static bool obj_stock_flush_required(struct obj_stock_pcp *stock,
static void __refill_obj_stock(struct obj_cgroup *objcg,
struct obj_stock_pcp *stock,
unsigned int nr_bytes,
- bool allow_uncharge)
+ bool allow_uncharge,
+ bool allow_spin)
{
unsigned int nr_pages = 0;
- if (!stock) {
- nr_pages = nr_bytes >> PAGE_SHIFT;
- nr_bytes = nr_bytes & (PAGE_SIZE - 1);
- atomic_add(nr_bytes, &objcg->nr_charged_bytes);
- goto out;
- }
+ if (!stock)
+ goto fallback;
if (READ_ONCE(stock->cached_objcg) != objcg) { /* reset if necessary */
+ /* Not safe to drain since objcg release acquires spinlock */
+ if (unlikely(!allow_spin))
+ goto fallback;
+
drain_obj_stock(stock);
obj_cgroup_get(objcg);
stock->nr_bytes = atomic_read(&objcg->nr_charged_bytes)
@@ -3346,6 +3347,13 @@ static void __refill_obj_stock(struct obj_cgroup *objcg,
out:
if (nr_pages)
obj_cgroup_uncharge_pages(objcg, nr_pages);
+ return;
+
+fallback:
+ nr_pages = nr_bytes >> PAGE_SHIFT;
+ nr_bytes = nr_bytes & (PAGE_SIZE - 1);
+ atomic_add(nr_bytes, &objcg->nr_charged_bytes);
+ goto out;
}
static void refill_obj_stock(struct obj_cgroup *objcg,
@@ -3353,7 +3361,8 @@ static void refill_obj_stock(struct obj_cgroup *objcg,
bool allow_uncharge)
{
struct obj_stock_pcp *stock = trylock_stock();
- __refill_obj_stock(objcg, stock, nr_bytes, allow_uncharge);
+ __refill_obj_stock(objcg, stock, nr_bytes, allow_uncharge,
+ /* allow_spin = */ true);
unlock_stock(stock);
}
@@ -3428,6 +3437,7 @@ bool __memcg_slab_post_alloc_hook(struct kmem_cache *s, struct list_lru *lru,
size_t size, void **p)
{
size_t obj_size = obj_full_size(s);
+ bool allow_spin = alloc_flags_allow_spinning(slab_alloc_flags);
struct obj_cgroup *objcg;
struct slab *slab;
unsigned long off;
@@ -3497,7 +3507,8 @@ bool __memcg_slab_post_alloc_hook(struct kmem_cache *s, struct list_lru *lru,
return false;
stock = trylock_stock();
if (remainder)
- __refill_obj_stock(objcg, stock, remainder, false);
+ __refill_obj_stock(objcg, stock, remainder, false,
+ allow_spin);
}
__account_obj_stock(objcg, stock, obj_size,
slab_pgdat(slab), cache_vmstat_idx(s));
@@ -3516,7 +3527,8 @@ bool __memcg_slab_post_alloc_hook(struct kmem_cache *s, struct list_lru *lru,
}
void __memcg_slab_free_hook(struct kmem_cache *s, struct slab *slab,
- void **p, int objects, unsigned long obj_exts)
+ void **p, int objects, unsigned long obj_exts,
+ bool allow_spin)
{
size_t obj_size = obj_full_size(s);
@@ -3535,7 +3547,7 @@ void __memcg_slab_free_hook(struct kmem_cache *s, struct slab *slab,
obj_ext->objcg = NULL;
stock = trylock_stock();
- __refill_obj_stock(objcg, stock, obj_size, true);
+ __refill_obj_stock(objcg, stock, obj_size, true, allow_spin);
__account_obj_stock(objcg, stock, -obj_size,
slab_pgdat(slab), cache_vmstat_idx(s));
unlock_stock(stock);
diff --git a/mm/slab.h b/mm/slab.h
index 281a65233795..a6b4ac298d08 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -660,7 +660,8 @@ bool __memcg_slab_post_alloc_hook(struct kmem_cache *s, struct list_lru *lru,
gfp_t flags, unsigned int slab_alloc_flags,
size_t size, void **p);
void __memcg_slab_free_hook(struct kmem_cache *s, struct slab *slab,
- void **p, int objects, unsigned long obj_exts);
+ void **p, int objects, unsigned long obj_exts,
+ bool allow_spin);
#endif
void kvfree_rcu_cb(struct rcu_head *head);
diff --git a/mm/slub.c b/mm/slub.c
index 917635203f73..32672a92581b 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2488,7 +2488,7 @@ bool memcg_slab_post_alloc_hook(struct kmem_cache *s, gfp_t flags,
static __fastpath_inline
void memcg_slab_free_hook(struct kmem_cache *s, struct slab *slab, void **p,
- int objects)
+ int objects, bool allow_spin)
{
unsigned long obj_exts;
@@ -2500,7 +2500,7 @@ void memcg_slab_free_hook(struct kmem_cache *s, struct slab *slab, void **p,
return;
get_slab_obj_exts(obj_exts);
- __memcg_slab_free_hook(s, slab, p, objects, obj_exts);
+ __memcg_slab_free_hook(s, slab, p, objects, obj_exts, allow_spin);
put_slab_obj_exts(obj_exts);
}
@@ -2575,7 +2575,7 @@ static inline bool memcg_slab_post_alloc_hook(struct kmem_cache *s,
}
static inline void memcg_slab_free_hook(struct kmem_cache *s, struct slab *slab,
- void **p, int objects)
+ void **p, int objects, bool allow_spin)
{
}
@@ -2946,11 +2946,12 @@ static bool __rcu_free_sheaf_prepare(struct kmem_cache *s,
void **p = &sheaf->objects[0];
unsigned int i = 0;
bool pfmemalloc = false;
+ bool allow_spin = true;
while (i < sheaf->size) {
struct slab *slab = virt_to_slab(p[i]);
- memcg_slab_free_hook(s, slab, p + i, 1);
+ memcg_slab_free_hook(s, slab, p + i, 1, allow_spin);
alloc_tagging_slab_free_hook(s, slab, p + i, 1);
if (unlikely(!slab_free_hook(s, p[i], init, true))) {
@@ -6215,12 +6216,13 @@ static void free_to_pcs_bulk(struct kmem_cache *s, size_t size, void **p)
struct node_barn *barn;
void *remote_objects[PCS_BATCH_MAX];
unsigned int remote_nr = 0;
+ bool allow_spin = true;
next_remote_batch:
while (i < size) {
struct slab *slab = virt_to_slab(p[i]);
- memcg_slab_free_hook(s, slab, p + i, 1);
+ memcg_slab_free_hook(s, slab, p + i, 1, allow_spin);
alloc_tagging_slab_free_hook(s, slab, p + i, 1);
if (unlikely(!slab_free_hook(s, p[i], init, false))) {
@@ -6398,13 +6400,16 @@ static __fastpath_inline
void slab_free(struct kmem_cache *s, struct slab *slab, void *object,
unsigned long addr)
{
- memcg_slab_free_hook(s, slab, &object, 1);
+ bool allow_spin = true;
+
+ memcg_slab_free_hook(s, slab, &object, 1, allow_spin);
alloc_tagging_slab_free_hook(s, slab, &object, 1);
if (unlikely(!slab_free_hook(s, object, slab_want_init_on_free(s), false)))
return;
- if (likely(can_free_to_pcs(slab)) && likely(free_to_pcs(s, object, true)))
+ if (likely(can_free_to_pcs(slab)) &&
+ likely(free_to_pcs(s, object, allow_spin)))
return;
__slab_free(s, slab, object, object, 1, addr);
@@ -6429,7 +6434,9 @@ static __fastpath_inline
void slab_free_bulk(struct kmem_cache *s, struct slab *slab, void *head,
void *tail, void **p, int cnt, unsigned long addr)
{
- memcg_slab_free_hook(s, slab, p, cnt);
+ bool allow_spin = true;
+
+ memcg_slab_free_hook(s, slab, p, cnt, allow_spin);
alloc_tagging_slab_free_hook(s, slab, p, cnt);
/*
* With KASAN enabled slab_free_freelist_hook modifies the freelist
@@ -6734,6 +6741,7 @@ void kfree_nolock(const void *object)
struct slab *slab;
struct kmem_cache *s;
void *x = (void *)object;
+ bool allow_spin = false;
if (unlikely(ZERO_OR_NULL_PTR(object)))
return;
@@ -6746,7 +6754,7 @@ void kfree_nolock(const void *object)
s = slab->slab_cache;
- memcg_slab_free_hook(s, slab, &x, 1);
+ memcg_slab_free_hook(s, slab, &x, 1, allow_spin);
alloc_tagging_slab_free_hook(s, slab, &x, 1);
/*
* Unlike slab_free() do NOT call the following:
@@ -6776,7 +6784,8 @@ void kfree_nolock(const void *object)
*/
kasan_slab_free(s, x, false, false, /* skip quarantine */true);
- if (likely(can_free_to_pcs(slab)) && likely(free_to_pcs(s, x, false)))
+ if (likely(can_free_to_pcs(slab)) &&
+ likely(free_to_pcs(s, x, allow_spin)))
return;
/*
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH RFC 2/4] mm/slab: handle allow_spin in slab_free_hook() instead of open coding
2026-06-24 13:11 [PATCH RFC 0/4] memcg,slab: kmalloc_nolock() fixes Harry Yoo (Oracle)
2026-06-24 13:11 ` [PATCH RFC 1/4] mm/memcontrol: do not drain objcg stock when spinning is not allowed Harry Yoo (Oracle)
@ 2026-06-24 13:11 ` Harry Yoo (Oracle)
2026-06-24 13:24 ` sashiko-bot
2026-06-24 13:11 ` [PATCH RFC 3/4] mm/slab: fix a deadlock in memcg_alloc_abort_single() Harry Yoo (Oracle)
` (2 subsequent siblings)
4 siblings, 1 reply; 9+ messages in thread
From: Harry Yoo (Oracle) @ 2026-06-24 13:11 UTC (permalink / raw)
To: Johannes Weiner, Michal Hocko, Roman Gushchin, Shakeel Butt,
Muchun Song, Andrew Morton, Vlastimil Babka, Hao Li,
Christoph Lameter, David Rientjes, Alexei Starovoitov,
Pedro Falcato
Cc: cgroups, linux-mm, linux-kernel, bpf
kfree_nolock() deliberately skips slab free hooks that should not be
called in unknown context. However, there is one more place that
needs the same thing: memcg_alloc_abort_single().
Instead of open coding slab_free_hook(), let it handle the allow_spin
parameter. This is required to correctly handle allocation failures due
to memcg.
There are two functional changes from this.
First, memcg_alloc_abort_single() -> slab_free_hook() path no longer
calls free hooks that acquire spinlocks if !allow_spin.
Second, kfree_nolock() now follows init_on_free which has been ignored.
Besides that, no functional change intended.
Fixes: af92793e52c3 ("slab: Introduce kmalloc_nolock() and kfree_nolock().")
Cc: stable@vger.kernel.org
Signed-off-by: Harry Yoo (Oracle) <harry@kernel.org>
---
mm/slub.c | 100 +++++++++++++++++++++++++++++++-------------------------------
1 file changed, 50 insertions(+), 50 deletions(-)
diff --git a/mm/slub.c b/mm/slub.c
index 32672a92581b..85760c8ff2e2 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2611,41 +2611,52 @@ struct rcu_delayed_free {
* - memcg_slab_post_alloc_hook()
* - alloc_tagging_slab_alloc_hook()
*
+ * slab_free_hook() assumes that memcg_slab_free_hook() and
+ * alloc_tagging_slab_free_hook() are already invoked.
+ *
* Free hooks that must handle missing corresponding alloc hooks:
* - kmemleak_free_recursive()
* - kfence_free()
*
- * Free hooks that have no alloc hook counterpart, and thus safe to call:
+ * Free hooks that have no alloc hook counterpart, and thus safe to call
+ * when spinning is allowed:
* - debug_check_no_locks_freed()
* - debug_check_no_obj_freed()
* - __kcsan_check_access()
*/
static __always_inline
bool slab_free_hook(struct kmem_cache *s, void *x, bool init,
- bool after_rcu_delay)
+ bool after_rcu_delay, bool allow_spin)
{
/* Are the object contents still accessible? */
bool still_accessible = (s->flags & SLAB_TYPESAFE_BY_RCU) && !after_rcu_delay;
- kmemleak_free_recursive(x, s->flags);
kmsan_slab_free(s, x);
- debug_check_no_locks_freed(x, s->object_size);
-
- if (!(s->flags & SLAB_DEBUG_OBJECTS))
- debug_check_no_obj_freed(x, s->object_size);
-
- /* Use KCSAN to help debug racy use-after-free. */
- if (!still_accessible)
- __kcsan_check_access(x, s->object_size,
- KCSAN_ACCESS_WRITE | KCSAN_ACCESS_ASSERT);
-
- if (kfence_free(x))
- return false;
+ if (likely(allow_spin)) {
+ /* These hooks acquire spinlocks */
+ kmemleak_free_recursive(x, s->flags);
+ debug_check_no_locks_freed(x, s->object_size);
+ if (!(s->flags & SLAB_DEBUG_OBJECTS))
+ debug_check_no_obj_freed(x, s->object_size);
+ /* Use KCSAN to help debug racy use-after-free. */
+ if (!still_accessible)
+ __kcsan_check_access(x, s->object_size,
+ KCSAN_ACCESS_WRITE | KCSAN_ACCESS_ASSERT);
+ if (kfence_free(x))
+ return false;
+ }
/*
* Give KASAN a chance to notice an invalid free operation before we
* modify the object.
+ *
+ * If KASAN finds a bug it will do kasan_report_invalid_free() which
+ * will call raw_spin_lock_irqsave() which is technically unsafe from
+ * NMI, but take chance and report kernel bug. The sequence of
+ * kasan_report_invalid_free() -> raw_spin_lock_irqsave() -> NMI
+ * -> kfree_nolock() -> kasan_report_invalid_free() on the same CPU
+ * is double buggy and deserves to deadlock.
*/
if (kasan_slab_pre_free(s, x))
return false;
@@ -2654,6 +2665,7 @@ bool slab_free_hook(struct kmem_cache *s, void *x, bool init,
if (still_accessible) {
struct rcu_delayed_free *delayed_free;
+ VM_WARN_ON_ONCE(!allow_spin);
delayed_free = kmalloc_obj(*delayed_free, GFP_NOWAIT);
if (delayed_free) {
/*
@@ -2701,8 +2713,11 @@ bool slab_free_hook(struct kmem_cache *s, void *x, bool init,
set_orig_size(s, x, orig_size);
}
- /* KASAN might put x into memory quarantine, delaying its reuse. */
- return !kasan_slab_free(s, x, init, still_accessible, false);
+ /*
+ * KASAN might put x into memory quarantine, delaying its reuse.
+ * Skip quarantine when spinning is not allowed as it uses a spinlock.
+ */
+ return !kasan_slab_free(s, x, init, still_accessible, !allow_spin);
}
static __fastpath_inline
@@ -2714,9 +2729,10 @@ bool slab_free_freelist_hook(struct kmem_cache *s, void **head, void **tail,
void *next = *head;
void *old_tail = *tail;
bool init;
+ bool allow_spin = true;
if (is_kfence_address(next)) {
- slab_free_hook(s, next, false, false);
+ slab_free_hook(s, next, false, false, allow_spin);
return false;
}
@@ -2731,7 +2747,7 @@ bool slab_free_freelist_hook(struct kmem_cache *s, void **head, void **tail,
next = get_freepointer(s, object);
/* If object's reuse doesn't have to be delayed */
- if (likely(slab_free_hook(s, object, init, false))) {
+ if (likely(slab_free_hook(s, object, init, false, allow_spin))) {
/* Move object to the new freelist */
set_freepointer(s, object, *head);
*head = object;
@@ -2954,7 +2970,7 @@ static bool __rcu_free_sheaf_prepare(struct kmem_cache *s,
memcg_slab_free_hook(s, slab, p + i, 1, allow_spin);
alloc_tagging_slab_free_hook(s, slab, p + i, 1);
- if (unlikely(!slab_free_hook(s, p[i], init, true))) {
+ if (unlikely(!slab_free_hook(s, p[i], init, true, allow_spin))) {
p[i] = p[--sheaf->size];
continue;
}
@@ -6225,7 +6241,7 @@ static void free_to_pcs_bulk(struct kmem_cache *s, size_t size, void **p)
memcg_slab_free_hook(s, slab, p + i, 1, allow_spin);
alloc_tagging_slab_free_hook(s, slab, p + i, 1);
- if (unlikely(!slab_free_hook(s, p[i], init, false))) {
+ if (unlikely(!slab_free_hook(s, p[i], init, false, allow_spin))) {
p[i] = p[--size];
continue;
}
@@ -6401,11 +6417,12 @@ void slab_free(struct kmem_cache *s, struct slab *slab, void *object,
unsigned long addr)
{
bool allow_spin = true;
+ bool init = slab_want_init_on_free(s);
memcg_slab_free_hook(s, slab, &object, 1, allow_spin);
alloc_tagging_slab_free_hook(s, slab, &object, 1);
- if (unlikely(!slab_free_hook(s, object, slab_want_init_on_free(s), false)))
+ if (unlikely(!slab_free_hook(s, object, init, false, allow_spin)))
return;
if (likely(can_free_to_pcs(slab)) &&
@@ -6422,10 +6439,12 @@ static noinline
void memcg_alloc_abort_single(struct kmem_cache *s, void *object)
{
struct slab *slab = virt_to_slab(object);
+ bool init = slab_want_init_on_free(s);
+ bool allow_spin = true;
alloc_tagging_slab_free_hook(s, slab, &object, 1);
- if (likely(slab_free_hook(s, object, slab_want_init_on_free(s), false)))
+ if (likely(slab_free_hook(s, object, init, false, allow_spin)))
__slab_free(s, slab, object, object, 1, _RET_IP_);
}
#endif
@@ -6456,6 +6475,8 @@ static void slab_free_after_rcu_debug(struct rcu_head *rcu_head)
void *object = delayed_free->object;
struct slab *slab = virt_to_slab(object);
struct kmem_cache *s;
+ bool allow_spin = true;
+ bool init;
kfree(delayed_free);
@@ -6469,8 +6490,9 @@ static void slab_free_after_rcu_debug(struct rcu_head *rcu_head)
if (WARN_ON(!(s->flags & SLAB_TYPESAFE_BY_RCU)))
return;
+ init = slab_want_init_on_free(s);
/* resume freeing */
- if (slab_free_hook(s, object, slab_want_init_on_free(s), true)) {
+ if (slab_free_hook(s, object, init, true, allow_spin)) {
__slab_free(s, slab, object, object, 1, _THIS_IP_);
stat(s, FREE_SLOWPATH);
}
@@ -6742,6 +6764,7 @@ void kfree_nolock(const void *object)
struct kmem_cache *s;
void *x = (void *)object;
bool allow_spin = false;
+ bool init;
if (unlikely(ZERO_OR_NULL_PTR(object)))
return;
@@ -6756,33 +6779,10 @@ void kfree_nolock(const void *object)
memcg_slab_free_hook(s, slab, &x, 1, allow_spin);
alloc_tagging_slab_free_hook(s, slab, &x, 1);
- /*
- * Unlike slab_free() do NOT call the following:
- * kmemleak_free_recursive(x, s->flags);
- * debug_check_no_locks_freed(x, s->object_size);
- * debug_check_no_obj_freed(x, s->object_size);
- * __kcsan_check_access(x, s->object_size, ..);
- * kfence_free(x);
- * since they take spinlocks or not safe from any context.
- */
- kmsan_slab_free(s, x);
- /*
- * If KASAN finds a kernel bug it will do kasan_report_invalid_free()
- * which will call raw_spin_lock_irqsave() which is technically
- * unsafe from NMI, but take chance and report kernel bug.
- * The sequence of
- * kasan_report_invalid_free() -> raw_spin_lock_irqsave() -> NMI
- * -> kfree_nolock() -> kasan_report_invalid_free() on the same CPU
- * is double buggy and deserves to deadlock.
- */
- if (kasan_slab_pre_free(s, x))
+
+ init = slab_want_init_on_free(s);
+ if (!slab_free_hook(s, x, init, false, allow_spin))
return;
- /*
- * memcg, kasan_slab_pre_free are done for 'x'.
- * The only thing left is kasan_poison without quarantine,
- * since kasan quarantine takes locks and not supported from NMI.
- */
- kasan_slab_free(s, x, false, false, /* skip quarantine */true);
if (likely(can_free_to_pcs(slab)) &&
likely(free_to_pcs(s, x, allow_spin)))
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH RFC 3/4] mm/slab: fix a deadlock in memcg_alloc_abort_single()
2026-06-24 13:11 [PATCH RFC 0/4] memcg,slab: kmalloc_nolock() fixes Harry Yoo (Oracle)
2026-06-24 13:11 ` [PATCH RFC 1/4] mm/memcontrol: do not drain objcg stock when spinning is not allowed Harry Yoo (Oracle)
2026-06-24 13:11 ` [PATCH RFC 2/4] mm/slab: handle allow_spin in slab_free_hook() instead of open coding Harry Yoo (Oracle)
@ 2026-06-24 13:11 ` Harry Yoo (Oracle)
2026-06-24 13:11 ` [PATCH RFC 4/4] mm/slab: serialize defer_free_barrier() Harry Yoo (Oracle)
2026-06-24 16:30 ` [PATCH RFC 0/4] memcg,slab: kmalloc_nolock() fixes Alexei Starovoitov
4 siblings, 0 replies; 9+ messages in thread
From: Harry Yoo (Oracle) @ 2026-06-24 13:11 UTC (permalink / raw)
To: Johannes Weiner, Michal Hocko, Roman Gushchin, Shakeel Butt,
Muchun Song, Andrew Morton, Vlastimil Babka, Hao Li,
Christoph Lameter, David Rientjes, Alexei Starovoitov,
Pedro Falcato
Cc: cgroups, linux-mm, linux-kernel, bpf
When kmalloc_nolock() successfully grabs a slab object but memcg aborts
the allocation, the object is freed via __slab_free(). Calling
__slab_free() in unknown context is not allowed and can lead to a
deadlock.
Free the object via defer_free() when spinning is not allowed.
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260610-slab_alloc_flags-v2-0-7190909db118%40kernel.org?part=9
Fixes: af92793e52c3 ("slab: Introduce kmalloc_nolock() and kfree_nolock().")
Cc: stable@vger.kernel.org
Signed-off-by: Harry Yoo (Oracle) <harry@kernel.org>
---
mm/slub.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/mm/slub.c b/mm/slub.c
index 85760c8ff2e2..4a3618e3967e 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2459,7 +2459,8 @@ alloc_tagging_slab_free_hook(struct kmem_cache *s, struct slab *slab, void **p,
#ifdef CONFIG_MEMCG
-static void memcg_alloc_abort_single(struct kmem_cache *s, void *object);
+static void memcg_alloc_abort_single(struct kmem_cache *s, void *object,
+ bool allow_spin);
static __fastpath_inline
bool memcg_slab_post_alloc_hook(struct kmem_cache *s, gfp_t flags,
@@ -2477,7 +2478,9 @@ bool memcg_slab_post_alloc_hook(struct kmem_cache *s, gfp_t flags,
return true;
if (likely(size == 1)) {
- memcg_alloc_abort_single(s, *p);
+ bool allow_spin = alloc_flags_allow_spinning(ac->alloc_flags);
+
+ memcg_alloc_abort_single(s, *p, allow_spin);
*p = NULL;
} else {
kmem_cache_free_bulk(s, size, p);
@@ -6436,16 +6439,20 @@ void slab_free(struct kmem_cache *s, struct slab *slab, void *object,
#ifdef CONFIG_MEMCG
/* Do not inline the rare memcg charging failed path into the allocation path */
static noinline
-void memcg_alloc_abort_single(struct kmem_cache *s, void *object)
+void memcg_alloc_abort_single(struct kmem_cache *s, void *object, bool allow_spin)
{
struct slab *slab = virt_to_slab(object);
bool init = slab_want_init_on_free(s);
- bool allow_spin = true;
alloc_tagging_slab_free_hook(s, slab, &object, 1);
- if (likely(slab_free_hook(s, object, init, false, allow_spin)))
+ if (unlikely(!slab_free_hook(s, object, init, false, allow_spin)))
+ return;
+
+ if (likely(allow_spin))
__slab_free(s, slab, object, object, 1, _RET_IP_);
+ else
+ defer_free(s, object);
}
#endif
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH RFC 4/4] mm/slab: serialize defer_free_barrier()
2026-06-24 13:11 [PATCH RFC 0/4] memcg,slab: kmalloc_nolock() fixes Harry Yoo (Oracle)
` (2 preceding siblings ...)
2026-06-24 13:11 ` [PATCH RFC 3/4] mm/slab: fix a deadlock in memcg_alloc_abort_single() Harry Yoo (Oracle)
@ 2026-06-24 13:11 ` Harry Yoo (Oracle)
2026-06-24 13:25 ` sashiko-bot
2026-06-24 16:30 ` [PATCH RFC 0/4] memcg,slab: kmalloc_nolock() fixes Alexei Starovoitov
4 siblings, 1 reply; 9+ messages in thread
From: Harry Yoo (Oracle) @ 2026-06-24 13:11 UTC (permalink / raw)
To: Johannes Weiner, Michal Hocko, Roman Gushchin, Shakeel Butt,
Muchun Song, Andrew Morton, Vlastimil Babka, Hao Li,
Christoph Lameter, David Rientjes, Alexei Starovoitov,
Pedro Falcato
Cc: cgroups, linux-mm, linux-kernel, bpf
irq_work_sync() uses rcuwait instead of busy waiting in two cases:
1. The kernel is using PREEMPT_RT and the irq work does not run in a
hardirq context.
2. The architecture cannot send inter-processor interrupts to make
busy waiting reasonably short.
However, rcuwait.h says:
> The caller is responsible for locking around rcuwait_wait_event(),
> and [prepare_to/finish]_rcuwait() such that writes to @task are
> properly serialized.
Since defer_free_barrier() calls irq_work_sync() without any locks,
it can potentially cause a hang as writes to @task are not serialized.
Fix this by calling defer_free_barrier() under slab_mutex and
cpus_read_lock() and add lockdep asserts.
Now that defer_free_barrier() is called inside cpus_read_lock(), iterate
over online cpus instead of possible cpus.
Reported-by: Sashiko <sashiko+bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260615-kfree_rcu_nolock-v3-0-70a54f3775bb%40kernel.org?part=5
Fixes: af92793e52c3 ("slab: Introduce kmalloc_nolock() and kfree_nolock().")
Cc: stable@vger.kernel.org
Signed-off-by: Harry Yoo (Oracle) <harry@kernel.org>
---
mm/slab_common.c | 5 ++---
mm/slub.c | 6 +++++-
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 388eb5980859..27f77273fabe 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -550,11 +550,10 @@ void kmem_cache_destroy(struct kmem_cache *s)
rcu_barrier();
}
- /* Wait for deferred work from kmalloc/kfree_nolock() */
- defer_free_barrier();
-
cpus_read_lock();
mutex_lock(&slab_mutex);
+ /* Wait for deferred work from kmalloc/kfree_nolock() */
+ defer_free_barrier();
s->refcount--;
if (s->refcount) {
diff --git a/mm/slub.c b/mm/slub.c
index 4a3618e3967e..52c8d3f33782 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -6411,7 +6411,11 @@ void defer_free_barrier(void)
{
int cpu;
- for_each_possible_cpu(cpu)
+ /* irq_work_sync() may use rcuwait that requires serialization */
+ lockdep_assert_held(&slab_mutex);
+ lockdep_assert_cpus_held();
+
+ for_each_online_cpu(cpu)
irq_work_sync(&per_cpu_ptr(&defer_free_objects, cpu)->work);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH RFC 2/4] mm/slab: handle allow_spin in slab_free_hook() instead of open coding
2026-06-24 13:11 ` [PATCH RFC 2/4] mm/slab: handle allow_spin in slab_free_hook() instead of open coding Harry Yoo (Oracle)
@ 2026-06-24 13:24 ` sashiko-bot
0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-06-24 13:24 UTC (permalink / raw)
Cc: tj, hannes, mkoutny, bpf
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] slab_free_hook() proceeds with an unsafe GFP_NOWAIT allocation after VM_WARN_ON_ONCE(!allow_spin) for SLAB_TYPESAFE_BY_RCU caches, deadlocking NMI callers.
--
commit b732dfb9de7b44943319ed866b71dd254fecb07a
Author: Harry Yoo (Oracle) <harry@kernel.org>
mm/slab: handle allow_spin in slab_free_hook() instead of open coding
This commit refactors slab_free_hook() to accept an allow_spin parameter,
replacing the open-coded hook logic in memcg_alloc_abort_single() and
kfree_nolock(). It ensures that spinlock-acquiring free hooks and KASAN
quarantine operations are bypassed when allow_spin is false.
> diff --git a/mm/slub.c b/mm/slub.c
> index 32672a92581b0..85760c8ff2e29 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
[ ... ]
> @@ -2654,6 +2665,7 @@ bool slab_free_hook(struct kmem_cache *s, void *x, bool init,
> if (still_accessible) {
> struct rcu_delayed_free *delayed_free;
>
> + VM_WARN_ON_ONCE(!allow_spin);
> delayed_free = kmalloc_obj(*delayed_free, GFP_NOWAIT);
[Severity: High]
If allow_spin is false (e.g., when called from kfree_nolock() in NMI or
atomic context), this triggers the warning but still proceeds to call
kmalloc_obj() with GFP_NOWAIT.
Since GFP_NOWAIT does not prevent the slab allocator from acquiring spinlocks
(such as pcp->lock or node->list_lock), and it does not strip
__GFP_KSWAPD_RECLAIM which can wake kswapd and acquire scheduler locks, could
this lead to a deadlock if called in NMI context?
Should this path explicitly skip the allocation or return early when
allow_spin is false?
> if (delayed_free) {
> /*
> * Let KASAN track our call stack as a "related work
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260624-kmalloc-nolock-fixes-v1-0-fdf4d17351dd@kernel.org?part=2
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH RFC 4/4] mm/slab: serialize defer_free_barrier()
2026-06-24 13:11 ` [PATCH RFC 4/4] mm/slab: serialize defer_free_barrier() Harry Yoo (Oracle)
@ 2026-06-24 13:25 ` sashiko-bot
0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-06-24 13:25 UTC (permalink / raw)
Cc: mkoutny, hannes, bpf, tj
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Skipping offline CPUs in defer_free_barrier() causes a Use-After-Free when an offline CPU resumes and processes stranded defer_free_objects.
--
commit f2e5ab943e275050dc4612d4d6e119be44858827
Author: Harry Yoo (Oracle) <harry@kernel.org>
mm/slab: serialize defer_free_barrier()
This commit addresses a potential hang in defer_free_barrier() by executing
it under slab_mutex and cpus_read_lock(). It also changes the iteration
from for_each_possible_cpu() to for_each_online_cpu() since the lock
is now held.
Closes: https://sashiko.dev/#/patchset/20260615-kfree_rcu_nolock-v3-0-70a54f3775bb%40kernel.org?part=5
> diff --git a/mm/slub.c b/mm/slub.c
> index 4a3618e3967ed..52c8d3f337827 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -6411,7 +6411,11 @@ void defer_free_barrier(void)
> {
> int cpu;
>
> - for_each_possible_cpu(cpu)
> + /* irq_work_sync() may use rcuwait that requires serialization */
> + lockdep_assert_held(&slab_mutex);
> + lockdep_assert_cpus_held();
> +
> + for_each_online_cpu(cpu)
[Severity: High]
By changing this to for_each_online_cpu(), does this skip offline CPUs
that might still hold pending deferred free objects?
If kfree_nolock() is called during CPU teardown after smpboot_park_threads()
or from a late NMI on an offline CPU, the defer_free work could remain
stranded on the offline CPU's lazy_list.
Because kmem_cache_destroy() would now skip waiting for these offline CPUs,
it could successfully destroy the cache while objects are still queued.
When the CPU is eventually brought back online, wouldn't the resumed CPU
process the stranded objects in free_deferred_objects() and dereference the
already destroyed cache?
mm/slub.c:free_deferred_objects() {
...
s = slab->slab_cache;
...
set_freepointer(s, x, NULL);
__slab_free(s, slab, x, x, 1, _THIS_IP_);
...
}
> + irq_work_sync(&per_cpu_ptr(&defer_free_objects, cpu)->work);
> }
>
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260624-kmalloc-nolock-fixes-v1-0-fdf4d17351dd@kernel.org?part=4
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH RFC 1/4] mm/memcontrol: do not drain objcg stock when spinning is not allowed
2026-06-24 13:11 ` [PATCH RFC 1/4] mm/memcontrol: do not drain objcg stock when spinning is not allowed Harry Yoo (Oracle)
@ 2026-06-24 13:28 ` sashiko-bot
0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-06-24 13:28 UTC (permalink / raw)
Cc: mkoutny, bpf, tj, hannes
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
New issues:
- [High] The fallback path in `__refill_obj_stock()` indefinitely accumulates memcg charge without uncharging it, leading to a massive memcg leak and premature OOM for `!allow_spin` workloads.
Pre-existing issues:
- [High] `__memcg_slab_free_hook()` unconditionally drops object references via `obj_cgroup_put()`, causing spinlock acquisition on PREEMPT_RT even when `allow_spin == false`.
- [High] `kfree_nolock()` can still acquire a sleeping lock on PREEMPT_RT through `obj_cgroup_uncharge_pages()` when `allow_spin == false`.
--
commit f6eb6f507d999767dfe0866c3a461084a0d9e774
Author: Harry Yoo (Oracle) <harry@kernel.org>
mm/memcontrol: do not drain objcg stock when spinning is not allowed
This commit updates kmalloc_nolock() and related objcg functions to avoid
draining the objcg stock when spinning is not allowed, aiming to fix
lockdep warnings on PREEMPT_RT. It falls back to atomics if the objcg
doesn't match and draining is unsafe.
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 29390ba13baa2..5bb5e75ef5b0c 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
[ ... ]
> @@ -3346,6 +3347,13 @@ static void __refill_obj_stock(struct obj_cgroup *objcg,
> out:
> if (nr_pages)
> obj_cgroup_uncharge_pages(objcg, nr_pages);
[Severity: High]
This is a pre-existing issue, but can this call to
obj_cgroup_uncharge_pages() still acquire a sleeping lock on PREEMPT_RT?
Even with allow_spin == false, __refill_obj_stock() calls
obj_cgroup_uncharge_pages() if the object's objcg matches the CPU's cached
objcg and the accumulated bytes exceed PAGE_SIZE, or if falling back with a
large object.
obj_cgroup_uncharge_pages() unconditionally calls refill_stock(), which
uses local_trylock(&memcg_stock.lock).
Per kernel guidelines, acquiring a local_lock (even via trylock) within a
raw spinlock or hardirq context causes an Invalid wait context lockdep splat
due to wait-type mismatch.
> + return;
> +
> +fallback:
> + nr_pages = nr_bytes >> PAGE_SHIFT;
> + nr_bytes = nr_bytes & (PAGE_SIZE - 1);
> + atomic_add(nr_bytes, &objcg->nr_charged_bytes);
> + goto out;
> }
[Severity: High]
Does this fallback path indefinitely accumulate memcg charges without ever
uncharging them?
When __refill_obj_stock() is called with allow_spin == false and the cached
objcg doesn't match, it jumps to this fallback path. It adds the remaining
bytes to objcg->nr_charged_bytes via atomic_add(). Because nr_bytes is
typically less than PAGE_SIZE, nr_pages is 0.
Since the function returns immediately via the out label without checking if
the newly accumulated nr_charged_bytes exceeds PAGE_SIZE, the charge is
never uncharged.
If a workload exclusively uses kfree_nolock(), could the memcg charge grow
unbounded and cause a premature OOM?
[ ... ]
> @@ -3535,7 +3547,7 @@ void __memcg_slab_free_hook(struct kmem_cache *s, struct slab *slab,
> obj_ext->objcg = NULL;
>
> stock = trylock_stock();
> - __refill_obj_stock(objcg, stock, obj_size, true);
> + __refill_obj_stock(objcg, stock, obj_size, true, allow_spin);
> __account_obj_stock(objcg, stock, -obj_size,
> slab_pgdat(slab), cache_vmstat_idx(s));
> unlock_stock(stock);
[Severity: High]
This isn't a bug introduced by this patch, but does __memcg_slab_free_hook()
still unconditionally drop object references via obj_cgroup_put() right
after unlock_stock() returns?
If this drops the final reference to an offline memcg, obj_cgroup_put()
synchronously invokes the release callback obj_cgroup_release(), which
acquires the sleeping objcg_lock lock.
Could this trigger the exact Invalid wait context lockdep splat or deadlock
on PREEMPT_RT that this patch intends to prevent, even when allow_spin is
false?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260624-kmalloc-nolock-fixes-v1-0-fdf4d17351dd@kernel.org?part=1
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH RFC 0/4] memcg,slab: kmalloc_nolock() fixes
2026-06-24 13:11 [PATCH RFC 0/4] memcg,slab: kmalloc_nolock() fixes Harry Yoo (Oracle)
` (3 preceding siblings ...)
2026-06-24 13:11 ` [PATCH RFC 4/4] mm/slab: serialize defer_free_barrier() Harry Yoo (Oracle)
@ 2026-06-24 16:30 ` Alexei Starovoitov
4 siblings, 0 replies; 9+ messages in thread
From: Alexei Starovoitov @ 2026-06-24 16:30 UTC (permalink / raw)
To: Harry Yoo (Oracle), Johannes Weiner, Michal Hocko, Roman Gushchin,
Shakeel Butt, Muchun Song, Andrew Morton, Vlastimil Babka, Hao Li,
Christoph Lameter, David Rientjes, Alexei Starovoitov,
Pedro Falcato
Cc: cgroups, linux-mm, linux-kernel, bpf
On Wed Jun 24, 2026 at 6:11 AM PDT, Harry Yoo (Oracle) wrote:
>
> Bug 1 was reported by lockdep, and bugs 2 [2] and 3 [3] were
> reported by Sashiko.
... and in fixes for sashiko complains sashiko finds more issues.
I don't think it will ever end. I suggest to fix realistic scenarios
instead of one out of billion cases that sashiko think is plausible
but will never be hit in reality. The chance of server crashing
due to cosmic rays are higher than such bugs. Hence do not fix them.
> To BPF folks: do we need to backport kmalloc_nolock() support
> for architectures without __CMPXCHG_DOUBLE to v6.18?
nope.
> There are still few users in v6.18, but I can't tell whether it is
> necessary to backport it to v6.18 (hopefully not as urgent as other
> bugfixes).
imo none of these 'fixes' are necessary. Humans are not hitting them.
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-06-24 16:30 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-24 13:11 [PATCH RFC 0/4] memcg,slab: kmalloc_nolock() fixes Harry Yoo (Oracle)
2026-06-24 13:11 ` [PATCH RFC 1/4] mm/memcontrol: do not drain objcg stock when spinning is not allowed Harry Yoo (Oracle)
2026-06-24 13:28 ` sashiko-bot
2026-06-24 13:11 ` [PATCH RFC 2/4] mm/slab: handle allow_spin in slab_free_hook() instead of open coding Harry Yoo (Oracle)
2026-06-24 13:24 ` sashiko-bot
2026-06-24 13:11 ` [PATCH RFC 3/4] mm/slab: fix a deadlock in memcg_alloc_abort_single() Harry Yoo (Oracle)
2026-06-24 13:11 ` [PATCH RFC 4/4] mm/slab: serialize defer_free_barrier() Harry Yoo (Oracle)
2026-06-24 13:25 ` sashiko-bot
2026-06-24 16:30 ` [PATCH RFC 0/4] memcg,slab: kmalloc_nolock() fixes Alexei Starovoitov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox