[PATCH for-next-fixes v2 5/5] mm/slab: serialize deferred_work_barrier()

From: Harry Yoo (Meta)

Date: Tue Nov 03 2026 - 09:59:32 EST


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 deferred_work_barrier() calls irq_work_sync() without any locks,
it can potentially cause a hang as writes to @task are not serialized.

Fix this by serializing deferred_work_barrier() with a dedicated mutex.
We cannot reuse slab_mutex because e.g.) some users of
kvfree_rcu_barrier() are outside mm/.

Reported-by: Sashiko <sashiko-bot@xxxxxxxxxx>
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().")
Signed-off-by: Harry Yoo (Meta) <harry@xxxxxxxxxx>
---
mm/slub.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/mm/slub.c b/mm/slub.c
index 6dfa8ca3c937..50e88edcef3a 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -6636,8 +6636,12 @@ void defer_kfree_rcu(struct kvfree_rcu_head *head)
/* Must be called before flush_rcu_sheaves_on_cache() */
void deferred_work_barrier(void)
{
+ static DEFINE_MUTEX(barrier_mutex);
int cpu;

+ /* irq_work_sync() may use rcuwait that requires serialization */
+ guard(mutex)(&barrier_mutex);
+
for_each_possible_cpu(cpu)
irq_work_sync(&per_cpu_ptr(&deferred_percpu_work, cpu)->work);
}

--
2.54.0