[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