aboutsummaryrefslogtreecommitdiff
path: root/block
diff options
context:
space:
mode:
authorTejun Heo2020-09-18 14:41:27 -0400
committerJens Axboe2020-09-25 08:35:02 -0600
commitbec02dbbafad534674309f8b948094900f456797 (patch)
tree964cf1a1fd23ca0155677c8cdf536df0c78993be /block
parentc5a6561b8d99ea7d8df21308249ce05bce3dd466 (diff)
iocost: consider iocgs with active delays for debt forgiveness
An iocg may have 0 debt but non-zero delay. The current debt forgiveness logic doesn't act on such iocgs. This can lead to unexpected behaviors - an iocg with a little bit of debt will have its delay canceled through debt forgiveness but one w/o any debt but active delay will have to wait out until its delay decays out. This patch updates the debt handling logic so that it treats delays the same as debts. If either debt or delay is active, debt forgiveness logic kicks in and acts on both the same way. Also, avoid turning the debt and delay directly to zero as that can confuse state transitions. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block')
-rw-r--r--block/blk-iocost.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/block/blk-iocost.c b/block/blk-iocost.c
index 328ae805e85f..b82649c1440b 100644
--- a/block/blk-iocost.c
+++ b/block/blk-iocost.c
@@ -2048,7 +2048,7 @@ static void ioc_forgive_debts(struct ioc *ioc, u64 usage_us_sum, int nr_debtors,
list_for_each_entry(iocg, &ioc->active_iocgs, active_list) {
u64 __maybe_unused old_debt, __maybe_unused old_delay;
- if (!iocg->abs_vdebt)
+ if (!iocg->abs_vdebt && !iocg->delay)
continue;
spin_lock(&iocg->waitq.lock);
@@ -2056,8 +2056,11 @@ static void ioc_forgive_debts(struct ioc *ioc, u64 usage_us_sum, int nr_debtors,
old_debt = iocg->abs_vdebt;
old_delay = iocg->delay;
- iocg->abs_vdebt >>= nr_cycles;
- iocg->delay = 0; /* kick_waitq will recalc */
+ if (iocg->abs_vdebt)
+ iocg->abs_vdebt = iocg->abs_vdebt >> nr_cycles ?: 1;
+ if (iocg->delay)
+ iocg->delay = iocg->delay >> nr_cycles ?: 1;
+
iocg_kick_waitq(iocg, true, now);
TRACE_IOCG_PATH(iocg_forgive_debt, iocg, now, usage_pct,
@@ -2129,7 +2132,7 @@ static void ioc_timer_fn(struct timer_list *timer)
iocg->delay) {
/* might be oversleeping vtime / hweight changes, kick */
iocg_kick_waitq(iocg, true, &now);
- if (iocg->abs_vdebt)
+ if (iocg->abs_vdebt || iocg->delay)
nr_debtors++;
} else if (iocg_is_idle(iocg)) {
/* no waiter and idle, deactivate */