From: Joonsoo Kim <iamjoonsoo.kim@xxxxxxx> 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@xxxxxxx> --- 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 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@xxxxxxxxx. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"dont@xxxxxxxxx"> email@xxxxxxxxx </a>