return nr_freed;
 }
 
-/* Called with slab_mutex held to protect against cpu hotplug */
-static int __cache_shrink(struct kmem_cache *cachep)
+int __kmem_cache_shrink(struct kmem_cache *cachep)
 {
        int ret = 0, i = 0;
        struct kmem_cache_node *n;
        return (ret ? 1 : 0);
 }
 
-/**
- * kmem_cache_shrink - Shrink a cache.
- * @cachep: The cache to shrink.
- *
- * Releases as many slabs as possible for a cache.
- * To help debugging, a zero exit status indicates all slabs were released.
- */
-int kmem_cache_shrink(struct kmem_cache *cachep)
-{
-       int ret;
-       BUG_ON(!cachep || in_interrupt());
-
-       get_online_cpus();
-       mutex_lock(&slab_mutex);
-       ret = __cache_shrink(cachep);
-       mutex_unlock(&slab_mutex);
-       put_online_cpus();
-       return ret;
-}
-EXPORT_SYMBOL(kmem_cache_shrink);
-
 int __kmem_cache_shutdown(struct kmem_cache *cachep)
 {
        int i;
        struct kmem_cache_node *n;
-       int rc = __cache_shrink(cachep);
+       int rc = __kmem_cache_shrink(cachep);
 
        if (rc)
                return rc;
 
 #define CACHE_CREATE_MASK (SLAB_CORE_FLAGS | SLAB_DEBUG_FLAGS | SLAB_CACHE_FLAGS)
 
 int __kmem_cache_shutdown(struct kmem_cache *);
+int __kmem_cache_shrink(struct kmem_cache *);
 void slab_kmem_cache_release(struct kmem_cache *);
 
 struct seq_file;
 
        int err;
 
        get_online_cpus();
+       get_online_mems();
+
        mutex_lock(&slab_mutex);
 
        err = kmem_cache_sanity_check(name, size);
 
 out_unlock:
        mutex_unlock(&slab_mutex);
+
+       put_online_mems();
        put_online_cpus();
 
        if (err) {
        char *cache_name;
 
        get_online_cpus();
+       get_online_mems();
+
        mutex_lock(&slab_mutex);
 
        /*
 
 out_unlock:
        mutex_unlock(&slab_mutex);
+
+       put_online_mems();
        put_online_cpus();
 }
 
 void kmem_cache_destroy(struct kmem_cache *s)
 {
        get_online_cpus();
+       get_online_mems();
+
        mutex_lock(&slab_mutex);
 
        s->refcount--;
 #else
        slab_kmem_cache_release(s);
 #endif
-       goto out_put_cpus;
+       goto out;
 
 out_unlock:
        mutex_unlock(&slab_mutex);
-out_put_cpus:
+out:
+       put_online_mems();
        put_online_cpus();
 }
 EXPORT_SYMBOL(kmem_cache_destroy);
 
+/**
+ * kmem_cache_shrink - Shrink a cache.
+ * @cachep: The cache to shrink.
+ *
+ * Releases as many slabs as possible for a cache.
+ * To help debugging, a zero exit status indicates all slabs were released.
+ */
+int kmem_cache_shrink(struct kmem_cache *cachep)
+{
+       int ret;
+
+       get_online_cpus();
+       get_online_mems();
+       ret = __kmem_cache_shrink(cachep);
+       put_online_mems();
+       put_online_cpus();
+       return ret;
+}
+EXPORT_SYMBOL(kmem_cache_shrink);
+
 int slab_is_available(void)
 {
        return slab_state >= UP;
 
        return 0;
 }
 
-int kmem_cache_shrink(struct kmem_cache *d)
+int __kmem_cache_shrink(struct kmem_cache *d)
 {
        return 0;
 }
-EXPORT_SYMBOL(kmem_cache_shrink);
 
 struct kmem_cache kmem_cache_boot = {
        .name = "kmem_cache",
 
  * being allocated from last increasing the chance that the last objects
  * are freed in them.
  */
-int kmem_cache_shrink(struct kmem_cache *s)
+int __kmem_cache_shrink(struct kmem_cache *s)
 {
        int node;
        int i;
        kfree(slabs_by_inuse);
        return 0;
 }
-EXPORT_SYMBOL(kmem_cache_shrink);
 
 static int slab_mem_going_offline_callback(void *arg)
 {
 
        mutex_lock(&slab_mutex);
        list_for_each_entry(s, &slab_caches, list)
-               kmem_cache_shrink(s);
+               __kmem_cache_shrink(s);
        mutex_unlock(&slab_mutex);
 
        return 0;