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