Index: linux-2.6.16-rc4-mm2/mm/slab.c =================================================================== --- linux-2.6.16-rc4-mm2.orig/mm/slab.c 2006-02-28 19:04:31.000000000 -0800 +++ linux-2.6.16-rc4-mm2/mm/slab.c 2006-02-28 19:09:27.000000000 -0800 @@ -942,6 +942,10 @@ static void free_alien_cache(struct arra kfree(ac_ptr); } +/* + * Drain one alien cache. Enter with the ac->lock already + * acquired. Leave without it. + */ static void __drain_alien_cache(struct kmem_cache *cachep, struct array_cache *ac, int node) { @@ -953,6 +957,7 @@ static void __drain_alien_cache(struct k ac->avail = 0; spin_unlock(&rl3->list_lock); } + spin_unlock(&ac->lock); } /* @@ -967,7 +972,6 @@ static void reap_alien(struct kmem_cache if (ac && ac->avail) { spin_lock_irq(&ac->lock); __drain_alien_cache(cachep, ac, node); - spin_unlock_irq(&ac->lock); } } } @@ -984,7 +988,6 @@ static void drain_alien_cache(struct kme if (ac) { spin_lock_irqsave(&ac->lock, flags); __drain_alien_cache(cachep, ac, i); - spin_unlock_irqrestore(&ac->lock, flags); } } } @@ -3070,11 +3073,10 @@ void kmem_cache_free(struct kmem_cache * if (l3->alien && l3->alien[nodeid]) { alien = l3->alien[nodeid]; spin_lock(&alien->lock); + alien->entry[alien->avail++] = objp; if (unlikely(alien->avail == alien->limit)) __drain_alien_cache(cachep, alien, nodeid); - alien->entry[alien->avail++] = objp; - spin_unlock(&alien->lock); } else { spin_lock(&(cachep->nodelists[nodeid])-> list_lock);