lkml.org 
[lkml]   [2005]   [Sep]   [20]   [last100]   RSS Feed
Views: [more markup]  [less markup]  [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
DateMon, 19 Sep 2005 14:20:03 -0700 (PDT)
FromChristoph Lameter <>
SubjectRe: 2.6.14-rc1-git-now still dying in mm/slab - this time line 1849
On Mon, 19 Sep 2005, Andrew Morton wrote:

> 	list_for_each(walk, &cache_chain) {
> 		kmem_cache_t *searchp;
> 		struct list_head* p;
> 		int tofree;
> 		struct slab *slabp;
> 
> 		searchp = list_entry(walk, kmem_cache_t, next);
> 
> 		if (searchp->flags & SLAB_NO_REAP)
> 			goto next;
> 
> 		check_irq_on();
> 
> 		l3 = searchp->nodelists[numa_node_id()];
> 		if (l3->alien)
> 			drain_alien_cache(searchp, l3);
> ->preempt here
> 		spin_lock_irq(&l3->list_lock);
> 
> 		drain_array_locked(searchp, ac_data(searchp), 0,
> 				numa_node_id());
> ->oops, wrong node.

This is called from keventd which exists per processor. Hmmm... This looks 
as if it can change processors after all but the slab allocator depends on 
it running on the right processor. So does the page allocator. sigh. What 
is the point of having per processor workqueues if they do not stay on 
the assigned processor?

The fast fix for this case is to get the node number once and then use it 
consistently. But we really need to audit the slab and page allocator for 
additional cases like this or disable preempt and check for the right 
processor in cache_reap().

Index: linux-2.6/mm/slab.c
===================================================================
--- linux-2.6.orig/mm/slab.c	2005-09-19 14:10:33.489800899 -0700
+++ linux-2.6/mm/slab.c	2005-09-19 14:10:44.555105862 -0700
@@ -3262,6 +3262,7 @@
 {
 	struct list_head *walk;
 	struct kmem_list3 *l3;
+	int node = numa_node_id();
 
 	if (down_trylock(&cache_chain_sem)) {
 		/* Give up. Setup the next iteration. */
@@ -3282,13 +3283,13 @@
 
 		check_irq_on();
 
-		l3 = searchp->nodelists[numa_node_id()];
+		l3 = searchp->nodelists[node];
 		if (l3->alien)
 			drain_alien_cache(searchp, l3);
 		spin_lock_irq(&l3->list_lock);
 
 		drain_array_locked(searchp, ac_data(searchp), 0,
-				numa_node_id());
+				node);
 
 		if (time_after(l3->next_reap, jiffies))
 			goto next_unlock;
@@ -3297,7 +3298,7 @@
 
 		if (l3->shared)
 			drain_array_locked(searchp, l3->shared, 0,
-				numa_node_id());
+				node);
 
 		if (l3->free_touched) {
 			l3->free_touched = 0;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
\
 
 \ /
  Last update: 2005-09-20 12:03    [from the cache]
©2003-2008