Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Jens Axboe
Date: Wednesday, May 28, 2008 - 5:44 am

On Wed, May 28 2008, Paul E. McKenney wrote:

Your reviews are ALWAYS greatly appreciated!


So that one was also OK, as Fabio pointed out. If you follow the
ioc_gone and user tracking, the:

        if (elv_ioc_count_read(ioc_count))
                wait_for_completion(ioc_gone);

also has the side effect of waiting for RCU callbacks calling
kmem_cache_free() to have finished as well.


It's in there, it now does:

        rcu_read_lock();
        cic = rcu_dereference(ioc->ioc_data);
        if (cic && cic->key == cfqd) {
                rcu_read_unlock();
                return cic;
        }
        ...

OK? Which is basically what remains of the patch now, except for the
comment additions. Oh, and the ioc->lock protecting setting of
->ioc_data as well. New version below. Alexey, care to give this a
spin? Seems your box is very well suited for finding RCU preempt
problems :-)


diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 4df3f05..d01b411 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -1142,6 +1142,9 @@ static void cfq_put_queue(struct cfq_queue *cfqq)
 	kmem_cache_free(cfq_pool, cfqq);
 }
 
+/*
+ * Must always be called with the rcu_read_lock() held
+ */
 static void
 __call_for_each_cic(struct io_context *ioc,
 		    void (*func)(struct io_context *, struct cfq_io_context *))
@@ -1197,6 +1200,11 @@ static void cic_free_func(struct io_context *ioc, struct cfq_io_context *cic)
 	cfq_cic_free(cic);
 }
 
+/*
+ * Must be called with rcu_read_lock() held or preemption otherwise disabled.
+ * Only two callers of this - ->dtor() which is called with the rcu_read_lock(),
+ * and ->trim() which is called with the task lock held
+ */
 static void cfq_free_io_context(struct io_context *ioc)
 {
 	/*
@@ -1502,20 +1510,24 @@ static struct cfq_io_context *
 cfq_cic_lookup(struct cfq_data *cfqd, struct io_context *ioc)
 {
 	struct cfq_io_context *cic;
+	unsigned long flags;
 	void *k;
 
 	if (unlikely(!ioc))
 		return NULL;
 
+	rcu_read_lock();
+
 	/*
 	 * we maintain a last-hit cache, to avoid browsing over the tree
 	 */
 	cic = rcu_dereference(ioc->ioc_data);
-	if (cic && cic->key == cfqd)
+	if (cic && cic->key == cfqd) {
+		rcu_read_unlock();
 		return cic;
+	}
 
 	do {
-		rcu_read_lock();
 		cic = radix_tree_lookup(&ioc->radix_root, (unsigned long) cfqd);
 		rcu_read_unlock();
 		if (!cic)
@@ -1524,10 +1536,13 @@ cfq_cic_lookup(struct cfq_data *cfqd, struct io_context *ioc)
 		k = cic->key;
 		if (unlikely(!k)) {
 			cfq_drop_dead_cic(cfqd, ioc, cic);
+			rcu_read_lock();
 			continue;
 		}
 
+		spin_lock_irqsave(&ioc->lock, flags);
 		rcu_assign_pointer(ioc->ioc_data, cic);
+		spin_unlock_irqrestore(&ioc->lock, flags);
 		break;
 	} while (1);
 
@@ -2134,6 +2149,10 @@ static void *cfq_init_queue(struct request_queue *q)
 
 static void cfq_slab_kill(void)
 {
+	/*
+	 * Caller already ensured that pending RCU callbacks are completed,
+	 * so we should have no busy allocations at this point.
+	 */
 	if (cfq_pool)
 		kmem_cache_destroy(cfq_pool);
 	if (cfq_ioc_pool)
@@ -2292,6 +2311,11 @@ static void __exit cfq_exit(void)
 	ioc_gone = &all_gone;
 	/* ioc_gone's update must be visible before reading ioc_count */
 	smp_wmb();
+
+	/*
+	 * this also protects us from entering cfq_slab_kill() with
+	 * pending RCU callbacks
+	 */
 	if (elv_ioc_count_read(ioc_count))
 		wait_for_completion(ioc_gone);
 	cfq_slab_kill();

-- 
Jens Axboe

--
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
2.6.25-$sha1: RIP call_for_each_cic+0x25/0x50, Alexey Dobriyan, (Sun Apr 27, 3:55 pm)
Re: 2.6.25-$sha1: RIP call_for_each_cic+0x25/0x50, Andrew Morton, (Mon Apr 28, 5:01 am)
Re: 2.6.25-$sha1: RIP call_for_each_cic+0x25/0x50, Jens Axboe, (Mon Apr 28, 5:04 am)
Re: 2.6.25-$sha1: RIP call_for_each_cic+0x25/0x50, Alexey Dobriyan, (Mon Apr 28, 12:55 pm)
Re: 2.6.25-$sha1: RIP call_for_each_cic+0x25/0x50, Alexey Dobriyan, (Mon Apr 28, 11:21 pm)
Re: 2.6.25-$sha1: RIP call_for_each_cic+0x25/0x50, Jens Axboe, (Tue Apr 29, 2:06 am)
Re: 2.6.25-$sha1: RIP call_for_each_cic+0x25/0x50, Alexey Dobriyan, (Wed Apr 30, 3:12 pm)
Re: 2.6.25-$sha1: RIP call_for_each_cic+0x25/0x50, Jens Axboe, (Sun May 4, 12:08 pm)
Re: 2.6.25-$sha1: RIP call_for_each_cic+0x25/0x50, Jens Axboe, (Sun May 4, 12:25 pm)
Re: 2.6.25-$sha1: RIP call_for_each_cic+0x25/0x50, Alexey Dobriyan, (Sun May 4, 1:15 pm)
Re: 2.6.25-$sha1: RIP call_for_each_cic+0x25/0x50, Alexey Dobriyan, (Sun May 4, 2:17 pm)
2.6.25-$sha1: RIP __call_for_each_cic+0x20/0x50, Alexey Dobriyan, (Sat May 10, 3:37 am)
2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Alexey Dobriyan, (Mon May 26, 10:27 pm)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Jens Axboe, (Tue May 27, 6:35 am)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Paul E. McKenney, (Tue May 27, 8:18 am)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Jens Axboe, (Wed May 28, 3:07 am)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Paul E. McKenney, (Wed May 28, 3:30 am)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Fabio Checconi, (Wed May 28, 4:52 am)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Jens Axboe, (Wed May 28, 4:58 am)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Jens Axboe, (Wed May 28, 5:44 am)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Paul E. McKenney, (Wed May 28, 6:20 am)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Paul E. McKenney, (Wed May 28, 9:38 pm)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Jens Axboe, (Wed May 28, 11:26 pm)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Jens Axboe, (Wed May 28, 11:42 pm)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Paul E. McKenney, (Thu May 29, 2:17 am)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Jens Axboe, (Thu May 29, 3:13 am)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Paul E. McKenney, (Thu May 29, 4:25 am)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Jens Axboe, (Thu May 29, 4:44 am)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Paul E. McKenney, (Thu May 29, 5:11 am)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Jens Axboe, (Thu May 29, 5:13 am)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Paul E. McKenney, (Fri May 30, 4:04 am)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Paul E. McKenney, (Fri May 30, 6:16 am)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Alexey Dobriyan, (Fri May 30, 11:34 am)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Paul E. McKenney, (Tue Jun 3, 8:31 pm)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Linus Torvalds, (Wed Jun 4, 11:32 am)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Paul E. McKenney, (Wed Jun 4, 9:23 pm)
Re: 2.6.26-rc4: RIP __call_for_each_cic+0x20/0x50, Paul E. McKenney, (Fri Jun 6, 7:49 am)