summaryrefslogtreecommitdiffstats
path: root/block/blk-throttle.c
diff options
context:
space:
mode:
authorShaohua Li <shli@fb.com>2017-05-17 16:07:26 -0400
committerJens Axboe <axboe@fb.com>2017-05-22 16:47:12 -0400
commit9bb67aeb96784527dbc784c7a1b234461299363c (patch)
treee2146e228a7a161b463429ff1f4723c985db19ce /block/blk-throttle.c
parent4cff729f62d1bd433178f1ffe09db5718835e925 (diff)
blk-throttle: respect 0 bps/iops settings for io.low
If a cgroup with low limit 0 for both bps/iops, the cgroup's low limit is ignored and we throttle the cgroup with its max limit. In this way, other cgroups with a low limit will not get protected. To fix this, we don't do the exception any more. cgroup will be throttled to a limit 0 if it uese default setting. To avoid completed stall, we give such cgroup tiny IO resources. 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.c41
1 files changed, 29 insertions, 12 deletions
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index 1f8d62f5e808..f6a9f42a0ad7 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -27,6 +27,8 @@ static int throtl_quantum = 32;
27#define MAX_IDLE_TIME (5L * 1000 * 1000) /* 5 s */ 27#define MAX_IDLE_TIME (5L * 1000 * 1000) /* 5 s */
28/* default latency target is 0, eg, guarantee IO latency by default */ 28/* default latency target is 0, eg, guarantee IO latency by default */
29#define DFL_LATENCY_TARGET (0) 29#define DFL_LATENCY_TARGET (0)
30#define MIN_THROTL_BPS (320 * 1024)
31#define MIN_THROTL_IOPS (10)
30 32
31#define SKIP_LATENCY (((u64)1) << BLK_STAT_RES_SHIFT) 33#define SKIP_LATENCY (((u64)1) << BLK_STAT_RES_SHIFT)
32 34
@@ -296,8 +298,14 @@ static uint64_t tg_bps_limit(struct throtl_grp *tg, int rw)
296 298
297 td = tg->td; 299 td = tg->td;
298 ret = tg->bps[rw][td->limit_index]; 300 ret = tg->bps[rw][td->limit_index];
299 if (ret == 0 && td->limit_index == LIMIT_LOW) 301 if (ret == 0 && td->limit_index == LIMIT_LOW) {
300 return tg->bps[rw][LIMIT_MAX]; 302 /* intermediate node or iops isn't 0 */
303 if (!list_empty(&blkg->blkcg->css.children) ||
304 tg->iops[rw][td->limit_index])
305 return U64_MAX;
306 else
307 return MIN_THROTL_BPS;
308 }
301 309
302 if (td->limit_index == LIMIT_MAX && tg->bps[rw][LIMIT_LOW] && 310 if (td->limit_index == LIMIT_MAX && tg->bps[rw][LIMIT_LOW] &&
303 tg->bps[rw][LIMIT_LOW] != tg->bps[rw][LIMIT_MAX]) { 311 tg->bps[rw][LIMIT_LOW] != tg->bps[rw][LIMIT_MAX]) {
@@ -317,10 +325,17 @@ static unsigned int tg_iops_limit(struct throtl_grp *tg, int rw)
317 325
318 if (cgroup_subsys_on_dfl(io_cgrp_subsys) && !blkg->parent) 326 if (cgroup_subsys_on_dfl(io_cgrp_subsys) && !blkg->parent)
319 return UINT_MAX; 327 return UINT_MAX;
328
320 td = tg->td; 329 td = tg->td;
321 ret = tg->iops[rw][td->limit_index]; 330 ret = tg->iops[rw][td->limit_index];
322 if (ret == 0 && tg->td->limit_index == LIMIT_LOW) 331 if (ret == 0 && tg->td->limit_index == LIMIT_LOW) {
323 return tg->iops[rw][LIMIT_MAX]; 332 /* intermediate node or bps isn't 0 */
333 if (!list_empty(&blkg->blkcg->css.children) ||
334 tg->bps[rw][td->limit_index])
335 return UINT_MAX;
336 else
337 return MIN_THROTL_IOPS;
338 }
324 339
325 if (td->limit_index == LIMIT_MAX && tg->iops[rw][LIMIT_LOW] && 340 if (td->limit_index == LIMIT_MAX && tg->iops[rw][LIMIT_LOW] &&
326 tg->iops[rw][LIMIT_LOW] != tg->iops[rw][LIMIT_MAX]) { 341 tg->iops[rw][LIMIT_LOW] != tg->iops[rw][LIMIT_MAX]) {
@@ -1353,7 +1368,7 @@ static int tg_print_conf_uint(struct seq_file *sf, void *v)
1353 return 0; 1368 return 0;
1354} 1369}
1355 1370
1356static void tg_conf_updated(struct throtl_grp *tg) 1371static void tg_conf_updated(struct throtl_grp *tg, bool global)
1357{ 1372{
1358 struct throtl_service_queue *sq = &tg->service_queue; 1373 struct throtl_service_queue *sq = &tg->service_queue;
1359 struct cgroup_subsys_state *pos_css; 1374 struct cgroup_subsys_state *pos_css;
@@ -1371,7 +1386,8 @@ static void tg_conf_updated(struct throtl_grp *tg)
1371 * restrictions in the whole hierarchy and allows them to bypass 1386 * restrictions in the whole hierarchy and allows them to bypass
1372 * blk-throttle. 1387 * blk-throttle.
1373 */ 1388 */
1374 blkg_for_each_descendant_pre(blkg, pos_css, tg_to_blkg(tg)) { 1389 blkg_for_each_descendant_pre(blkg, pos_css,
1390 global ? tg->td->queue->root_blkg : tg_to_blkg(tg)) {
1375 struct throtl_grp *this_tg = blkg_to_tg(blkg); 1391 struct throtl_grp *this_tg = blkg_to_tg(blkg);
1376 struct throtl_grp *parent_tg; 1392 struct throtl_grp *parent_tg;
1377 1393
@@ -1434,7 +1450,7 @@ static ssize_t tg_set_conf(struct kernfs_open_file *of,
1434 else 1450 else
1435 *(unsigned int *)((void *)tg + of_cft(of)->private) = v; 1451 *(unsigned int *)((void *)tg + of_cft(of)->private) = v;
1436 1452
1437 tg_conf_updated(tg); 1453 tg_conf_updated(tg, false);
1438 ret = 0; 1454 ret = 0;
1439out_finish: 1455out_finish:
1440 blkg_conf_finish(&ctx); 1456 blkg_conf_finish(&ctx);
@@ -1522,16 +1538,16 @@ static u64 tg_prfill_limit(struct seq_file *sf, struct blkg_policy_data *pd,
1522 tg->latency_target_conf == DFL_LATENCY_TARGET))) 1538 tg->latency_target_conf == DFL_LATENCY_TARGET)))
1523 return 0; 1539 return 0;
1524 1540
1525 if (tg->bps_conf[READ][off] != bps_dft) 1541 if (tg->bps_conf[READ][off] != U64_MAX)
1526 snprintf(bufs[0], sizeof(bufs[0]), "%llu", 1542 snprintf(bufs[0], sizeof(bufs[0]), "%llu",
1527 tg->bps_conf[READ][off]); 1543 tg->bps_conf[READ][off]);
1528 if (tg->bps_conf[WRITE][off] != bps_dft) 1544 if (tg->bps_conf[WRITE][off] != U64_MAX)
1529 snprintf(bufs[1], sizeof(bufs[1]), "%llu", 1545 snprintf(bufs[1], sizeof(bufs[1]), "%llu",
1530 tg->bps_conf[WRITE][off]); 1546 tg->bps_conf[WRITE][off]);
1531 if (tg->iops_conf[READ][off] != iops_dft) 1547 if (tg->iops_conf[READ][off] != UINT_MAX)
1532 snprintf(bufs[2], sizeof(bufs[2]), "%u", 1548 snprintf(bufs[2], sizeof(bufs[2]), "%u",
1533 tg->iops_conf[READ][off]); 1549 tg->iops_conf[READ][off]);
1534 if (tg->iops_conf[WRITE][off] != iops_dft) 1550 if (tg->iops_conf[WRITE][off] != UINT_MAX)
1535 snprintf(bufs[3], sizeof(bufs[3]), "%u", 1551 snprintf(bufs[3], sizeof(bufs[3]), "%u",
1536 tg->iops_conf[WRITE][off]); 1552 tg->iops_conf[WRITE][off]);
1537 if (off == LIMIT_LOW) { 1553 if (off == LIMIT_LOW) {
@@ -1654,7 +1670,8 @@ static ssize_t tg_set_limit(struct kernfs_open_file *of,
1654 tg->latency_target_conf = latency_time; 1670 tg->latency_target_conf = latency_time;
1655 tg->latency_target = tg->latency_target_conf; 1671 tg->latency_target = tg->latency_target_conf;
1656 } 1672 }
1657 tg_conf_updated(tg); 1673 tg_conf_updated(tg, index == LIMIT_LOW &&
1674 tg->td->limit_valid[LIMIT_LOW]);
1658 ret = 0; 1675 ret = 0;
1659out_finish: 1676out_finish:
1660 blkg_conf_finish(&ctx); 1677 blkg_conf_finish(&ctx);