diff options
author | Jens Axboe <jens.axboe@oracle.com> | 2009-12-06 03:54:19 -0500 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2009-12-06 03:54:19 -0500 |
commit | bb729bc98c0f3e6a898d8730df3e2830bf68751a (patch) | |
tree | f2170f8f688a7c7f813168a6c8c757087934c094 /block | |
parent | 846954b0a32f4ae953e082eabd178e7a98dd2efd (diff) |
cfq-iosched: use call_rcu() instead of doing grace period stall on queue exit
After the merge of the IO controller patches, booting on my megaraid
box ran much slower. Vivek Goyal traced it down to megaraid discovery
creating tons of devices, each suffering a grace period when they later
kill that queue (if no device is found).
So lets use call_rcu() to batch these deferred frees, instead of taking
the grace period hit for each one.
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block')
-rw-r--r-- | block/cfq-iosched.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 78f4829895bd..3815f9789b6a 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -287,6 +287,7 @@ struct cfq_data { | |||
287 | 287 | ||
288 | /* List of cfq groups being managed on this device*/ | 288 | /* List of cfq groups being managed on this device*/ |
289 | struct hlist_head cfqg_list; | 289 | struct hlist_head cfqg_list; |
290 | struct rcu_head rcu; | ||
290 | }; | 291 | }; |
291 | 292 | ||
292 | static struct cfq_group *cfq_get_next_cfqg(struct cfq_data *cfqd); | 293 | static struct cfq_group *cfq_get_next_cfqg(struct cfq_data *cfqd); |
@@ -3601,6 +3602,11 @@ static void cfq_put_async_queues(struct cfq_data *cfqd) | |||
3601 | cfq_put_queue(cfqd->async_idle_cfqq); | 3602 | cfq_put_queue(cfqd->async_idle_cfqq); |
3602 | } | 3603 | } |
3603 | 3604 | ||
3605 | static void cfq_cfqd_free(struct rcu_head *head) | ||
3606 | { | ||
3607 | kfree(container_of(head, struct cfq_data, rcu)); | ||
3608 | } | ||
3609 | |||
3604 | static void cfq_exit_queue(struct elevator_queue *e) | 3610 | static void cfq_exit_queue(struct elevator_queue *e) |
3605 | { | 3611 | { |
3606 | struct cfq_data *cfqd = e->elevator_data; | 3612 | struct cfq_data *cfqd = e->elevator_data; |
@@ -3630,8 +3636,7 @@ static void cfq_exit_queue(struct elevator_queue *e) | |||
3630 | cfq_shutdown_timer_wq(cfqd); | 3636 | cfq_shutdown_timer_wq(cfqd); |
3631 | 3637 | ||
3632 | /* Wait for cfqg->blkg->key accessors to exit their grace periods. */ | 3638 | /* Wait for cfqg->blkg->key accessors to exit their grace periods. */ |
3633 | synchronize_rcu(); | 3639 | call_rcu(&cfqd->rcu, cfq_cfqd_free); |
3634 | kfree(cfqd); | ||
3635 | } | 3640 | } |
3636 | 3641 | ||
3637 | static void *cfq_init_queue(struct request_queue *q) | 3642 | static void *cfq_init_queue(struct request_queue *q) |
@@ -3706,6 +3711,7 @@ static void *cfq_init_queue(struct request_queue *q) | |||
3706 | cfqd->cfq_group_isolation = 0; | 3711 | cfqd->cfq_group_isolation = 0; |
3707 | cfqd->hw_tag = -1; | 3712 | cfqd->hw_tag = -1; |
3708 | cfqd->last_end_sync_rq = jiffies; | 3713 | cfqd->last_end_sync_rq = jiffies; |
3714 | INIT_RCU_HEAD(&cfqd->rcu); | ||
3709 | return cfqd; | 3715 | return cfqd; |
3710 | } | 3716 | } |
3711 | 3717 | ||