From: Philippe Elie <phil.el@wanadoo.fr>

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;

_