Since latency Qos detection doesn't account for IOs which are in-flight for longer than a period, we detect them by comparing vdone against period start. If lagging behind IOs from past periods, don't increase vrate, but don't let cmds which take a very long time pin lagging for too long. The current code compares vdone against (vnow - period_vtime), which is thought to be the period start. But the earliest period start should be (vnow - period_vtime - margins.target). And we will slide forward vtime and vdone on each period timer, so we can't depend on vtime to check if the iocg has pinned lagging for longer than MAX_LAGGING_PERIODS. This patch adds lagging_periods in iocg to record how long the iocg has pinned lagging, will not be thought as lagging if longer than MAX_LAGGING_PERIODS. Signed-off-by: Chengming Zhou <zhouchengming@xxxxxxxxxxxxx> --- v2: - add lagging_periods to check very long lagging iocg. --- block/blk-iocost.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/block/blk-iocost.c b/block/blk-iocost.c index 33a11ba971ea..998bb38ffb37 100644 --- a/block/blk-iocost.c +++ b/block/blk-iocost.c @@ -541,6 +541,8 @@ struct ioc_gq { u64 indebt_since; u64 indelay_since; + int lagging_periods; + /* this iocg's depth in the hierarchy and ancestors including self */ int level; struct ioc_gq *ancestors[]; @@ -2257,10 +2259,13 @@ static void ioc_timer_fn(struct timer_list *timer) if ((ppm_rthr != MILLION || ppm_wthr != MILLION) && !atomic_read(&iocg_to_blkg(iocg)->use_delay) && time_after64(vtime, vdone) && - time_after64(vtime, now.vnow - - MAX_LAGGING_PERIODS * period_vtime) && - time_before64(vdone, now.vnow - period_vtime)) - nr_lagging++; + time_before64(vdone, ioc->period_at_vtime - ioc->margins.target)) { + if (iocg->lagging_periods < MAX_LAGGING_PERIODS) { + nr_lagging++; + iocg->lagging_periods++; + } + } else if (iocg->lagging_periods) + iocg->lagging_periods = 0; /* * Determine absolute usage factoring in in-flight IOs to avoid -- 2.36.1