aboutsummaryrefslogtreecommitdiffstats
path: root/block/cfq-iosched.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-01-09 11:05:11 -0500
committerTejun Heo <tj@kernel.org>2013-01-09 11:05:11 -0500
commit7918ffb5b83e3373206ada84873c674fbddf61cc (patch)
treed7b2fe17efe9453fbb1afbfad8c7fc0e7a6bb01b /block/cfq-iosched.c
parente71357e118bdd4057e3bc020b9d80fecdd08f588 (diff)
cfq-iosched: implement cfq_group->nr_active and ->children_weight
To prepare for blkcg hierarchy support, add cfqg->nr_active and ->children_weight. cfqg->nr_active counts the number of active cfqgs at the cfqg's level and ->children_weight is sum of weights of those cfqgs. The level covers itself (cfqg->leaf_weight) and immediate children. The two values are updated when a cfqg enters and leaves the group service tree. Unless the hierarchy is very deep, the added overhead should be negligible. Currently, the parent is determined using cfqg_flat_parent() which makes the root cfqg the parent of all other cfqgs. This is to make the transition to hierarchy-aware scheduling gradual. Scheduling logic will be converted to use cfqg->children_weight without actually changing the behavior. When everything is ready, blkcg_weight_parent() will be replaced with proper parent function. This patch doesn't introduce any behavior chagne. v2: s/cfqg->level_weight/cfqg->children_weight/ as per Vivek. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Vivek Goyal <vgoyal@redhat.com>
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r--block/cfq-iosched.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 175218d66d67..7701c3fe49b9 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -225,6 +225,18 @@ struct cfq_group {
225 u64 vdisktime; 225 u64 vdisktime;
226 226
227 /* 227 /*
228 * The number of active cfqgs and sum of their weights under this
229 * cfqg. This covers this cfqg's leaf_weight and all children's
230 * weights, but does not cover weights of further descendants.
231 *
232 * If a cfqg is on the service tree, it's active. An active cfqg
233 * also activates its parent and contributes to the children_weight
234 * of the parent.
235 */
236 int nr_active;
237 unsigned int children_weight;
238
239 /*
228 * There are two weights - (internal) weight is the weight of this 240 * There are two weights - (internal) weight is the weight of this
229 * cfqg against the sibling cfqgs. leaf_weight is the wight of 241 * cfqg against the sibling cfqgs. leaf_weight is the wight of
230 * this cfqg against the child cfqgs. For the root cfqg, both 242 * this cfqg against the child cfqgs. For the root cfqg, both
@@ -583,6 +595,22 @@ static inline struct cfq_group *blkg_to_cfqg(struct blkcg_gq *blkg)
583 return pd_to_cfqg(blkg_to_pd(blkg, &blkcg_policy_cfq)); 595 return pd_to_cfqg(blkg_to_pd(blkg, &blkcg_policy_cfq));
584} 596}
585 597
598/*
599 * Determine the parent cfqg for weight calculation. Currently, cfqg
600 * scheduling is flat and the root is the parent of everyone else.
601 */
602static inline struct cfq_group *cfqg_flat_parent(struct cfq_group *cfqg)
603{
604 struct blkcg_gq *blkg = cfqg_to_blkg(cfqg);
605 struct cfq_group *root;
606
607 while (blkg->parent)
608 blkg = blkg->parent;
609 root = blkg_to_cfqg(blkg);
610
611 return root != cfqg ? root : NULL;
612}
613
586static inline void cfqg_get(struct cfq_group *cfqg) 614static inline void cfqg_get(struct cfq_group *cfqg)
587{ 615{
588 return blkg_get(cfqg_to_blkg(cfqg)); 616 return blkg_get(cfqg_to_blkg(cfqg));
@@ -683,6 +711,7 @@ static void cfq_pd_reset_stats(struct blkcg_gq *blkg)
683 711
684#else /* CONFIG_CFQ_GROUP_IOSCHED */ 712#else /* CONFIG_CFQ_GROUP_IOSCHED */
685 713
714static inline struct cfq_group *cfqg_flat_parent(struct cfq_group *cfqg) { return NULL; }
686static inline void cfqg_get(struct cfq_group *cfqg) { } 715static inline void cfqg_get(struct cfq_group *cfqg) { }
687static inline void cfqg_put(struct cfq_group *cfqg) { } 716static inline void cfqg_put(struct cfq_group *cfqg) { }
688 717
@@ -1208,11 +1237,33 @@ cfq_update_group_weight(struct cfq_group *cfqg)
1208static void 1237static void
1209cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg) 1238cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg)
1210{ 1239{
1240 struct cfq_group *pos = cfqg;
1241 bool propagate;
1242
1243 /* add to the service tree */
1211 BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node)); 1244 BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node));
1212 1245
1213 cfq_update_group_weight(cfqg); 1246 cfq_update_group_weight(cfqg);
1214 __cfq_group_service_tree_add(st, cfqg); 1247 __cfq_group_service_tree_add(st, cfqg);
1215 st->total_weight += cfqg->weight; 1248 st->total_weight += cfqg->weight;
1249
1250 /*
1251 * Activate @cfqg and propagate activation upwards until we meet an
1252 * already activated node or reach root.
1253 */
1254 propagate = !pos->nr_active++;
1255 pos->children_weight += pos->leaf_weight;
1256
1257 while (propagate) {
1258 struct cfq_group *parent = cfqg_flat_parent(pos);
1259
1260 if (!parent)
1261 break;
1262
1263 propagate = !parent->nr_active++;
1264 parent->children_weight += pos->weight;
1265 pos = parent;
1266 }
1216} 1267}
1217 1268
1218static void 1269static void
@@ -1243,6 +1294,31 @@ cfq_group_notify_queue_add(struct cfq_data *cfqd, struct cfq_group *cfqg)
1243static void 1294static void
1244cfq_group_service_tree_del(struct cfq_rb_root *st, struct cfq_group *cfqg) 1295cfq_group_service_tree_del(struct cfq_rb_root *st, struct cfq_group *cfqg)
1245{ 1296{
1297 struct cfq_group *pos = cfqg;
1298 bool propagate;
1299
1300 /*
1301 * Undo activation from cfq_group_service_tree_add(). Deactivate
1302 * @cfqg and propagate deactivation upwards.
1303 */
1304 propagate = !--pos->nr_active;
1305 pos->children_weight -= pos->leaf_weight;
1306
1307 while (propagate) {
1308 struct cfq_group *parent = cfqg_flat_parent(pos);
1309
1310 /* @pos has 0 nr_active at this point */
1311 WARN_ON_ONCE(pos->children_weight);
1312
1313 if (!parent)
1314 break;
1315
1316 propagate = !--parent->nr_active;
1317 parent->children_weight -= pos->weight;
1318 pos = parent;
1319 }
1320
1321 /* remove from the service tree */
1246 st->total_weight -= cfqg->weight; 1322 st->total_weight -= cfqg->weight;
1247 if (!RB_EMPTY_NODE(&cfqg->rb_node)) 1323 if (!RB_EMPTY_NODE(&cfqg->rb_node))
1248 cfq_rb_erase(&cfqg->rb_node, st); 1324 cfq_rb_erase(&cfqg->rb_node, st);