diff options
author | Tejun Heo <tj@kernel.org> | 2012-03-05 16:15:15 -0500 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2012-03-06 15:27:23 -0500 |
commit | 1adaf3dde37a8b9b59ea59c5f58fed7761178383 (patch) | |
tree | e4a46485b1bf0370aa41a5b9a8f138fba34c9d23 /block/cfq-iosched.c | |
parent | 0381411e4b1a52cee134eb73750e5e3cc1155d09 (diff) |
blkcg: move refcnt to blkcg core
Currently, blkcg policy implementations manage blkg refcnt duplicating
mostly identical code in both policies. This patch moves refcnt to
blkg and let blkcg core handle refcnt and freeing of blkgs.
* cfq blkgs now also get freed via RCU.
* cfq blkgs lose RB_EMPTY_ROOT() sanity check on blkg free. If
necessary, we can add blkio_exit_group_fn() to resurrect this.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r-- | block/cfq-iosched.c | 58 |
1 files changed, 10 insertions, 48 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index c7449db52a86..86980023339a 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -210,7 +210,6 @@ struct cfq_group { | |||
210 | enum wl_prio_t saved_serving_prio; | 210 | enum wl_prio_t saved_serving_prio; |
211 | #ifdef CONFIG_CFQ_GROUP_IOSCHED | 211 | #ifdef CONFIG_CFQ_GROUP_IOSCHED |
212 | struct hlist_node cfqd_node; | 212 | struct hlist_node cfqd_node; |
213 | int ref; | ||
214 | #endif | 213 | #endif |
215 | /* number of requests that are on the dispatch list or inside driver */ | 214 | /* number of requests that are on the dispatch list or inside driver */ |
216 | int dispatched; | 215 | int dispatched; |
@@ -1071,14 +1070,6 @@ static void cfq_init_blkio_group(struct blkio_group *blkg) | |||
1071 | 1070 | ||
1072 | cfq_init_cfqg_base(cfqg); | 1071 | cfq_init_cfqg_base(cfqg); |
1073 | cfqg->weight = blkg->blkcg->weight; | 1072 | cfqg->weight = blkg->blkcg->weight; |
1074 | |||
1075 | /* | ||
1076 | * Take the initial reference that will be released on destroy | ||
1077 | * This can be thought of a joint reference by cgroup and | ||
1078 | * elevator which will be dropped by either elevator exit | ||
1079 | * or cgroup deletion path depending on who is exiting first. | ||
1080 | */ | ||
1081 | cfqg->ref = 1; | ||
1082 | } | 1073 | } |
1083 | 1074 | ||
1084 | /* | 1075 | /* |
@@ -1105,12 +1096,6 @@ static struct cfq_group *cfq_lookup_create_cfqg(struct cfq_data *cfqd, | |||
1105 | return cfqg; | 1096 | return cfqg; |
1106 | } | 1097 | } |
1107 | 1098 | ||
1108 | static inline struct cfq_group *cfq_ref_get_cfqg(struct cfq_group *cfqg) | ||
1109 | { | ||
1110 | cfqg->ref++; | ||
1111 | return cfqg; | ||
1112 | } | ||
1113 | |||
1114 | static void cfq_link_cfqq_cfqg(struct cfq_queue *cfqq, struct cfq_group *cfqg) | 1099 | static void cfq_link_cfqq_cfqg(struct cfq_queue *cfqq, struct cfq_group *cfqg) |
1115 | { | 1100 | { |
1116 | /* Currently, all async queues are mapped to root group */ | 1101 | /* Currently, all async queues are mapped to root group */ |
@@ -1119,28 +1104,7 @@ static void cfq_link_cfqq_cfqg(struct cfq_queue *cfqq, struct cfq_group *cfqg) | |||
1119 | 1104 | ||
1120 | cfqq->cfqg = cfqg; | 1105 | cfqq->cfqg = cfqg; |
1121 | /* cfqq reference on cfqg */ | 1106 | /* cfqq reference on cfqg */ |
1122 | cfqq->cfqg->ref++; | 1107 | blkg_get(cfqg_to_blkg(cfqg)); |
1123 | } | ||
1124 | |||
1125 | static void cfq_put_cfqg(struct cfq_group *cfqg) | ||
1126 | { | ||
1127 | struct blkio_group *blkg = cfqg_to_blkg(cfqg); | ||
1128 | struct cfq_rb_root *st; | ||
1129 | int i, j; | ||
1130 | |||
1131 | BUG_ON(cfqg->ref <= 0); | ||
1132 | cfqg->ref--; | ||
1133 | if (cfqg->ref) | ||
1134 | return; | ||
1135 | |||
1136 | /* release the extra blkcg reference this blkg has been holding */ | ||
1137 | css_put(&blkg->blkcg->css); | ||
1138 | |||
1139 | for_each_cfqg_st(cfqg, i, j, st) | ||
1140 | BUG_ON(!RB_EMPTY_ROOT(&st->rb)); | ||
1141 | free_percpu(blkg->stats_cpu); | ||
1142 | kfree(blkg->pd); | ||
1143 | kfree(blkg); | ||
1144 | } | 1108 | } |
1145 | 1109 | ||
1146 | static void cfq_destroy_cfqg(struct cfq_data *cfqd, struct cfq_group *cfqg) | 1110 | static void cfq_destroy_cfqg(struct cfq_data *cfqd, struct cfq_group *cfqg) |
@@ -1157,7 +1121,7 @@ static void cfq_destroy_cfqg(struct cfq_data *cfqd, struct cfq_group *cfqg) | |||
1157 | * Put the reference taken at the time of creation so that when all | 1121 | * Put the reference taken at the time of creation so that when all |
1158 | * queues are gone, group can be destroyed. | 1122 | * queues are gone, group can be destroyed. |
1159 | */ | 1123 | */ |
1160 | cfq_put_cfqg(cfqg); | 1124 | blkg_put(cfqg_to_blkg(cfqg)); |
1161 | } | 1125 | } |
1162 | 1126 | ||
1163 | static bool cfq_release_cfq_groups(struct cfq_data *cfqd) | 1127 | static bool cfq_release_cfq_groups(struct cfq_data *cfqd) |
@@ -1225,18 +1189,12 @@ static struct cfq_group *cfq_lookup_create_cfqg(struct cfq_data *cfqd, | |||
1225 | return cfqd->root_group; | 1189 | return cfqd->root_group; |
1226 | } | 1190 | } |
1227 | 1191 | ||
1228 | static inline struct cfq_group *cfq_ref_get_cfqg(struct cfq_group *cfqg) | ||
1229 | { | ||
1230 | return cfqg; | ||
1231 | } | ||
1232 | |||
1233 | static inline void | 1192 | static inline void |
1234 | cfq_link_cfqq_cfqg(struct cfq_queue *cfqq, struct cfq_group *cfqg) { | 1193 | cfq_link_cfqq_cfqg(struct cfq_queue *cfqq, struct cfq_group *cfqg) { |
1235 | cfqq->cfqg = cfqg; | 1194 | cfqq->cfqg = cfqg; |
1236 | } | 1195 | } |
1237 | 1196 | ||
1238 | static void cfq_release_cfq_groups(struct cfq_data *cfqd) {} | 1197 | static void cfq_release_cfq_groups(struct cfq_data *cfqd) {} |
1239 | static inline void cfq_put_cfqg(struct cfq_group *cfqg) {} | ||
1240 | 1198 | ||
1241 | #endif /* GROUP_IOSCHED */ | 1199 | #endif /* GROUP_IOSCHED */ |
1242 | 1200 | ||
@@ -2630,7 +2588,7 @@ static void cfq_put_queue(struct cfq_queue *cfqq) | |||
2630 | 2588 | ||
2631 | BUG_ON(cfq_cfqq_on_rr(cfqq)); | 2589 | BUG_ON(cfq_cfqq_on_rr(cfqq)); |
2632 | kmem_cache_free(cfq_pool, cfqq); | 2590 | kmem_cache_free(cfq_pool, cfqq); |
2633 | cfq_put_cfqg(cfqg); | 2591 | blkg_put(cfqg_to_blkg(cfqg)); |
2634 | } | 2592 | } |
2635 | 2593 | ||
2636 | static void cfq_put_cooperator(struct cfq_queue *cfqq) | 2594 | static void cfq_put_cooperator(struct cfq_queue *cfqq) |
@@ -3382,7 +3340,7 @@ static void cfq_put_request(struct request *rq) | |||
3382 | cfqq->allocated[rw]--; | 3340 | cfqq->allocated[rw]--; |
3383 | 3341 | ||
3384 | /* Put down rq reference on cfqg */ | 3342 | /* Put down rq reference on cfqg */ |
3385 | cfq_put_cfqg(RQ_CFQG(rq)); | 3343 | blkg_put(cfqg_to_blkg(RQ_CFQG(rq))); |
3386 | rq->elv.priv[0] = NULL; | 3344 | rq->elv.priv[0] = NULL; |
3387 | rq->elv.priv[1] = NULL; | 3345 | rq->elv.priv[1] = NULL; |
3388 | 3346 | ||
@@ -3477,8 +3435,9 @@ new_queue: | |||
3477 | cfqq->allocated[rw]++; | 3435 | cfqq->allocated[rw]++; |
3478 | 3436 | ||
3479 | cfqq->ref++; | 3437 | cfqq->ref++; |
3438 | blkg_get(cfqg_to_blkg(cfqq->cfqg)); | ||
3480 | rq->elv.priv[0] = cfqq; | 3439 | rq->elv.priv[0] = cfqq; |
3481 | rq->elv.priv[1] = cfq_ref_get_cfqg(cfqq->cfqg); | 3440 | rq->elv.priv[1] = cfqq->cfqg; |
3482 | spin_unlock_irq(q->queue_lock); | 3441 | spin_unlock_irq(q->queue_lock); |
3483 | return 0; | 3442 | return 0; |
3484 | } | 3443 | } |
@@ -3676,8 +3635,11 @@ static int cfq_init_queue(struct request_queue *q) | |||
3676 | */ | 3635 | */ |
3677 | cfq_init_cfqq(cfqd, &cfqd->oom_cfqq, 1, 0); | 3636 | cfq_init_cfqq(cfqd, &cfqd->oom_cfqq, 1, 0); |
3678 | cfqd->oom_cfqq.ref++; | 3637 | cfqd->oom_cfqq.ref++; |
3638 | |||
3639 | spin_lock_irq(q->queue_lock); | ||
3679 | cfq_link_cfqq_cfqg(&cfqd->oom_cfqq, cfqd->root_group); | 3640 | cfq_link_cfqq_cfqg(&cfqd->oom_cfqq, cfqd->root_group); |
3680 | cfq_put_cfqg(cfqd->root_group); | 3641 | blkg_put(cfqg_to_blkg(cfqd->root_group)); |
3642 | spin_unlock_irq(q->queue_lock); | ||
3681 | 3643 | ||
3682 | init_timer(&cfqd->idle_slice_timer); | 3644 | init_timer(&cfqd->idle_slice_timer); |
3683 | cfqd->idle_slice_timer.function = cfq_idle_slice_timer; | 3645 | cfqd->idle_slice_timer.function = cfq_idle_slice_timer; |