Messages in this thread Patch in this message | | | From | js1304@gmail ... | Subject | [PATCH 01/11] mm/slab: hold a slab_mutex when calling __kmem_cache_shrink() | Date | Mon, 28 Mar 2016 14:26:51 +0900 |
| |
From: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Major kmem_cache metadata in slab subsystem is synchronized with the slab_mutex. In SLAB, if some of them is changed, node's shared array cache would be freed and re-populated. If __kmem_cache_shrink() is called at the same time, it will call drain_array() with n->shared without holding node lock so problem can happen.
We can fix this small theoretical race condition by holding node lock in drain_array(), but, holding a slab_mutex in kmem_cache_shrink() looks more appropriate solution because stable state would make things less error-prone and this is not performance critical path.
In addtion, annotate on SLAB functions.
Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com> --- mm/slab.c | 2 ++ mm/slab_common.c | 4 ++++ 2 files changed, 6 insertions(+)
diff --git a/mm/slab.c b/mm/slab.c index a53a0f6..043606a 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2218,6 +2218,7 @@ static void do_drain(void *arg) ac->avail = 0; } +/* Should be called with slab_mutex to prevent from freeing shared array */ static void drain_cpu_caches(struct kmem_cache *cachep) { struct kmem_cache_node *n; @@ -3871,6 +3872,7 @@ skip_setup: * Drain an array if it contains any elements taking the node lock only if * necessary. Note that the node listlock also protects the array_cache * if drain_array() is used on the shared array. + * Should be called with slab_mutex to prevent from freeing shared array. */ static void drain_array(struct kmem_cache *cachep, struct kmem_cache_node *n, struct array_cache *ac, int force, int node) diff --git a/mm/slab_common.c b/mm/slab_common.c index a65dad7..5bed565 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -755,7 +755,11 @@ int kmem_cache_shrink(struct kmem_cache *cachep) get_online_cpus(); get_online_mems(); kasan_cache_shrink(cachep); + + mutex_lock(&slab_mutex); ret = __kmem_cache_shrink(cachep, false); + mutex_unlock(&slab_mutex); + put_online_mems(); put_online_cpus(); return ret; -- 1.9.1
| |