From: Philippe Elie kmem_cache_destroy() can fail with the following error: slab error in kmem_cache_destroy(): cache `xxx': Can't free all objects but the cache user really free'd all objects This is becasue drain_array_locked() only frees 80% of thge objects. Fix it by adding a parameter to drain_array_locked() telling it to drain 100% of the objects. mm/slab.c | 13 +++++++------ 1 files changed, 7 insertions(+), 6 deletions(-) diff -puN mm/slab.c~slab-drain-all-objects-fix mm/slab.c --- 25/mm/slab.c~slab-drain-all-objects-fix 2003-06-26 18:42:24.000000000 -0700 +++ 25-akpm/mm/slab.c 2003-06-26 18:42:24.000000000 -0700 @@ -1278,7 +1278,8 @@ static void smp_call_function_all_cpus(v } static void free_block (kmem_cache_t* cachep, void** objpp, int len); -static void drain_array_locked(kmem_cache_t* cachep, struct array_cache *ac); +static void drain_array_locked(kmem_cache_t* cachep, + struct array_cache *ac, int force); static void do_drain(void *arg) { @@ -1299,7 +1300,7 @@ static void drain_cpu_caches(kmem_cache_ check_irq_on(); spin_lock_irq(&cachep->spinlock); if (cachep->lists.shared) - drain_array_locked(cachep, cachep->lists.shared); + drain_array_locked(cachep, cachep->lists.shared, 1); spin_unlock_irq(&cachep->spinlock); } @@ -2342,7 +2343,8 @@ static void drain_array(kmem_cache_t *ca } } -static void drain_array_locked(kmem_cache_t *cachep, struct array_cache *ac) +static void drain_array_locked(kmem_cache_t *cachep, + struct array_cache *ac, int force) { int tofree; @@ -2350,7 +2352,7 @@ static void drain_array_locked(kmem_cach if (ac->touched) { ac->touched = 0; } else if (ac->avail) { - tofree = (ac->limit+4)/5; + tofree = force ? ac->avail : (ac->limit+4)/5; if (tofree > ac->avail) { tofree = (ac->avail+1)/2; } @@ -2361,7 +2363,6 @@ static void drain_array_locked(kmem_cach } } - /** * cache_reap - Reclaim memory from caches. * @@ -2409,7 +2410,7 @@ static inline void cache_reap (void) searchp->lists.next_reap = jiffies + REAPTIMEOUT_LIST3; if (searchp->lists.shared) - drain_array_locked(searchp, searchp->lists.shared); + drain_array_locked(searchp, searchp->lists.shared, 0); if (searchp->lists.free_touched) { searchp->lists.free_touched = 0; _