summaryrefslogtreecommitdiffstats
path: root/block/blk-throttle.c
diff options
context:
space:
mode:
authorShaohua Li <shli@fb.com>2017-05-17 16:07:24 -0400
committerJens Axboe <axboe@fb.com>2017-05-22 16:47:12 -0400
commit5b81fc3cc625e857275573cb4240bbab553f919c (patch)
treeea36cd79d9bf4ba855d231826d5bf17a58fd0242 /block/blk-throttle.c
parent08332893e37af6ae779367e78e444f8f9571511d (diff)
blk-throttle: add hierarchy support for latency target and idle time
For idle time, children's setting should not be bigger than parent's. For latency target, children's setting should not be smaller than parent's. The leaf nodes will adjust their settings according to the hierarchy and compare their IO with the settings and do upgrade/downgrade. parents nodes don't need to track their IO latency/idle time. Signed-off-by: Shaohua Li <shli@fb.com> Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block/blk-throttle.c')
-rw-r--r--block/blk-throttle.c50
1 files changed, 36 insertions, 14 deletions
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index b78db2e5fdff..16174f8cb0a1 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -157,6 +157,7 @@ struct throtl_grp {
157 unsigned long last_check_time; 157 unsigned long last_check_time;
158 158
159 unsigned long latency_target; /* us */ 159 unsigned long latency_target; /* us */
160 unsigned long latency_target_conf; /* us */
160 /* When did we start a new slice */ 161 /* When did we start a new slice */
161 unsigned long slice_start[2]; 162 unsigned long slice_start[2];
162 unsigned long slice_end[2]; 163 unsigned long slice_end[2];
@@ -165,6 +166,7 @@ struct throtl_grp {
165 unsigned long checked_last_finish_time; /* ns / 1024 */ 166 unsigned long checked_last_finish_time; /* ns / 1024 */
166 unsigned long avg_idletime; /* ns / 1024 */ 167 unsigned long avg_idletime; /* ns / 1024 */
167 unsigned long idletime_threshold; /* us */ 168 unsigned long idletime_threshold; /* us */
169 unsigned long idletime_threshold_conf; /* us */
168 170
169 unsigned int bio_cnt; /* total bios */ 171 unsigned int bio_cnt; /* total bios */
170 unsigned int bad_bio_cnt; /* bios exceeding latency threshold */ 172 unsigned int bad_bio_cnt; /* bios exceeding latency threshold */
@@ -482,6 +484,7 @@ static struct blkg_policy_data *throtl_pd_alloc(gfp_t gfp, int node)
482 /* LIMIT_LOW will have default value 0 */ 484 /* LIMIT_LOW will have default value 0 */
483 485
484 tg->latency_target = DFL_LATENCY_TARGET; 486 tg->latency_target = DFL_LATENCY_TARGET;
487 tg->latency_target_conf = DFL_LATENCY_TARGET;
485 488
486 return &tg->pd; 489 return &tg->pd;
487} 490}
@@ -512,6 +515,7 @@ static void throtl_pd_init(struct blkg_policy_data *pd)
512 tg->td = td; 515 tg->td = td;
513 516
514 tg->idletime_threshold = td->dft_idletime_threshold; 517 tg->idletime_threshold = td->dft_idletime_threshold;
518 tg->idletime_threshold_conf = td->dft_idletime_threshold;
515} 519}
516 520
517/* 521/*
@@ -1367,8 +1371,25 @@ static void tg_conf_updated(struct throtl_grp *tg)
1367 * restrictions in the whole hierarchy and allows them to bypass 1371 * restrictions in the whole hierarchy and allows them to bypass
1368 * blk-throttle. 1372 * blk-throttle.
1369 */ 1373 */
1370 blkg_for_each_descendant_pre(blkg, pos_css, tg_to_blkg(tg)) 1374 blkg_for_each_descendant_pre(blkg, pos_css, tg_to_blkg(tg)) {
1371 tg_update_has_rules(blkg_to_tg(blkg)); 1375 struct throtl_grp *this_tg = blkg_to_tg(blkg);
1376 struct throtl_grp *parent_tg;
1377
1378 tg_update_has_rules(this_tg);
1379 /* ignore root/second level */
1380 if (!cgroup_subsys_on_dfl(io_cgrp_subsys) || !blkg->parent ||
1381 !blkg->parent->parent)
1382 continue;
1383 parent_tg = blkg_to_tg(blkg->parent);
1384 /*
1385 * make sure all children has lower idle time threshold and
1386 * higher latency target
1387 */
1388 this_tg->idletime_threshold = min(this_tg->idletime_threshold,
1389 parent_tg->idletime_threshold);
1390 this_tg->latency_target = max(this_tg->latency_target,
1391 parent_tg->latency_target);
1392 }
1372 1393
1373 /* 1394 /*
1374 * We're already holding queue_lock and know @tg is valid. Let's 1395 * We're already holding queue_lock and know @tg is valid. Let's
@@ -1497,8 +1518,8 @@ static u64 tg_prfill_limit(struct seq_file *sf, struct blkg_policy_data *pd,
1497 tg->iops_conf[READ][off] == iops_dft && 1518 tg->iops_conf[READ][off] == iops_dft &&
1498 tg->iops_conf[WRITE][off] == iops_dft && 1519 tg->iops_conf[WRITE][off] == iops_dft &&
1499 (off != LIMIT_LOW || 1520 (off != LIMIT_LOW ||
1500 (tg->idletime_threshold == tg->td->dft_idletime_threshold && 1521 (tg->idletime_threshold_conf == tg->td->dft_idletime_threshold &&
1501 tg->latency_target == DFL_LATENCY_TARGET))) 1522 tg->latency_target_conf == DFL_LATENCY_TARGET)))
1502 return 0; 1523 return 0;
1503 1524
1504 if (tg->bps_conf[READ][off] != bps_dft) 1525 if (tg->bps_conf[READ][off] != bps_dft)
@@ -1514,17 +1535,17 @@ static u64 tg_prfill_limit(struct seq_file *sf, struct blkg_policy_data *pd,
1514 snprintf(bufs[3], sizeof(bufs[3]), "%u", 1535 snprintf(bufs[3], sizeof(bufs[3]), "%u",
1515 tg->iops_conf[WRITE][off]); 1536 tg->iops_conf[WRITE][off]);
1516 if (off == LIMIT_LOW) { 1537 if (off == LIMIT_LOW) {
1517 if (tg->idletime_threshold == ULONG_MAX) 1538 if (tg->idletime_threshold_conf == ULONG_MAX)
1518 strcpy(idle_time, " idle=max"); 1539 strcpy(idle_time, " idle=max");
1519 else 1540 else
1520 snprintf(idle_time, sizeof(idle_time), " idle=%lu", 1541 snprintf(idle_time, sizeof(idle_time), " idle=%lu",
1521 tg->idletime_threshold); 1542 tg->idletime_threshold_conf);
1522 1543
1523 if (tg->latency_target == ULONG_MAX) 1544 if (tg->latency_target_conf == ULONG_MAX)
1524 strcpy(latency_time, " latency=max"); 1545 strcpy(latency_time, " latency=max");
1525 else 1546 else
1526 snprintf(latency_time, sizeof(latency_time), 1547 snprintf(latency_time, sizeof(latency_time),
1527 " latency=%lu", tg->latency_target); 1548 " latency=%lu", tg->latency_target_conf);
1528 } 1549 }
1529 1550
1530 seq_printf(sf, "%s rbps=%s wbps=%s riops=%s wiops=%s%s%s\n", 1551 seq_printf(sf, "%s rbps=%s wbps=%s riops=%s wiops=%s%s%s\n",
@@ -1563,8 +1584,8 @@ static ssize_t tg_set_limit(struct kernfs_open_file *of,
1563 v[2] = tg->iops_conf[READ][index]; 1584 v[2] = tg->iops_conf[READ][index];
1564 v[3] = tg->iops_conf[WRITE][index]; 1585 v[3] = tg->iops_conf[WRITE][index];
1565 1586
1566 idle_time = tg->idletime_threshold; 1587 idle_time = tg->idletime_threshold_conf;
1567 latency_time = tg->latency_target; 1588 latency_time = tg->latency_target_conf;
1568 while (true) { 1589 while (true) {
1569 char tok[27]; /* wiops=18446744073709551616 */ 1590 char tok[27]; /* wiops=18446744073709551616 */
1570 char *p; 1591 char *p;
@@ -1628,10 +1649,10 @@ static ssize_t tg_set_limit(struct kernfs_open_file *of,
1628 blk_throtl_update_limit_valid(tg->td); 1649 blk_throtl_update_limit_valid(tg->td);
1629 if (tg->td->limit_valid[LIMIT_LOW]) 1650 if (tg->td->limit_valid[LIMIT_LOW])
1630 tg->td->limit_index = LIMIT_LOW; 1651 tg->td->limit_index = LIMIT_LOW;
1631 tg->idletime_threshold = (idle_time == ULONG_MAX) ? 1652 tg->idletime_threshold_conf = idle_time;
1632 ULONG_MAX : idle_time; 1653 tg->idletime_threshold = tg->idletime_threshold_conf;
1633 tg->latency_target = (latency_time == ULONG_MAX) ? 1654 tg->latency_target_conf = latency_time;
1634 ULONG_MAX : latency_time; 1655 tg->latency_target = tg->latency_target_conf;
1635 } 1656 }
1636 tg_conf_updated(tg); 1657 tg_conf_updated(tg);
1637 ret = 0; 1658 ret = 0;
@@ -2385,6 +2406,7 @@ void blk_throtl_register_queue(struct request_queue *q)
2385 struct throtl_grp *tg = blkg_to_tg(blkg); 2406 struct throtl_grp *tg = blkg_to_tg(blkg);
2386 2407
2387 tg->idletime_threshold = td->dft_idletime_threshold; 2408 tg->idletime_threshold = td->dft_idletime_threshold;
2409 tg->idletime_threshold_conf = td->dft_idletime_threshold;
2388 } 2410 }
2389 rcu_read_unlock(); 2411 rcu_read_unlock();
2390} 2412}