Skip to content

Commit 2eb14c1

Browse files
committed
mm, slab: reintroduce rcu_barrier() into kmem_cache_destroy()
There used to be a rcu_barrier() for SLAB_TYPESAFE_BY_RCU caches in kmem_cache_destroy() until commit 657dc2f ("slab: remove synchronous rcu_barrier() call in memcg cache release path") moved it to an asynchronous work that finishes the destroying of such caches. The motivation for that commit was the MEMCG_KMEM integration that at the time created and removed clones of the global slab caches together with their cgroups, and blocking cgroups removal was unwelcome. The implementation later changed to per-object memcg tracking using a single cache, so there should be no more need for a fast non-blocking kmem_cache_destroy(), which is typically only done when a module is unloaded etc. Going back to synchronous barrier has the following advantages: - simpler implementation - it's easier to test the result of kmem_cache_destroy() in a kunit test Thus effectively revert commit 657dc2f. It is not a 1:1 revert as the code has changed since. The main part is that kmem_cache_release(s) is always called from kmem_cache_destroy(), but for SLAB_TYPESAFE_BY_RCU caches there's a rcu_barrier() first. Suggested-by: Mateusz Guzik <[email protected]> Reviewed-by: Jann Horn <[email protected]> Signed-off-by: Vlastimil Babka <[email protected]>
1 parent f77d0cd commit 2eb14c1

File tree

1 file changed

+4
-43
lines changed

1 file changed

+4
-43
lines changed

mm/slab_common.c

Lines changed: 4 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,6 @@ LIST_HEAD(slab_caches);
4040
DEFINE_MUTEX(slab_mutex);
4141
struct kmem_cache *kmem_cache;
4242

43-
static LIST_HEAD(slab_caches_to_rcu_destroy);
44-
static void slab_caches_to_rcu_destroy_workfn(struct work_struct *work);
45-
static DECLARE_WORK(slab_caches_to_rcu_destroy_work,
46-
slab_caches_to_rcu_destroy_workfn);
47-
4843
/*
4944
* Set of flags that will prevent slab merging
5045
*/
@@ -499,33 +494,6 @@ static void kmem_cache_release(struct kmem_cache *s)
499494
slab_kmem_cache_release(s);
500495
}
501496

502-
static void slab_caches_to_rcu_destroy_workfn(struct work_struct *work)
503-
{
504-
LIST_HEAD(to_destroy);
505-
struct kmem_cache *s, *s2;
506-
507-
/*
508-
* On destruction, SLAB_TYPESAFE_BY_RCU kmem_caches are put on the
509-
* @slab_caches_to_rcu_destroy list. The slab pages are freed
510-
* through RCU and the associated kmem_cache are dereferenced
511-
* while freeing the pages, so the kmem_caches should be freed only
512-
* after the pending RCU operations are finished. As rcu_barrier()
513-
* is a pretty slow operation, we batch all pending destructions
514-
* asynchronously.
515-
*/
516-
mutex_lock(&slab_mutex);
517-
list_splice_init(&slab_caches_to_rcu_destroy, &to_destroy);
518-
mutex_unlock(&slab_mutex);
519-
520-
if (list_empty(&to_destroy))
521-
return;
522-
523-
rcu_barrier();
524-
525-
list_for_each_entry_safe(s, s2, &to_destroy, list)
526-
kmem_cache_release(s);
527-
}
528-
529497
void slab_kmem_cache_release(struct kmem_cache *s)
530498
{
531499
__kmem_cache_release(s);
@@ -535,7 +503,6 @@ void slab_kmem_cache_release(struct kmem_cache *s)
535503

536504
void kmem_cache_destroy(struct kmem_cache *s)
537505
{
538-
bool rcu_set;
539506
int err;
540507

541508
if (unlikely(!s) || !kasan_check_byte(s))
@@ -551,8 +518,6 @@ void kmem_cache_destroy(struct kmem_cache *s)
551518
return;
552519
}
553520

554-
rcu_set = s->flags & SLAB_TYPESAFE_BY_RCU;
555-
556521
/* free asan quarantined objects */
557522
kasan_cache_shutdown(s);
558523

@@ -572,14 +537,10 @@ void kmem_cache_destroy(struct kmem_cache *s)
572537
if (err)
573538
return;
574539

575-
if (rcu_set) {
576-
mutex_lock(&slab_mutex);
577-
list_add_tail(&s->list, &slab_caches_to_rcu_destroy);
578-
schedule_work(&slab_caches_to_rcu_destroy_work);
579-
mutex_unlock(&slab_mutex);
580-
} else {
581-
kmem_cache_release(s);
582-
}
540+
if (s->flags & SLAB_TYPESAFE_BY_RCU)
541+
rcu_barrier();
542+
543+
kmem_cache_release(s);
583544
}
584545
EXPORT_SYMBOL(kmem_cache_destroy);
585546

0 commit comments

Comments
 (0)