aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorJens Axboe <jaxboe@fusionio.com>2011-04-19 03:10:35 -0400
committerJens Axboe <jaxboe@fusionio.com>2011-04-19 03:10:35 -0400
commit5f45c69589b7d2953584e6cd0b31e35dbe960ad0 (patch)
tree7f920cebcbbe6a1435975e355cee15289ddbc428 /block
parentbd900d4580107c899d43b262fbbd995f11097a43 (diff)
cfq-iosched: read_lock() does not always imply rcu_read_lock()
For some configurations of CONFIG_PREEMPT that is not true. So get rid of __call_for_each_cic() and always uses the explicitly rcu_read_lock() protected call_for_each_cic() instead. This fixes a potential bug related to IO scheduler removal or online switching. Thanks to Paul McKenney for clarifying this. Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Diffstat (limited to 'block')
-rw-r--r--block/cfq-iosched.c20
1 files changed, 6 insertions, 14 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 46b0a1d1d925..5b52011e3a40 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -2582,28 +2582,20 @@ static void cfq_put_queue(struct cfq_queue *cfqq)
2582} 2582}
2583 2583
2584/* 2584/*
2585 * Must always be called with the rcu_read_lock() held 2585 * Call func for each cic attached to this ioc.
2586 */ 2586 */
2587static void 2587static void
2588__call_for_each_cic(struct io_context *ioc, 2588call_for_each_cic(struct io_context *ioc,
2589 void (*func)(struct io_context *, struct cfq_io_context *)) 2589 void (*func)(struct io_context *, struct cfq_io_context *))
2590{ 2590{
2591 struct cfq_io_context *cic; 2591 struct cfq_io_context *cic;
2592 struct hlist_node *n; 2592 struct hlist_node *n;
2593 2593
2594 rcu_read_lock();
2595
2594 hlist_for_each_entry_rcu(cic, n, &ioc->cic_list, cic_list) 2596 hlist_for_each_entry_rcu(cic, n, &ioc->cic_list, cic_list)
2595 func(ioc, cic); 2597 func(ioc, cic);
2596}
2597 2598
2598/*
2599 * Call func for each cic attached to this ioc.
2600 */
2601static void
2602call_for_each_cic(struct io_context *ioc,
2603 void (*func)(struct io_context *, struct cfq_io_context *))
2604{
2605 rcu_read_lock();
2606 __call_for_each_cic(ioc, func);
2607 rcu_read_unlock(); 2599 rcu_read_unlock();
2608} 2600}
2609 2601
@@ -2664,7 +2656,7 @@ static void cfq_free_io_context(struct io_context *ioc)
2664 * should be ok to iterate over the known list, we will see all cic's 2656 * should be ok to iterate over the known list, we will see all cic's
2665 * since no new ones are added. 2657 * since no new ones are added.
2666 */ 2658 */
2667 __call_for_each_cic(ioc, cic_free_func); 2659 call_for_each_cic(ioc, cic_free_func);
2668} 2660}
2669 2661
2670static void cfq_put_cooperator(struct cfq_queue *cfqq) 2662static void cfq_put_cooperator(struct cfq_queue *cfqq)