aboutsummaryrefslogtreecommitdiffstats
path: root/block/cfq-iosched.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2012-03-05 16:15:15 -0500
committerJens Axboe <axboe@kernel.dk>2012-03-06 15:27:23 -0500
commit1adaf3dde37a8b9b59ea59c5f58fed7761178383 (patch)
treee4a46485b1bf0370aa41a5b9a8f138fba34c9d23 /block/cfq-iosched.c
parent0381411e4b1a52cee134eb73750e5e3cc1155d09 (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.c58
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
1108static inline struct cfq_group *cfq_ref_get_cfqg(struct cfq_group *cfqg)
1109{
1110 cfqg->ref++;
1111 return cfqg;
1112}
1113
1114static void cfq_link_cfqq_cfqg(struct cfq_queue *cfqq, struct cfq_group *cfqg) 1099static 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
1125static 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
1146static void cfq_destroy_cfqg(struct cfq_data *cfqd, struct cfq_group *cfqg) 1110static 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
1163static bool cfq_release_cfq_groups(struct cfq_data *cfqd) 1127static 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
1228static inline struct cfq_group *cfq_ref_get_cfqg(struct cfq_group *cfqg)
1229{
1230 return cfqg;
1231}
1232
1233static inline void 1192static inline void
1234cfq_link_cfqq_cfqg(struct cfq_queue *cfqq, struct cfq_group *cfqg) { 1193cfq_link_cfqq_cfqg(struct cfq_queue *cfqq, struct cfq_group *cfqg) {
1235 cfqq->cfqg = cfqg; 1194 cfqq->cfqg = cfqg;
1236} 1195}
1237 1196
1238static void cfq_release_cfq_groups(struct cfq_data *cfqd) {} 1197static void cfq_release_cfq_groups(struct cfq_data *cfqd) {}
1239static 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
2636static void cfq_put_cooperator(struct cfq_queue *cfqq) 2594static 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;