[Devel] [PATCH RHEL7 COMMIT] vziolimit: port diff-iolimit-implement-the-iops-limiting
Konstantin Khorenko
khorenko at odin.com
Tue May 5 02:44:39 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 8bf760736d64c58618f2fcc89382819a703e7a74
Author: Dmitry Monakhov <dmonakhov at openvz.org>
Date: Tue May 5 13:44:39 2015 +0400
vziolimit: port diff-iolimit-implement-the-iops-limiting
vziolimit: implement iops throttler
Add IO-operatins per second iolimit throttler.
API is the same as for throttler.
https://jira.sw.ru/browse/PCLIN-29446
Signed-off-by: Konstantin Khlebnikov <khlebnikov at openvz.org>
====================================
https://jira.sw.ru/browse/PSBM-20104
Signed-off-by: Dmitry Monakhov <dmonakhov at openvz.org>
---
include/linux/vziolimit.h | 2 +
kernel/ve/vziolimit.c | 119 +++++++++++++++++++++++++++++++++-------------
2 files changed, 87 insertions(+), 34 deletions(-)
diff --git a/include/linux/vziolimit.h b/include/linux/vziolimit.h
index 5af8c04..6452b22 100644
--- a/include/linux/vziolimit.h
+++ b/include/linux/vziolimit.h
@@ -23,5 +23,7 @@ struct iolimit_state {
#define VZCTL_SET_IOLIMIT _IOW(VZIOLIMITTYPE, 0, struct iolimit_state)
#define VZCTL_GET_IOLIMIT _IOR(VZIOLIMITTYPE, 1, struct iolimit_state)
+#define VZCTL_SET_IOPSLIMIT _IOW(VZIOLIMITTYPE, 2, struct iolimit_state)
+#define VZCTL_GET_IOPSLIMIT _IOR(VZIOLIMITTYPE, 3, struct iolimit_state)
#endif /* _LINUX_VZIOLIMIT_H */
diff --git a/kernel/ve/vziolimit.c b/kernel/ve/vziolimit.c
index af2b50d..e2eedae 100644
--- a/kernel/ve/vziolimit.c
+++ b/kernel/ve/vziolimit.c
@@ -87,6 +87,7 @@ static unsigned long throttle_timeout(struct throttle *th, unsigned long now)
struct iolimit {
struct throttle throttle;
+ struct throttle iops;
wait_queue_head_t wq;
};
@@ -106,6 +107,14 @@ static void iolimit_wait(struct iolimit *iolimit, unsigned long timeout)
finish_wait(&iolimit->wq, &wait);
}
+static unsigned long iolimit_timeout(struct iolimit *iolimit)
+{
+ unsigned long now = jiffies;
+
+ return max(throttle_timeout(&iolimit->throttle, now),
+ throttle_timeout(&iolimit->iops, now));
+}
+
static int iolimit_virtinfo(struct vnotifier_block *nb,
unsigned long cmd, void *arg, int old_ret)
{
@@ -116,26 +125,35 @@ static int iolimit_virtinfo(struct vnotifier_block *nb,
if (!iolimit)
return old_ret;
- if (!iolimit->throttle.speed)
+ if (!iolimit->throttle.speed && !iolimit->iops.speed)
return NOTIFY_OK;
switch (cmd) {
case VIRTINFO_IO_ACCOUNT:
+ if (!iolimit->throttle.speed)
+ break;
spin_lock_irqsave(&ub->ub_lock, flags);
throttle_charge(&iolimit->throttle, *(size_t*)arg);
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);
+ spin_unlock_irqrestore(&ub->ub_lock, flags);
+ break;
case VIRTINFO_IO_PREPARE:
case VIRTINFO_IO_JOURNAL:
if (current->flags & PF_FLUSHER)
break;
- timeout = throttle_timeout(&iolimit->throttle, jiffies);
+ timeout = iolimit_timeout(iolimit);
if (timeout && !fatal_signal_pending(current))
iolimit_wait(iolimit, timeout);
break;
case VIRTINFO_IO_READAHEAD:
case VIRTINFO_IO_CONGESTION:
- timeout = throttle_timeout(&iolimit->throttle, jiffies);
+ timeout = iolimit_timeout(iolimit);
if (timeout)
return NOTIFY_FAIL;
break;
@@ -148,14 +166,49 @@ static struct vnotifier_block iolimit_virtinfo_nb = {
.notifier_call = iolimit_virtinfo,
};
+
+static void throttle_state(struct user_beancounter *ub,
+ struct throttle *throttle, struct iolimit_state *state)
+{
+ spin_lock_irq(&ub->ub_lock);
+ state->speed = throttle->speed;
+ state->burst = throttle->burst;
+ state->latency = jiffies_to_msecs(throttle->latency);
+ spin_unlock_irq(&ub->ub_lock);
+}
+
+static struct iolimit *iolimit_get(struct user_beancounter *ub)
+{
+ struct iolimit *iolimit = ub->private_data2;
+
+ if (iolimit)
+ return iolimit;
+
+ iolimit = kzalloc(sizeof(struct iolimit), GFP_KERNEL);
+ if (!iolimit)
+ return NULL;
+ init_waitqueue_head(&iolimit->wq);
+
+ spin_lock_irq(&ub->ub_lock);
+ if (ub->private_data2) {
+ kfree(iolimit);
+ iolimit = ub->private_data2;
+ } else
+ ub->private_data2 = iolimit;
+ spin_unlock_irq(&ub->ub_lock);
+
+ return iolimit;
+}
+
static int iolimit_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct user_beancounter *ub;
- struct iolimit *iolimit, *new_iolimit = NULL;
+ struct iolimit *iolimit;
struct iolimit_state state;
int err;
- if (cmd != VZCTL_SET_IOLIMIT && cmd != VZCTL_GET_IOLIMIT)
+ if (cmd != VZCTL_SET_IOLIMIT && cmd != VZCTL_GET_IOLIMIT &&
+ cmd != VZCTL_SET_IOPSLIMIT && cmd != VZCTL_GET_IOPSLIMIT)
return -ENOTTY;
if (copy_from_user(&state, (void __user *)arg, sizeof(state)))
@@ -169,49 +222,47 @@ static int iolimit_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
switch (cmd) {
case VZCTL_SET_IOLIMIT:
- if (!iolimit) {
- new_iolimit = kmalloc(sizeof(struct iolimit), GFP_KERNEL);
- err = -ENOMEM;
- if (!new_iolimit)
- break;
- init_waitqueue_head(&new_iolimit->wq);
- }
-
+ iolimit = iolimit_get(ub);
+ err = -ENOMEM;
+ if (!iolimit)
+ break;
spin_lock_irq(&ub->ub_lock);
-
- if (!iolimit && ub->private_data2) {
- kfree(new_iolimit);
- iolimit = ub->private_data2;
- } else if (!iolimit)
- iolimit = new_iolimit;
-
throttle_setup(&iolimit->throttle, state.speed,
state.burst, state.latency);
-
- if (!ub->private_data2)
- ub->private_data2 = iolimit;
-
spin_unlock_irq(&ub->ub_lock);
-
wake_up_all(&iolimit->wq);
-
err = 0;
break;
- case VZCTL_GET_IOLIMIT:
- err = -ENXIO;
+ case VZCTL_SET_IOPSLIMIT:
+ iolimit = iolimit_get(ub);
+ err = -ENOMEM;
if (!iolimit)
break;
-
spin_lock_irq(&ub->ub_lock);
- state.speed = iolimit->throttle.speed;
- state.burst = iolimit->throttle.burst;
- state.latency = jiffies_to_msecs(iolimit->throttle.latency);
+ throttle_setup(&iolimit->iops, state.speed,
+ state.burst, state.latency);
spin_unlock_irq(&ub->ub_lock);
-
+ wake_up_all(&iolimit->wq);
+ err = 0;
+ break;
+ case VZCTL_GET_IOLIMIT:
+ err = -ENXIO;
+ if (!iolimit)
+ break;
+ throttle_state(ub, &iolimit->throttle, &state);
+ err = -EFAULT;
+ if (copy_to_user((void __user *)arg, &state, sizeof(state)))
+ break;
+ err = 0;
+ break;
+ case VZCTL_GET_IOPSLIMIT:
+ err = -ENXIO;
+ if (!iolimit)
+ break;
+ throttle_state(ub, &iolimit->iops, &state);
err = -EFAULT;
if (copy_to_user((void __user *)arg, &state, sizeof(state)))
break;
-
err = 0;
break;
default:
More information about the Devel
mailing list