From: Zhu Yangyang <zhuyangyan...@huawei.com>

Calling qmp_block_resize() will be blocked for a long time on 
bdrv_drained_begin()
when a network disk is configured and the network failure is just about
to occur.

Therefore, we add a timeout parameter for qmp_block_resize() to control its
execution duration.

The default value of timeout is 0, that is infinite wait, consistent with
previous behavior.

Signed-off-by: Zhu Yangyang <zhuyangyan...@huawei.com>
---
 block/monitor/block-hmp-cmds.c |  2 +-
 blockdev.c                     | 16 ++++++++++++++--
 qapi/block-core.json           |  6 +++++-
 3 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
index 6919a49bf5..c24574d950 100644
--- a/block/monitor/block-hmp-cmds.c
+++ b/block/monitor/block-hmp-cmds.c
@@ -486,7 +486,7 @@ void coroutine_fn hmp_block_resize(Monitor *mon, const 
QDict *qdict)
     int64_t size = qdict_get_int(qdict, "size");
     Error *err = NULL;
 
-    qmp_block_resize(device, NULL, size, &err);
+    qmp_block_resize(device, NULL, size, false, 0, &err);
     hmp_handle_error(mon, err);
 }
 
diff --git a/blockdev.c b/blockdev.c
index 1d1f27cfff..d1314f4e2a 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2252,12 +2252,15 @@ BlockDirtyBitmapSha256 
*qmp_x_debug_block_dirty_bitmap_sha256(const char *node,
 }
 
 void coroutine_fn qmp_block_resize(const char *device, const char *node_name,
-                                   int64_t size, Error **errp)
+                                   int64_t size,
+                                   bool has_timeout, uint32_t timeout,
+                                   Error **errp)
 {
     Error *local_err = NULL;
     BlockBackend *blk;
     BlockDriverState *bs;
     AioContext *old_ctx;
+    uint64_t timeout_ns;
 
     bs = bdrv_lookup_bs(device, node_name, &local_err);
     if (local_err) {
@@ -2282,12 +2285,21 @@ void coroutine_fn qmp_block_resize(const char *device, 
const char *node_name,
         return;
     }
 
-    bdrv_drained_begin(bs);
+    /* Default is 0, that means infinite */
+    timeout_ns = 0;
+    if (has_timeout) {
+        timeout_ns = timeout * NANOSECONDS_PER_SECOND;
+    }
+    if (bdrv_drained_begin_timeout(bs, timeout_ns) < 0) {
+        error_setg(errp, "command timed out");
+        goto out;
+    }
 
     old_ctx = bdrv_co_enter(bs);
     blk_co_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
     bdrv_co_leave(bs, old_ctx);
 
+out:
     bdrv_drained_end(bs);
     blk_co_unref(blk);
 }
diff --git a/qapi/block-core.json b/qapi/block-core.json
index a75ff1cb0c..2ddff59835 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1460,6 +1460,9 @@
 #
 # @size: new image size in bytes
 #
+# @timeout: In seconds. Timeout for block_resize,
+#     0 means no limit. Defaults to 0. (Since 10.1)
+#
 # Errors:
 #     - If @device is not a valid block device, DeviceNotFound
 #
@@ -1474,7 +1477,8 @@
 { 'command': 'block_resize',
   'data': { '*device': 'str',
             '*node-name': 'str',
-            'size': 'int' },
+            'size': 'int',
+            '*timeout': 'uint32' },
   'coroutine': true,
   'allow-preconfig': true }
 
-- 
2.33.0


Reply via email to