From 48fdf7fee7a17b21feef9fba95f6ab732ecad893 Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Fri, 21 Jun 2013 06:20:07 +0200
Subject: [PATCH 11/21] block: keep I/O throttling slice time constant
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <1371795611-7208-12-git-send-email-famz@redhat.com>
Patchwork-id: 52085
O-Subject: [PATCH RHEL-6.5 qemu-kvm v3 11/15] block: keep I/O throttling slice time constant
Bugzilla: 956825
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>

From: Stefan Hajnoczi <stefanha@redhat.com>

It is not necessary to adjust the slice time at runtime.  We already
extend the current slice in order to carry over accounting into the next
slice.  Changing the actual slice time value introduces oscillations.

The guest may experience large changes in throughput or IOPS from one
moment to the next when slice times are adjusted.

Reported-by: Benoît Canet <benoit@irqsave.net>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Tested-By: Benoit Canet <benoit@irqsave.net>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit ae29d6c64bd8d55873a2cb1df50ae4321b497447)

Signed-off-by: Fam Zheng <famz@redhat.com>

Conflicts:
    block.c
    include/block/block_int.h
---
 block.c     | 20 +++++++++-----------
 block_int.h |  1 -
 blockdev.c  |  1 -
 3 files changed, 9 insertions(+), 13 deletions(-)

Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 block.c     |   20 +++++++++-----------
 block_int.h |    1 -
 blockdev.c  |    1 -
 3 files changed, 9 insertions(+), 13 deletions(-)

diff --git a/block.c b/block.c
index 3e582a8..6e56ae9 100644
--- a/block.c
+++ b/block.c
@@ -135,7 +135,6 @@ void bdrv_io_limits_disable(BlockDriverState *bs)
 
     bs->slice_start = 0;
     bs->slice_end   = 0;
-    bs->slice_time  = 0;
 }
 
 static void bdrv_block_timer(void *opaque)
@@ -1157,7 +1156,6 @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top)
     tmp.copy_on_read      = bs_top->copy_on_read;
 
     /* i/o timing parameters */
-    tmp.slice_time        = bs_top->slice_time;
     tmp.slice_start       = bs_top->slice_start;
     tmp.slice_end         = bs_top->slice_end;
     tmp.slice_submitted   = bs_top->slice_submitted;
@@ -1226,7 +1224,6 @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top)
      * to affect or delete the block_timer, as it has been moved to bs_top */
     bs_new->io_limits_enabled = false;
     bs_new->block_timer       = NULL;
-    bs_new->slice_time        = 0;
     bs_new->slice_start       = 0;
     bs_new->slice_end         = 0;
 }
@@ -3603,6 +3600,7 @@ static bool bdrv_exceed_bps_limits(BlockDriverState *bs, int nb_sectors,
                  bool is_write, double elapsed_time, uint64_t *wait)
 {
     uint64_t bps_limit = 0;
+    uint64_t extension;
     double   bytes_limit, bytes_base, bytes_res;
     double   slice_time, wait_time;
 
@@ -3650,8 +3648,10 @@ static bool bdrv_exceed_bps_limits(BlockDriverState *bs, int nb_sectors,
      * info can be kept until the timer fire, so it is increased and tuned
      * based on the result of experiment.
      */
-    bs->slice_time = wait_time * BLOCK_IO_SLICE_TIME * 10;
-    bs->slice_end += bs->slice_time - 3 * BLOCK_IO_SLICE_TIME;
+    extension = wait_time * NANOSECONDS_PER_SECOND;
+    extension = DIV_ROUND_UP(extension, BLOCK_IO_SLICE_TIME) *
+                BLOCK_IO_SLICE_TIME;
+    bs->slice_end += extension;
     if (wait) {
         *wait = wait_time * BLOCK_IO_SLICE_TIME * 10;
     }
@@ -3702,8 +3702,8 @@ static bool bdrv_exceed_iops_limits(BlockDriverState *bs, bool is_write,
         wait_time = 0;
     }
 
-    bs->slice_time = wait_time * BLOCK_IO_SLICE_TIME * 10;
-    bs->slice_end += bs->slice_time - 3 * BLOCK_IO_SLICE_TIME;
+    /* Exceeded current slice, extend it by another slice time */
+    bs->slice_end += BLOCK_IO_SLICE_TIME;
     if (wait) {
         *wait = wait_time * BLOCK_IO_SLICE_TIME * 10;
     }
@@ -3722,12 +3722,10 @@ static bool bdrv_exceed_io_limits(BlockDriverState *bs, int nb_sectors,
     now = qemu_get_clock(vm_clock);
     if ((bs->slice_start < now)
         && (bs->slice_end > now)) {
-        bs->slice_end = now + bs->slice_time;
+        bs->slice_end = now + BLOCK_IO_SLICE_TIME;
     } else {
-        bs->slice_time  =  5 * BLOCK_IO_SLICE_TIME;
         bs->slice_start = now;
-        bs->slice_end   = now + bs->slice_time;
-
+        bs->slice_end   = now + BLOCK_IO_SLICE_TIME;
         memset(&bs->slice_submitted, 0, sizeof(bs->slice_submitted));
     }
 
diff --git a/block_int.h b/block_int.h
index abf6609..610ea66 100644
--- a/block_int.h
+++ b/block_int.h
@@ -280,7 +280,6 @@ struct BlockDriverState {
     void *sync_aiocb;
 
     /* the time for latest disk I/O */
-    int64_t slice_time;
     int64_t slice_start;
     int64_t slice_end;
     BlockIOLimit io_limits;
diff --git a/blockdev.c b/blockdev.c
index 2b7969a..c3c0651 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1272,7 +1272,6 @@ int do_block_set_io_throttle(Monitor *mon,
     }
 
     bs->io_limits = io_limits;
-    bs->slice_time = BLOCK_IO_SLICE_TIME;
 
     if (!bs->io_limits_enabled && bdrv_io_limits_enabled(bs)) {
         bdrv_io_limits_enable(bs);
-- 
1.7.1

