slab fixes for 7.3-rc2

-----BEGIN PGP SIGNATURE-----
 
 iQFPBAABCAA5FiEEe7vIQRWZI0iWSE3xu+CwddJFiJoFAmqjuAUbFIAAAAAABAAO
 bWFudTIsMi41KzEuMTIsMiwyAAoJELvgsHXSRYia070H/RpgbPlRT+YF5EceAqlz
 gbCHYJa7ep52uCIZSgHd0DpMiE3jF8tRtLlpaF2l961hYXIr+NhEC9HKerJcD5tc
 4LUpGu6Cs5/ruYz7fbAltYrAZ2YOAhaJwBBy0Buc2Xl37OpONR8hUWMYlqqXBSWM
 bApp9mrRYzLmQBpYn5N1KyZU9gBespiouCnStEUzD2s06VjnHSUJ5tBplbXXPC0v
 My/kjaUim9z0P91FHPFooFQtzhlLQI96obROsbKR18euePml+C+XPhhmDwAY0NVT
 VtAPm2ov7oTvy0FvjDAVzAdrYGIIXVluonJqhgLFi6+Um1L3iBE39Q2OEMiQ/Lq3
 044=
 =B/eP
 -----END PGP SIGNATURE-----

Merge tag 'slab-for-7.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/mm/slab

Pull slab fixes from Vlastimil Babka:

 - Stable fix for an ABA issue causing slab list corruption introduced
   in 7.2 (Harry Yoo, with big thanks to Hyunwoo Kim for the thorough
   report and initial version of the fix)

 - Fix for 7.3 regression of kvfree_rcu() on PREEMPT_RT which can cause
   a deadlock from the set_cpus_allowed_force() caller (Vlastimil Babka)

* tag 'slab-for-7.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/mm/slab:
  mm/slab: take n->list_lock in __slab_try_return_freelist() to avoid race
  mm/slab: disallow kfree_rcu_sheaf() on PREEMPT_RT again
This commit is contained in:
Linus Torvalds 2026-09-11 11:56:33 -07:00
commit 3026c6e4f2
2 changed files with 25 additions and 20 deletions

View File

@ -1667,14 +1667,6 @@ static bool kfree_rcu_sheaf(void *obj)
{
struct kmem_cache *s;
struct slab *slab;
unsigned int free_flags = SLAB_FREE_DEFAULT;
/*
* It is not safe to spin on PREEMPT_RT because the kernel might be
* holding a raw spinlock and slab acquires sleeping locks.
*/
if (IS_ENABLED(CONFIG_PREEMPT_RT))
free_flags = SLAB_FREE_NOLOCK;
if (is_vmalloc_addr(obj))
return false;
@ -1685,7 +1677,7 @@ static bool kfree_rcu_sheaf(void *obj)
s = slab->slab_cache;
if (likely(!IS_ENABLED(CONFIG_NUMA) || slab_nid(slab) == numa_mem_id()))
return __kfree_rcu_sheaf(s, obj, free_flags);
return __kfree_rcu_sheaf(s, obj, SLAB_FREE_DEFAULT);
return false;
}
@ -2034,7 +2026,13 @@ void kvfree_call_rcu(struct kvfree_rcu_head *head, void *ptr)
if (!head)
might_sleep();
if (kfree_rcu_sheaf(ptr))
/*
* kvfree_rcu() is called by set_cpus_allowed_force() with
* task_struct::pi_lock acquired. On PREEMPT_RT the local_trylock()
* usage below will acquire the waitlock which must be avoided.
* Therefore avoid it on PREEMPT_RT.
*/
if (!IS_ENABLED(CONFIG_PREEMPT_RT) && kfree_rcu_sheaf(ptr))
return;
// Queue the object but don't yet schedule the batch.

View File

@ -5680,10 +5680,12 @@ static noinline void free_to_partial_list(
*
* Fail if the slab isn't full anymore due to a concurrent free.
*/
static bool __slab_try_return_freelist(struct kmem_cache *s, struct slab *slab,
void *head, int cnt)
static bool __slab_try_return_freelist(struct kmem_cache *s,
struct kmem_cache_node *n,
struct slab *slab, void *head, int cnt)
{
struct freelist_counters old, new;
unsigned long flags;
old.freelist = slab->freelist;
old.counters = slab->counters;
@ -5695,9 +5697,15 @@ static bool __slab_try_return_freelist(struct kmem_cache *s, struct slab *slab,
new.counters = old.counters;
new.inuse -= cnt;
if (!slab_update_freelist(s, slab, &old, &new, "__slab_try_return_freelist"))
return false;
spin_lock_irqsave(&n->list_lock, flags);
if (!slab_update_freelist(s, slab, &old, &new, "__slab_try_return_freelist")) {
spin_unlock_irqrestore(&n->list_lock, flags);
return false;
}
add_partial(n, slab, ADD_TO_TAIL);
spin_unlock_irqrestore(&n->list_lock, flags);
return true;
}
@ -6088,8 +6096,9 @@ static void rcu_free_sheaf(struct rcu_head *head)
/*
* kvfree_call_rcu() can be called while holding a raw_spinlock_t. Since
* __kfree_rcu_sheaf() may acquire a spinlock_t (sleeping lock on PREEMPT_RT),
* this would violate lock nesting rules. Therefore, kvfree_call_rcu() avoids
* this problem by passing SLAB_FREE_NOLOCK on PREEMPT_RT.
* this would violate lock nesting rules. Therefore, kfree_call_rcu_nolock()
* avoids this problem by passing SLAB_FREE_NOLOCK. kvfree_call_rcu() is
* bypassing the sheaves layer completely on PREEMPT_RT.
*
* However, lockdep still complains that it is invalid to acquire spinlock_t
* while holding raw_spinlock_t, even on !PREEMPT_RT where spinlock_t is a
@ -7296,10 +7305,8 @@ __refill_objects_node(struct kmem_cache *s, void **p, gfp_t gfp, unsigned int mi
void *head = object;
void *tail;
if (__slab_try_return_freelist(s, slab, head, count)) {
list_add(&slab->slab_list, &pc.slabs);
if (__slab_try_return_freelist(s, n, slab, head, count))
break;
}
do {
tail = object;
@ -7312,7 +7319,7 @@ __refill_objects_node(struct kmem_cache *s, void **p, gfp_t gfp, unsigned int mi
break;
}
if (!list_empty(&pc.slabs)) {
if (unlikely(!list_empty(&pc.slabs))) {
spin_lock_irqsave(&n->list_lock, flags);
list_for_each_entry(slab, &pc.slabs, slab_list)