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 <dmonak...@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 <khlebni...@openvz.org> Acked-by: Pavel Emelyanov <xe...@parallels.com> ==================================== https://jira.sw.ru/browse/PSBM-20104 Signed-off-by: Dmitry Monakhov <dmonak...@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: _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel