Skip to content

Commit

Permalink
iocost: factor out ioc_forgive_debts()
Browse files Browse the repository at this point in the history
Debt reduction logic is going to be improved and expanded. Factor it out
into ioc_forgive_debts() and generalize the comment a bit. No functional
change.

Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
  • Loading branch information
Tejun Heo authored and Jens Axboe committed Sep 25, 2020
1 parent 6abc494 commit ab8df82
Showing 1 changed file with 35 additions and 31 deletions.
66 changes: 35 additions & 31 deletions block/blk-iocost.c
Original file line number Diff line number Diff line change
Expand Up @@ -1979,6 +1979,40 @@ static void transfer_surpluses(struct list_head *surpluses, struct ioc_now *now)
list_del_init(&iocg->walk_list);
}

/*
* A low weight iocg can amass a large amount of debt, for example, when
* anonymous memory gets reclaimed aggressively. If the system has a lot of
* memory paired with a slow IO device, the debt can span multiple seconds or
* more. If there are no other subsequent IO issuers, the in-debt iocg may end
* up blocked paying its debt while the IO device is idle.
*
* The following protects against such cases. If the device has been
* sufficiently idle for a while, the debts are halved.
*/
static void ioc_forgive_debts(struct ioc *ioc, u64 usage_us_sum, int nr_debtors,
int nr_shortages, struct ioc_now *now)
{
if (nr_shortages ||
div64_u64(100 * usage_us_sum, now->now - ioc->period_at) >=
DEBT_BUSY_USAGE_PCT)
ioc->debt_busy_at = now->now;

if (nr_debtors &&
now->now - ioc->debt_busy_at >= DEBT_REDUCTION_IDLE_DUR) {
struct ioc_gq *iocg;

list_for_each_entry(iocg, &ioc->active_iocgs, active_list) {
if (iocg->abs_vdebt) {
spin_lock(&iocg->waitq.lock);
iocg->abs_vdebt /= 2;
iocg_kick_waitq(iocg, true, now);
spin_unlock(&iocg->waitq.lock);
}
}
ioc->debt_busy_at = now->now;
}
}

static void ioc_timer_fn(struct timer_list *timer)
{
struct ioc *ioc = container_of(timer, struct ioc, timer);
Expand Down Expand Up @@ -2171,37 +2205,7 @@ static void ioc_timer_fn(struct timer_list *timer)
list_for_each_entry_safe(iocg, tiocg, &surpluses, surplus_list)
list_del_init(&iocg->surplus_list);

/*
* A low weight iocg can amass a large amount of debt, for example, when
* anonymous memory gets reclaimed aggressively. If the system has a lot
* of memory paired with a slow IO device, the debt can span multiple
* seconds or more. If there are no other subsequent IO issuers, the
* in-debt iocg may end up blocked paying its debt while the IO device
* is idle.
*
* The following protects against such pathological cases. If the device
* has been sufficiently idle for a substantial amount of time, the
* debts are halved. The criteria are on the conservative side as we
* want to resolve the rare extreme cases without impacting regular
* operation by forgiving debts too readily.
*/
if (nr_shortages ||
div64_u64(100 * usage_us_sum, now.now - ioc->period_at) >=
DEBT_BUSY_USAGE_PCT)
ioc->debt_busy_at = now.now;

if (nr_debtors &&
now.now - ioc->debt_busy_at >= DEBT_REDUCTION_IDLE_DUR) {
list_for_each_entry(iocg, &ioc->active_iocgs, active_list) {
if (iocg->abs_vdebt) {
spin_lock(&iocg->waitq.lock);
iocg->abs_vdebt /= 2;
iocg_kick_waitq(iocg, true, &now);
spin_unlock(&iocg->waitq.lock);
}
}
ioc->debt_busy_at = now.now;
}
ioc_forgive_debts(ioc, usage_us_sum, nr_debtors, nr_shortages, &now);

/*
* If q is getting clogged or we're missing too much, we're issuing
Expand Down

0 comments on commit ab8df82

Please sign in to comment.