summaryrefslogtreecommitdiff
path: root/mm/slab_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/slab_common.c')
-rw-r--r--mm/slab_common.c16
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);