]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
fix RCU-callback-after-kmem_cache_destroy problem in sl[aou]b
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Thu, 25 Jun 2009 19:31:37 +0000 (12:31 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 30 Jul 2009 21:39:04 +0000 (14:39 -0700)
commit 7ed9f7e5db58c6e8c2b4b738a75d5dcd8e17aad5 upstream.

Jesper noted that kmem_cache_destroy() invokes synchronize_rcu() rather than
rcu_barrier() in the SLAB_DESTROY_BY_RCU case, which could result in RCU
callbacks accessing a kmem_cache after it had been destroyed.

Acked-by: Matt Mackall <mpm@selenic.com>
Reported-by: Jesper Dangaard Brouer <hawk@comx.dk>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
mm/slab.c
mm/slob.c
mm/slub.c

index 9a90b00d2f9140e2aaa67ecb949e33d89431e9c5..021d69fec164f95377a1f4bc7a884dbd0ea84dcc 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -2592,7 +2592,7 @@ void kmem_cache_destroy(struct kmem_cache *cachep)
        }
 
        if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU))
-               synchronize_rcu();
+               rcu_barrier();
 
        __kmem_cache_destroy(cachep);
        mutex_unlock(&cache_chain_mutex);
index f92e66d558bd3608f5c758d7b7c39748cf936f51..c80d982a6f5c929159b08aa48823b692e0e464aa 100644 (file)
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -590,6 +590,8 @@ EXPORT_SYMBOL(kmem_cache_create);
 
 void kmem_cache_destroy(struct kmem_cache *c)
 {
+       if (c->flags & SLAB_DESTROY_BY_RCU)
+               rcu_barrier();
        slob_free(c, sizeof(struct kmem_cache));
 }
 EXPORT_SYMBOL(kmem_cache_destroy);
index 65ffda5934b09b8220e9a00332945dc19ba88de6..253016d3cb4ce1919283d8e1ba4c7a1149bb52f7 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2490,6 +2490,8 @@ static inline int kmem_cache_close(struct kmem_cache *s)
  */
 void kmem_cache_destroy(struct kmem_cache *s)
 {
+       if (s->flags & SLAB_DESTROY_BY_RCU)
+               rcu_barrier();
        down_write(&slub_lock);
        s->refcount--;
        if (!s->refcount) {