[PULL,for-2.11-rc2,3/5] block: Check for inserted BlockDriverState in blk_io_limits_disable()

Message ID 20171114103721.13869-4-stefanha@redhat.com
State New
Headers show
Series
  • [PULL,for-2.11-rc2,1/5] block: all I/O should be completed before removing throttle timers.
Related show

Commit Message

Stefan Hajnoczi Nov. 14, 2017, 10:37 a.m.
From: Alberto Garcia <berto@igalia.com>

When you set I/O limits using block_set_io_throttle or the command
line throttling.* options they are kept in the BlockBackend regardless
of whether a BlockDriverState is attached to the backend or not.

Therefore when removing the limits using blk_io_limits_disable() we
need to check if there's a BDS before attempting to drain it, else it
will crash QEMU. This can be reproduced very easily using HMP:

     (qemu) drive_add 0 if=none,throttling.iops-total=5000
     (qemu) drive_del none0

Reported-by: sochin jiang <sochin.jiang@huawei.com>
Signed-off-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Message-id: 0d3a67ce8d948bb33e08672564714dcfb76a3d8c.1510339534.git.berto@igalia.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 block/block-backend.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

Patch

diff --git a/block/block-backend.c b/block/block-backend.c
index ab75da32c9..df92a6280d 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -1980,10 +1980,16 @@  void blk_set_io_limits(BlockBackend *blk, ThrottleConfig *cfg)
 
 void blk_io_limits_disable(BlockBackend *blk)
 {
-    assert(blk->public.throttle_group_member.throttle_state);
-    bdrv_drained_begin(blk_bs(blk));
-    throttle_group_unregister_tgm(&blk->public.throttle_group_member);
-    bdrv_drained_end(blk_bs(blk));
+    BlockDriverState *bs = blk_bs(blk);
+    ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
+    assert(tgm->throttle_state);
+    if (bs) {
+        bdrv_drained_begin(bs);
+    }
+    throttle_group_unregister_tgm(tgm);
+    if (bs) {
+        bdrv_drained_end(bs);
+    }
 }
 
 /* should be called before blk_set_io_limits if a limit is set */