diff options
-rw-r--r-- | block/blk-cgroup.c | 4 | ||||
-rw-r--r-- | block/blk-cgroup.h | 1 | ||||
-rw-r--r-- | block/cfq-iosched.c | 134 |
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 | ||
27 | static DEFINE_MUTEX(blkcg_pol_mutex); | 27 | static DEFINE_MUTEX(blkcg_pol_mutex); |
28 | 28 | ||
29 | struct blkcg blkcg_root = { .cfq_weight = 2 * CFQ_WEIGHT_DEFAULT }; | 29 | struct blkcg blkcg_root = { .cfq_weight = 2 * CFQ_WEIGHT_DEFAULT, |
30 | .cfq_leaf_weight = 2 * CFQ_WEIGHT_DEFAULT, }; | ||
30 | EXPORT_SYMBOL_GPL(blkcg_root); | 31 | EXPORT_SYMBOL_GPL(blkcg_root); |
31 | 32 | ||
32 | static struct blkcg_policy *blkcg_policy[BLKCG_MAX_POLS]; | 33 | static 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 */ |
714 | done: | 716 | done: |
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 | ||
59 | struct blkg_stat { | 60 | struct 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 | |||
1182 | cfq_update_group_weight(struct cfq_group *cfqg) | 1193 | cfq_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 | ||
1191 | static void | 1208 | static 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 | ||
1425 | static 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 | |||
1435 | static 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 | |||
1407 | static int cfq_print_weight(struct cgroup *cgrp, struct cftype *cft, | 1445 | static 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 | ||
1414 | static int cfqg_set_weight_device(struct cgroup *cgrp, struct cftype *cft, | 1452 | static 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 | |||
1460 | static 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 | ||
1438 | static int cfq_set_weight(struct cgroup *cgrp, struct cftype *cft, u64 val) | 1489 | static 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 | |||
1495 | static 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 | |||
1501 | static 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 | ||
1537 | static int cfq_set_weight(struct cgroup *cgrp, struct cftype *cft, u64 val) | ||
1538 | { | ||
1539 | return __cfq_set_weight(cgrp, cft, val, false); | ||
1540 | } | ||
1541 | |||
1542 | static 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 | |||
1461 | static int cfqg_print_stat(struct cgroup *cgrp, struct cftype *cft, | 1547 | static 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 |