diff options
Diffstat (limited to 'mm/slab_common.c')
-rw-r--r-- | mm/slab_common.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/mm/slab_common.c b/mm/slab_common.c index 1a2873293f5d..884e8e70a56d 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -511,6 +511,22 @@ void kmem_cache_destroy(struct kmem_cache *s) /* in-flight kfree_rcu()'s may include objects from our cache */ kvfree_rcu_barrier(); + if (IS_ENABLED(CONFIG_SLUB_RCU_DEBUG) && + (s->flags & SLAB_TYPESAFE_BY_RCU)) { + /* + * Under CONFIG_SLUB_RCU_DEBUG, when objects in a + * SLAB_TYPESAFE_BY_RCU slab are freed, SLUB will internally + * defer their freeing with call_rcu(). + * Wait for such call_rcu() invocations here before actually + * destroying the cache. + * + * It doesn't matter that we haven't looked at the slab refcount + * yet - slabs with SLAB_TYPESAFE_BY_RCU can't be merged, so + * the refcount should be 1 here. + */ + rcu_barrier(); + } + cpus_read_lock(); mutex_lock(&slab_mutex); |