aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/blk-cgroup.c4
-rw-r--r--block/blk-cgroup.h1
-rw-r--r--block/cfq-iosched.c134
3 files changed, 130 insertions, 9 deletions
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 942f344fdfa7..10e1df9da46e 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -26,7 +26,8 @@
26 26
27static DEFINE_MUTEX(blkcg_pol_mutex); 27static DEFINE_MUTEX(blkcg_pol_mutex);
28 28
29struct blkcg blkcg_root = { .cfq_weight = 2 * CFQ_WEIGHT_DEFAULT }; 29struct blkcg blkcg_root = { .cfq_weight = 2 * CFQ_WEIGHT_DEFAULT,
30 .cfq_leaf_weight = 2 * CFQ_WEIGHT_DEFAULT, };
30EXPORT_SYMBOL_GPL(blkcg_root); 31EXPORT_SYMBOL_GPL(blkcg_root);
31 32
32static struct blkcg_policy *blkcg_policy[BLKCG_MAX_POLS]; 33static struct blkcg_policy *blkcg_policy[BLKCG_MAX_POLS];
@@ -710,6 +711,7 @@ static struct cgroup_subsys_state *blkcg_css_alloc(struct cgroup *cgroup)
710 return ERR_PTR(-ENOMEM); 711 return ERR_PTR(-ENOMEM);
711 712
712 blkcg->cfq_weight = CFQ_WEIGHT_DEFAULT; 713 blkcg->cfq_weight = CFQ_WEIGHT_DEFAULT;
714 blkcg->cfq_leaf_weight = CFQ_WEIGHT_DEFAULT;
713 blkcg->id = atomic64_inc_return(&id_seq); /* root is 0, start from 1 */ 715 blkcg->id = atomic64_inc_return(&id_seq); /* root is 0, start from 1 */
714done: 716done:
715 spin_lock_init(&blkcg->lock); 717 spin_lock_init(&blkcg->lock);
diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h
index b26ed58899fe..24462258200e 100644
--- a/block/blk-cgroup.h
+++ b/block/blk-cgroup.h
@@ -54,6 +54,7 @@ struct blkcg {
54 54
55 /* TODO: per-policy storage in blkcg */ 55 /* TODO: per-policy storage in blkcg */
56 unsigned int cfq_weight; /* belongs to cfq */ 56 unsigned int cfq_weight; /* belongs to cfq */
57 unsigned int cfq_leaf_weight;
57}; 58};
58 59
59struct blkg_stat { 60struct blkg_stat {
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