forked from luck/tmp_suning_uos_patched
iocost: factor out ioc_forgive_debts()
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>
This commit is contained in:
parent
6abc49468e
commit
ab8df828b5
|
@ -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);
|
||||
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user