diff options
author | Jens Axboe <jaxboe@fusionio.com> | 2011-04-19 03:10:35 -0400 |
---|---|---|
committer | Jens Axboe <jaxboe@fusionio.com> | 2011-04-19 03:10:35 -0400 |
commit | 5f45c69589b7d2953584e6cd0b31e35dbe960ad0 (patch) | |
tree | 7f920cebcbbe6a1435975e355cee15289ddbc428 | |
parent | bd900d4580107c899d43b262fbbd995f11097a43 (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>
-rw-r--r-- | block/cfq-iosched.c | 20 |
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 | */ |
2587 | static void | 2587 | static void |
2588 | __call_for_each_cic(struct io_context *ioc, | 2588 | call_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 | */ | ||
2601 | static void | ||
2602 | call_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 | ||
2670 | static void cfq_put_cooperator(struct cfq_queue *cfqq) | 2662 | static void cfq_put_cooperator(struct cfq_queue *cfqq) |