From 1e67040c6960d2f503f7da082727d64bfd55a83a Mon Sep 17 00:00:00 2001 From: Fabian Keil Date: Wed, 2 Aug 2017 13:16:01 +0200 Subject: [PATCH 7/8] cam iosched: Enforce iop limits below the quanta value Previously the iops limiter would always allow at least quanta ios per second as cam_iosched_iops_tick() never set ios->l_value1 below 1. Obtained from: ElectroBSD --- sys/cam/cam_iosched.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/sys/cam/cam_iosched.c b/sys/cam/cam_iosched.c index 77ad53269cd2..2ebe4538a4e1 100644 --- a/sys/cam/cam_iosched.c +++ b/sys/cam/cam_iosched.c @@ -415,6 +415,7 @@ cam_iosched_iops_init(struct iop_stats *ios) ios->l_value1 = ios->current / ios->softc->quanta; if (ios->l_value1 <= 0) ios->l_value1 = 1; + ios->l_value2 = 0; return 0; } @@ -423,9 +424,18 @@ static int cam_iosched_iops_tick(struct iop_stats *ios) { + if ((ios->softc->total_ticks % ios->softc->quanta) == 0) + ios->l_value2 = 0; + ios->l_value1 = (int)((ios->current * (uint64_t)ios->softc->this_frac) >> 16); - if (ios->l_value1 <= 0) + /* + * Allow at least one IO per tick until all + * the IOs for this interval have been spent. + */ + if (ios->l_value1 <= 0 && ios->l_value2 < ios->current) { ios->l_value1 = 1; + ios->l_value2++; + } return 0; } -- 2.14.1 From 90848077590580bf1d2ec0a61add4818bb657876 Mon Sep 17 00:00:00 2001 From: Fabian Keil Date: Wed, 2 Aug 2017 15:38:10 +0200 Subject: [PATCH 8/8] cam iosched: Prevent cam_iosched_iops_tick() from discarding 'unspent' ios ... unless it's a new accounting interval. Previously ios that weren't used between ticks were lost, as a result the iops limiter could enforce a limit below the configured maximum. Obtained from: ElectroBSD --- sys/cam/cam_iosched.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/sys/cam/cam_iosched.c b/sys/cam/cam_iosched.c index 2ebe4538a4e1..cee93c9712a0 100644 --- a/sys/cam/cam_iosched.c +++ b/sys/cam/cam_iosched.c @@ -423,20 +423,30 @@ cam_iosched_iops_init(struct iop_stats *ios) static int cam_iosched_iops_tick(struct iop_stats *ios) { + int new_ios; - if ((ios->softc->total_ticks % ios->softc->quanta) == 0) - ios->l_value2 = 0; - - ios->l_value1 = (int)((ios->current * (uint64_t)ios->softc->this_frac) >> 16); + new_ios = (int)((ios->current * (uint64_t)ios->softc->this_frac) >> 16); /* * Allow at least one IO per tick until all * the IOs for this interval have been spent. */ - if (ios->l_value1 <= 0 && ios->l_value2 < ios->current) { - ios->l_value1 = 1; + if (new_ios < 1 && ios->l_value2 < ios->current) { + new_ios = 1; ios->l_value2++; } + /* + * If this a new accounting interval, discard any "unspent" ios + * granted in the previous interval. Otherwise add the new ios to + * the previously granted ones that haven't been spent yet. + */ + if ((ios->softc->total_ticks % ios->softc->quanta) == 0) { + ios->l_value1 = new_ios; + ios->l_value2 = 1; + } else { + ios->l_value1 += new_ios; + } + return 0; } -- 2.14.1