Index: linux-2.6.16-rc5-mm2/mm/slab.c =================================================================== --- linux-2.6.16-rc5-mm2.orig/mm/slab.c 2006-03-03 17:21:18.000000000 -0800 +++ linux-2.6.16-rc5-mm2/mm/slab.c 2006-03-03 17:34:39.000000000 -0800 @@ -3490,10 +3490,21 @@ static int do_tune_cpucache(struct kmem_ if (!ccold) continue; - local_irq_disable(); + + /* + * Local interrupts must be disabled only for + * this node because the list_lock may be obtained + * in an interrupt context. + */ + if (node == numa_node_id()) + local_irq_disable(); + free_block_lock(cachep, cachep->nodelists[node], ccold->entry, ccold->avail); - local_irq_enable(); + + if (node == numa_node_id()) + local_irq_enable(); + kfree(ccold); } @@ -3579,9 +3590,18 @@ void drain_array(struct kmem_cache *cach tofree = force ? ac->avail : (ac->limit + 4) / 5; if (tofree > ac->avail) tofree = (ac->avail + 1) / 2; - local_irq_disable(); + /* + * Freeing to the local node also requires that + * interrupts be disabled. + */ + if (node == numa_node_id()) + local_irq_disable(); + free_block_lock(cachep, l3, ac->entry, tofree); - local_irq_enable(); + + if (node == numa_node_id()) + local_irq_enable(); + ac->avail -= tofree; memmove(ac->entry, &(ac->entry[tofree]), sizeof(void *) * ac->avail);