aboutsummaryrefslogtreecommitdiffstats
path: root/block/cfq-iosched.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-01-09 11:05:10 -0500
committerTejun Heo <tj@kernel.org>2013-01-09 11:05:10 -0500
commite71357e118bdd4057e3bc020b9d80fecdd08f588 (patch)
treea26644afeb5efb7dcd5f2e8a59c32c1d509f8574 /block/cfq-iosched.c
parent3c547865902e9fc30dc15941f326fd8039c6628d (diff)
cfq-iosched: add leaf_weight
cfq blkcg is about to grow proper hierarchy handling, where a child blkg's weight would nest inside the parent's. This makes tasks in a blkg to compete against both tasks in the sibling blkgs and the tasks of child blkgs. We're gonna use the existing weight as the group weight which decides the blkg's weight against its siblings. This patch introduces a new weight - leaf_weight - which decides the weight of a blkg against the child blkgs. It's named leaf_weight because another way to look at it is that each internal blkg nodes have a hidden child leaf node which contains all its tasks and leaf_weight is the weight of the leaf node and handled the same as the weight of the child blkgs. This patch only adds leaf_weight fields and exposes it to userland. The new weight isn't actually used anywhere yet. Note that cfq-iosched currently offcially supports only single level hierarchy and root blkgs compete with the first level blkgs - ie. root weight is basically being used as leaf_weight. For root blkgs, the two weights are kept in sync for backward compatibility. v2: cfqd->root_group->leaf_weight initialization was missing from cfq_init_queue() causing divide by zero when !CONFIG_CFQ_GROUP_SCHED. Fix it. Reported by Fengguang. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Fengguang Wu <fengguang.wu@intel.com>
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r--block/cfq-iosched.c134
1 files changed, 126 insertions, 8 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index bc076f45ca46..175218d66d67 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -223,10 +223,21 @@ struct cfq_group {
223 223
224 /* group service_tree key */ 224 /* group service_tree key */
225 u64 vdisktime; 225 u64 vdisktime;
226
227 /*
228 * There are two weights - (internal) weight is the weight of this
229 * cfqg against the sibling cfqgs. leaf_weight is the wight of
230 * this cfqg against the child cfqgs. For the root cfqg, both
231 * weights are kept in sync for backward compatibility.
232 */
226 unsigned int weight; 233 unsigned int weight;
227 unsigned int new_weight; 234 unsigned int new_weight;
228 unsigned int dev_weight; 235 unsigned int dev_weight;
229 236
237 unsigned int leaf_weight;
238 unsigned int new_leaf_weight;
239 unsigned int dev_leaf_weight;
240
230 /* number of cfqq currently on this group */ 241 /* number of cfqq currently on this group */
231 int nr_cfqq; 242 int nr_cfqq;
232 243
@@ -1182,10 +1193,16 @@ static void
1182cfq_update_group_weight(struct cfq_group *cfqg) 1193cfq_update_group_weight(struct cfq_group *cfqg)
1183{ 1194{
1184 BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node)); 1195 BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node));
1196
1185 if (cfqg->new_weight) { 1197 if (cfqg->new_weight) {
1186 cfqg->weight = cfqg->new_weight; 1198 cfqg->weight = cfqg->new_weight;
1187 cfqg->new_weight = 0; 1199 cfqg->new_weight = 0;
1188 } 1200 }
1201
1202 if (cfqg->new_leaf_weight) {
1203 cfqg->leaf_weight = cfqg->new_leaf_weight;
1204 cfqg->new_leaf_weight = 0;
1205 }
1189} 1206}
1190 1207
1191static void 1208static void
@@ -1348,6 +1365,7 @@ static void cfq_pd_init(struct blkcg_gq *blkg)
1348 1365
1349 cfq_init_cfqg_base(cfqg); 1366 cfq_init_cfqg_base(cfqg);
1350 cfqg->weight = blkg->blkcg->cfq_weight; 1367 cfqg->weight = blkg->blkcg->cfq_weight;
1368 cfqg->leaf_weight = blkg->blkcg->cfq_leaf_weight;
1351} 1369}
1352 1370
1353/* 1371/*
@@ -1404,6 +1422,26 @@ static int cfqg_print_weight_device(struct cgroup *cgrp, struct cftype *cft,
1404 return 0; 1422 return 0;
1405} 1423}
1406 1424
1425static u64 cfqg_prfill_leaf_weight_device(struct seq_file *sf,
1426 struct blkg_policy_data *pd, int off)
1427{
1428 struct cfq_group *cfqg = pd_to_cfqg(pd);
1429
1430 if (!cfqg->dev_leaf_weight)
1431 return 0;
1432 return __blkg_prfill_u64(sf, pd, cfqg->dev_leaf_weight);
1433}
1434
1435static int cfqg_print_leaf_weight_device(struct cgroup *cgrp,
1436 struct cftype *cft,
1437 struct seq_file *sf)
1438{
1439 blkcg_print_blkgs(sf, cgroup_to_blkcg(cgrp),
1440 cfqg_prfill_leaf_weight_device, &blkcg_policy_cfq, 0,
1441 false);
1442 return 0;
1443}
1444
1407static int cfq_print_weight(struct cgroup *cgrp, struct cftype *cft, 1445static int cfq_print_weight(struct cgroup *cgrp, struct cftype *cft,
1408 struct seq_file *sf) 1446 struct seq_file *sf)
1409{ 1447{
@@ -1411,8 +1449,16 @@ static int cfq_print_weight(struct cgroup *cgrp, struct cftype *cft,
1411 return 0; 1449 return 0;
1412} 1450}
1413 1451
1414static int cfqg_set_weight_device(struct cgroup *cgrp, struct cftype *cft, 1452static int cfq_print_leaf_weight(struct cgroup *cgrp, struct cftype *cft,
1415 const char *buf) 1453 struct seq_file *sf)
1454{
1455 seq_printf(sf, "%u\n",
1456 cgroup_to_blkcg(cgrp)->cfq_leaf_weight);
1457 return 0;
1458}
1459
1460static int __cfqg_set_weight_device(struct cgroup *cgrp, struct cftype *cft,
1461 const char *buf, bool is_leaf_weight)
1416{ 1462{
1417 struct blkcg *blkcg = cgroup_to_blkcg(cgrp); 1463 struct blkcg *blkcg = cgroup_to_blkcg(cgrp);
1418 struct blkg_conf_ctx ctx; 1464 struct blkg_conf_ctx ctx;
@@ -1426,8 +1472,13 @@ static int cfqg_set_weight_device(struct cgroup *cgrp, struct cftype *cft,
1426 ret = -EINVAL; 1472 ret = -EINVAL;
1427 cfqg = blkg_to_cfqg(ctx.blkg); 1473 cfqg = blkg_to_cfqg(ctx.blkg);
1428 if (!ctx.v || (ctx.v >= CFQ_WEIGHT_MIN && ctx.v <= CFQ_WEIGHT_MAX)) { 1474 if (!ctx.v || (ctx.v >= CFQ_WEIGHT_MIN && ctx.v <= CFQ_WEIGHT_MAX)) {
1429 cfqg->dev_weight = ctx.v; 1475 if (!is_leaf_weight) {
1430 cfqg->new_weight = cfqg->dev_weight ?: blkcg->cfq_weight; 1476 cfqg->dev_weight = ctx.v;
1477 cfqg->new_weight = ctx.v ?: blkcg->cfq_weight;
1478 } else {
1479 cfqg->dev_leaf_weight = ctx.v;
1480 cfqg->new_leaf_weight = ctx.v ?: blkcg->cfq_leaf_weight;
1481 }
1431 ret = 0; 1482 ret = 0;
1432 } 1483 }
1433 1484
@@ -1435,7 +1486,20 @@ static int cfqg_set_weight_device(struct cgroup *cgrp, struct cftype *cft,
1435 return ret; 1486 return ret;
1436} 1487}
1437 1488
1438static int cfq_set_weight(struct cgroup *cgrp, struct cftype *cft, u64 val) 1489static int cfqg_set_weight_device(struct cgroup *cgrp, struct cftype *cft,
1490 const char *buf)
1491{
1492 return __cfqg_set_weight_device(cgrp, cft, buf, false);
1493}
1494
1495static int cfqg_set_leaf_weight_device(struct cgroup *cgrp, struct cftype *cft,
1496 const char *buf)
1497{
1498 return __cfqg_set_weight_device(cgrp, cft, buf, true);
1499}
1500
1501static int __cfq_set_weight(struct cgroup *cgrp, struct cftype *cft, u64 val,
1502 bool is_leaf_weight)
1439{ 1503{
1440 struct blkcg *blkcg = cgroup_to_blkcg(cgrp); 1504 struct blkcg *blkcg = cgroup_to_blkcg(cgrp);
1441 struct blkcg_gq *blkg; 1505 struct blkcg_gq *blkg;
@@ -1445,19 +1509,41 @@ static int cfq_set_weight(struct cgroup *cgrp, struct cftype *cft, u64 val)
1445 return -EINVAL; 1509 return -EINVAL;
1446 1510
1447 spin_lock_irq(&blkcg->lock); 1511 spin_lock_irq(&blkcg->lock);
1448 blkcg->cfq_weight = (unsigned int)val; 1512
1513 if (!is_leaf_weight)
1514 blkcg->cfq_weight = val;
1515 else
1516 blkcg->cfq_leaf_weight = val;
1449 1517
1450 hlist_for_each_entry(blkg, n, &blkcg->blkg_list, blkcg_node) { 1518 hlist_for_each_entry(blkg, n, &blkcg->blkg_list, blkcg_node) {
1451 struct cfq_group *cfqg = blkg_to_cfqg(blkg); 1519 struct cfq_group *cfqg = blkg_to_cfqg(blkg);
1452 1520
1453 if (cfqg && !cfqg->dev_weight) 1521 if (!cfqg)
1454 cfqg->new_weight = blkcg->cfq_weight; 1522 continue;
1523
1524 if (!is_leaf_weight) {
1525 if (!cfqg->dev_weight)
1526 cfqg->new_weight = blkcg->cfq_weight;
1527 } else {
1528 if (!cfqg->dev_leaf_weight)
1529 cfqg->new_leaf_weight = blkcg->cfq_leaf_weight;
1530 }
1455 } 1531 }
1456 1532
1457 spin_unlock_irq(&blkcg->lock); 1533 spin_unlock_irq(&blkcg->lock);
1458 return 0; 1534 return 0;
1459} 1535}
1460 1536
1537static int cfq_set_weight(struct cgroup *cgrp, struct cftype *cft, u64 val)
1538{
1539 return __cfq_set_weight(cgrp, cft, val, false);
1540}
1541
1542static int cfq_set_leaf_weight(struct cgroup *cgrp, struct cftype *cft, u64 val)
1543{
1544 return __cfq_set_weight(cgrp, cft, val, true);
1545}
1546
1461static int cfqg_print_stat(struct cgroup *cgrp, struct cftype *cft, 1547static int cfqg_print_stat(struct cgroup *cgrp, struct cftype *cft,
1462 struct seq_file *sf) 1548 struct seq_file *sf)
1463{ 1549{
@@ -1518,6 +1604,37 @@ static struct cftype cfq_blkcg_files[] = {
1518 .read_seq_string = cfq_print_weight, 1604 .read_seq_string = cfq_print_weight,
1519 .write_u64 = cfq_set_weight, 1605 .write_u64 = cfq_set_weight,
1520 }, 1606 },
1607
1608 /* on root, leaf_weight is mapped to weight */
1609 {
1610 .name = "leaf_weight_device",
1611 .flags = CFTYPE_ONLY_ON_ROOT,
1612 .read_seq_string = cfqg_print_weight_device,
1613 .write_string = cfqg_set_weight_device,
1614 .max_write_len = 256,
1615 },
1616 {
1617 .name = "leaf_weight",
1618 .flags = CFTYPE_ONLY_ON_ROOT,
1619 .read_seq_string = cfq_print_weight,
1620 .write_u64 = cfq_set_weight,
1621 },
1622
1623 /* no such mapping necessary for !roots */
1624 {
1625 .name = "leaf_weight_device",
1626 .flags = CFTYPE_NOT_ON_ROOT,
1627 .read_seq_string = cfqg_print_leaf_weight_device,
1628 .write_string = cfqg_set_leaf_weight_device,
1629 .max_write_len = 256,
1630 },
1631 {
1632 .name = "leaf_weight",
1633 .flags = CFTYPE_NOT_ON_ROOT,
1634 .read_seq_string = cfq_print_leaf_weight,
1635 .write_u64 = cfq_set_leaf_weight,
1636 },
1637
1521 { 1638 {
1522 .name = "time", 1639 .name = "time",
1523 .private = offsetof(struct cfq_group, stats.time), 1640 .private = offsetof(struct cfq_group, stats.time),
@@ -3992,6 +4109,7 @@ static int cfq_init_queue(struct request_queue *q)
3992 cfq_init_cfqg_base(cfqd->root_group); 4109 cfq_init_cfqg_base(cfqd->root_group);
3993#endif 4110#endif
3994 cfqd->root_group->weight = 2 * CFQ_WEIGHT_DEFAULT; 4111 cfqd->root_group->weight = 2 * CFQ_WEIGHT_DEFAULT;
4112 cfqd->root_group->leaf_weight = 2 * CFQ_WEIGHT_DEFAULT;
3995 4113
3996 /* 4114 /*
3997 * Not strictly needed (since RB_ROOT just clears the node and we 4115 * Not strictly needed (since RB_ROOT just clears the node and we