block: Forbid I/O throttling on nodes with multiple parents for 2.6
authorKevin Wolf <kwolf@redhat.com>
Mon, 4 Apr 2016 15:11:13 +0000 (17:11 +0200)
committerKevin Wolf <kwolf@redhat.com>
Tue, 5 Apr 2016 07:22:28 +0000 (09:22 +0200)
As the patches to move I/O throttling to BlockBackend didn't make it in
time for the 2.6 release, but the release adds new ways of configuring
VMs whose behaviour would change once the move is done, we need to
outlaw such configurations temporarily.

The problem exists whenever a BDS has more users than just its BB, for
example it is used as a backing file for another node. (This wasn't
possible in 2.5 yet as we introduced node references to specify a
backing file only recently.) In these cases, the throttling would
apply to these other users now, but after moving throttling to the
BlockBackend the other users wouldn't be throttled any more.

This patch prevents making new references to a throttled node as well as
using monitor commands to throttle a node with multiple parents.

Compared to 2.5 this changes behaviour in some corner cases where
references were allowed before, like bs->file or Quorum children. It
seems reasonable to assume that users didn't use I/O throttling on such
low level nodes. With the upcoming move of throttling into BlockBackend,
such configurations won't be possible anyway.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
block.c
blockdev.c

diff --git a/block.c b/block.c
index d36eb75be96a2c027c206e36deb1ada53c25f0f8..d4939b49bf05b1778306c4b13f2b2dce70af4ca9 100644 (file)
--- a/block.c
+++ b/block.c
@@ -1526,6 +1526,13 @@ static int bdrv_open_inherit(BlockDriverState **pbs, const char *filename,
         if (!bs) {
             return -ENODEV;
         }
+
+        if (bs->throttle_state) {
+            error_setg(errp, "Cannot reference an existing block device for "
+                       "which I/O throttling is enabled");
+            return -EINVAL;
+        }
+
         bdrv_ref(bs);
         *pbs = bs;
         return 0;
index 332068a8375fbe3cf236c9a180b3c90b0ec2497e..f1f520a2653baed5a9df4b0b223f9141a303c6dc 100644 (file)
@@ -2661,6 +2661,13 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
         goto out;
     }
 
+    /* The BlockBackend must be the only parent */
+    assert(QLIST_FIRST(&bs->parents));
+    if (QLIST_NEXT(QLIST_FIRST(&bs->parents), next_parent)) {
+        error_setg(errp, "Cannot throttle device with multiple parents");
+        goto out;
+    }
+
     throttle_config_init(&cfg);
     cfg.buckets[THROTTLE_BPS_TOTAL].avg = bps;
     cfg.buckets[THROTTLE_BPS_READ].avg  = bps_rd;