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

Reply via email to