]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
mm: memcg/slab: synchronize access to kmem_cache dying flag using a spinlock
authorRoman Gushchin <guro@fb.com>
Fri, 12 Jul 2019 03:56:24 +0000 (20:56 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 12 Jul 2019 18:05:44 +0000 (11:05 -0700)
Currently the memcg_params.dying flag and the corresponding workqueue used
for the asynchronous deactivation of kmem_caches is synchronized using the
slab_mutex.

It makes impossible to check this flag from the irq context, which will be
required in order to implement asynchronous release of kmem_caches.

So let's switch over to the irq-save flavor of the spinlock-based
synchronization.

Link: http://lkml.kernel.org/r/20190611231813.3148843-8-guro@fb.com
Signed-off-by: Roman Gushchin <guro@fb.com>
Acked-by: Vladimir Davydov <vdavydov.dev@gmail.com>
Reviewed-by: Shakeel Butt <shakeelb@google.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Waiman Long <longman@redhat.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: Andrei Vagin <avagin@gmail.com>
Cc: Qian Cai <cai@lca.pw>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
mm/slab_common.c

index afdd73553b88d5960b9fb72fb26123bf3bc0e252..a15557776d7d13a90069d6bd3a074f938c893606 100644 (file)
@@ -130,6 +130,7 @@ int __kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t nr,
 #ifdef CONFIG_MEMCG_KMEM
 
 LIST_HEAD(slab_root_caches);
+static DEFINE_SPINLOCK(memcg_kmem_wq_lock);
 
 void slab_init_memcg_params(struct kmem_cache *s)
 {
@@ -734,14 +735,22 @@ static void kmemcg_cache_deactivate(struct kmem_cache *s)
 
        __kmemcg_cache_deactivate(s);
 
+       /*
+        * memcg_kmem_wq_lock is used to synchronize memcg_params.dying
+        * flag and make sure that no new kmem_cache deactivation tasks
+        * are queued (see flush_memcg_workqueue() ).
+        */
+       spin_lock_irq(&memcg_kmem_wq_lock);
        if (s->memcg_params.root_cache->memcg_params.dying)
-               return;
+               goto unlock;
 
        /* pin memcg so that @s doesn't get destroyed in the middle */
        css_get(&s->memcg_params.memcg->css);
 
        s->memcg_params.work_fn = __kmemcg_cache_deactivate_after_rcu;
        call_rcu(&s->memcg_params.rcu_head, kmemcg_rcufn);
+unlock:
+       spin_unlock_irq(&memcg_kmem_wq_lock);
 }
 
 void memcg_deactivate_kmem_caches(struct mem_cgroup *memcg)
@@ -851,9 +860,9 @@ static int shutdown_memcg_caches(struct kmem_cache *s)
 
 static void flush_memcg_workqueue(struct kmem_cache *s)
 {
-       mutex_lock(&slab_mutex);
+       spin_lock_irq(&memcg_kmem_wq_lock);
        s->memcg_params.dying = true;
-       mutex_unlock(&slab_mutex);
+       spin_unlock_irq(&memcg_kmem_wq_lock);
 
        /*
         * SLAB and SLUB deactivate the kmem_caches through call_rcu. Make