[Devel] [PATCH RHEL7 COMMIT] vziolimit: port diff-ubc-iolimit-keep-charge-in-throttler
Konstantin Khorenko
khorenko at odin.com
Tue May 5 02:44:40 PDT 2015
The commit is pushed to "branch-rh7-3.10.0-123.1.2-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-123.1.2.vz7.4.9
------>
commit c476e1a6d365c8ee156b05ab0a0ccbcb9601a984
Author: Dmitry Monakhov <dmonakhov at openvz.org>
Date: Tue May 5 13:44:39 2015 +0400
vziolimit: port diff-ubc-iolimit-keep-charge-in-throttler
iolimit: keep charge in throttler
Now throttler can keep precharge, so we can start throttling earlier.
* use long long for state to avoid overflows.
Signed-off-by: Konstantin Khlebnikov <khlebnikov at openvz.org>
Acked-by: Pavel Emelyanov <xemul at parallels.com>
====================================
https://jira.sw.ru/browse/PSBM-20104
Signed-off-by: Dmitry Monakhov <dmonakhov at openvz.org>
---
kernel/ve/vziolimit.c | 53 ++++++++++++++++++++++++++++++++-------------------
1 file changed, 33 insertions(+), 20 deletions(-)
diff --git a/kernel/ve/vziolimit.c b/kernel/ve/vziolimit.c
index e2eedae..7ff2854 100644
--- a/kernel/ve/vziolimit.c
+++ b/kernel/ve/vziolimit.c
@@ -18,8 +18,8 @@ struct throttle {
unsigned speed; /* maximum speed, units per second */
unsigned burst; /* maximum bust, units */
unsigned latency; /* maximum wait delay, jiffies */
- unsigned state; /* current state */
unsigned long time; /* wall time in jiffies */
+ long long state; /* current state in units */
};
/**
@@ -34,41 +34,46 @@ static void throttle_setup(struct throttle *th, unsigned speed,
th->time = jiffies;
th->burst = burst;
th->latency = msecs_to_jiffies(latency);
- th->state = 0;
+ /* feed throttler to avoid freezing */
+ if (th->state < burst)
+ th->state = burst;
wmb();
th->speed = speed;
}
/* externally serialized */
-static void throttle_charge(struct throttle *th, unsigned charge)
+static void throttle_charge(struct throttle *th, long long charge)
{
- unsigned long now = jiffies;
- u64 step;
-
- if (!th->speed)
- return;
+ unsigned long time, now = jiffies;
+ long long step, ceiling = charge + th->burst;
if (time_before(th->time, now)) {
step = (u64)th->speed * (now - th->time);
do_div(step, HZ);
- th->state = min((unsigned)step + th->state, charge + th->burst);
+ step += th->state;
+ /* feed throttler as much as we can */
+ if (step <= ceiling)
+ th->state = step;
+ else if (th->state < ceiling)
+ th->state = ceiling;
th->time = now;
}
if (charge > th->state) {
charge -= th->state;
- step = (u64)charge * HZ;
+ step = charge * HZ;
if (do_div(step, th->speed))
step++;
- th->time += step;
+ time = th->time + step;
+ /* limit maximum latency */
+ if (time_after(time, now + th->latency))
+ time = now + th->latency;
+ th->time = time;
step *= th->speed;
- do_div(step, HZ);
- th->state = max_t(int, (int)step - charge, 0);
- } else
- th->state -= charge;
-
- if (time_after(th->time, now + th->latency))
- th->time = now + th->latency;
+ if (do_div(step, HZ))
+ step++;
+ th->state += step;
+ }
}
/* lockless */
@@ -133,14 +138,22 @@ static int iolimit_virtinfo(struct vnotifier_block *nb,
if (!iolimit->throttle.speed)
break;
spin_lock_irqsave(&ub->ub_lock, flags);
- throttle_charge(&iolimit->throttle, *(size_t*)arg);
+ if (iolimit->throttle.speed) {
+ long long charge = *(size_t*)arg;
+
+ throttle_charge(&iolimit->throttle, charge);
+ iolimit->throttle.state -= charge;
+ }
spin_unlock_irqrestore(&ub->ub_lock, flags);
break;
case VIRTINFO_IO_OP_ACCOUNT:
if (!iolimit->iops.speed)
break;
spin_lock_irqsave(&ub->ub_lock, flags);
- throttle_charge(&iolimit->iops, 1);
+ if (iolimit->iops.speed) {
+ throttle_charge(&iolimit->iops, 1);
+ iolimit->iops.state--;
+ }
spin_unlock_irqrestore(&ub->ub_lock, flags);
break;
case VIRTINFO_IO_PREPARE:
More information about the Devel
mailing list