diff options
-rw-r--r-- | block/blk-throttle.c | 50 |
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 | } |