* [PATCH v3 0/2] qapi/throttle: Fix qmp_block_set_io_throttle blocked for too long
@ 2025-03-26 9:26 zoudongjie via
2025-03-26 9:26 ` [PATCH v3 1/2] io/block: Refactoring the bdrv_drained_begin() function and implement a timeout mechanism zoudongjie via
` (3 more replies)
0 siblings, 4 replies; 13+ messages in thread
From: zoudongjie via @ 2025-03-26 9:26 UTC (permalink / raw)
To: qemu-devel
Cc: stefanha, kwolf, fam, hreitz, alex.chen, chenjianfei3,
eric.fangyi, luolongmin, mujinsheng, qemu-block, qemu-stable,
renxuming, suxiaodong1, wangjian161, wangyan122, yebiaoxiang,
zhuyangyang14, zoudongjie
From: Zhu Yangyang <zhuyangyang14@huawei.com>
Calling qmp_block_set_io_throttle() will be blocked for a long time
when a network disk is configured and the network failure is just about
to occur.
This series add a timeout parameter for qmp_block_set_io_throttle to control
its execution duration.
Changelog
v3 ---
Unify AIO_WAIT_WHILE_{TIMEOUT/INTERNAL} by replacing AIO_WAIT_WHILE_INTERNAL() with
AIO_WAIT_WHILE_TIMEOUT(..., 0).
v2 ----
1. Support 0 in BDRV_POLL_WHILE_TIMEOUT(), 0 means infinite.
2. Use uint64_t timeout_ns instead of int64 timeout to name variables.
3. Use timer_pending() to check for expiry instead of explicitly checking
against the deadline for BDRV_POLL_WHILE_TIMEOUT().
4. Add documentation for bdrv_drained_begin_timeout(), note that bdrv_drained_end()
must be called when -ETIMEDOUT is returned.
5. Add a timeout parameter to the qmp_block_set_io_throttle() instead of hardcoding
the timeout, and the default value is 0, mean an infinite timeout.
v1 patch link:
https://lore.kernel.org/qemu-devel/20250308101618.721954-1-zoudongjie@huawei.com/
Zhu Yangyang (2):
io/block: Refactoring the bdrv_drained_begin() function and implement
a timeout mechanism.
qapi/throttle: add timeout parameter for qmp_block_set_io_throttle()
block/block-backend.c | 14 ++++-
block/io.c | 58 +++++++++++++++++----
block/qapi-system.c | 10 +++-
include/block/aio-wait.h | 47 ++++++++++++-----
include/block/block-io.h | 22 +++++++-
include/system/block-backend-global-state.h | 1 +
qapi/block-core.json | 5 +-
util/aio-wait.c | 5 ++
8 files changed, 135 insertions(+), 27 deletions(-)
--
2.33.0
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH v3 1/2] io/block: Refactoring the bdrv_drained_begin() function and implement a timeout mechanism. 2025-03-26 9:26 [PATCH v3 0/2] qapi/throttle: Fix qmp_block_set_io_throttle blocked for too long zoudongjie via @ 2025-03-26 9:26 ` zoudongjie via 2025-03-26 9:26 ` [PATCH v3 2/2] qapi/throttle: add timeout parameter for qmp_block_set_io_throttle() zoudongjie via ` (2 subsequent siblings) 3 siblings, 0 replies; 13+ messages in thread From: zoudongjie via @ 2025-03-26 9:26 UTC (permalink / raw) To: qemu-devel Cc: stefanha, kwolf, fam, hreitz, alex.chen, chenjianfei3, eric.fangyi, luolongmin, mujinsheng, qemu-block, qemu-stable, renxuming, suxiaodong1, wangjian161, wangyan122, yebiaoxiang, zhuyangyang14, zoudongjie From: Zhu Yangyang <zhuyangyang14@huawei.com> The bdrv_drained_begin() function is a blocking function. In scenarios where network storage is used and network links fail, it may block for a long time. Therefore, we add a timeout parameter to control the duration of the block. Since bdrv_drained_begin() has been widely adopted, both bdrv_drained_begin() and bdrv_drained_begin_timeout() will be retained. Signed-off-by: Zhu Yangyang <zhuyangyang14@huawei.com> --- block/io.c | 58 +++++++++++++++++++++++++++++++++------- include/block/aio-wait.h | 47 +++++++++++++++++++++++--------- include/block/block-io.h | 22 ++++++++++++++- util/aio-wait.c | 5 ++++ 4 files changed, 108 insertions(+), 24 deletions(-) diff --git a/block/io.c b/block/io.c index 1ba8d1aeea..912b76c4a4 100644 --- a/block/io.c +++ b/block/io.c @@ -255,6 +255,8 @@ typedef struct { bool begin; bool poll; BdrvChild *parent; + uint64_t timeout_ns; + int ret; } BdrvCoDrainData; /* Returns true if BDRV_POLL_WHILE() should go into a blocking aio_poll() */ @@ -283,6 +285,10 @@ static bool bdrv_drain_poll_top_level(BlockDriverState *bs, return bdrv_drain_poll(bs, ignore_parent, false); } +static int bdrv_do_drained_begin_timeout(BlockDriverState *bs, + BdrvChild *parent, + bool poll, + uint64_t timeout_ns); static void bdrv_do_drained_begin(BlockDriverState *bs, BdrvChild *parent, bool poll); static void bdrv_do_drained_end(BlockDriverState *bs, BdrvChild *parent); @@ -296,7 +302,9 @@ static void bdrv_co_drain_bh_cb(void *opaque) if (bs) { bdrv_dec_in_flight(bs); if (data->begin) { - bdrv_do_drained_begin(bs, data->parent, data->poll); + data->ret = bdrv_do_drained_begin_timeout(bs, data->parent, + data->poll, + data->timeout_ns); } else { assert(!data->poll); bdrv_do_drained_end(bs, data->parent); @@ -310,10 +318,11 @@ static void bdrv_co_drain_bh_cb(void *opaque) aio_co_wake(co); } -static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs, - bool begin, - BdrvChild *parent, - bool poll) +static int coroutine_fn bdrv_co_yield_to_drain_timeout(BlockDriverState *bs, + bool begin, + BdrvChild *parent, + bool poll, + uint64_t timeout_ns) { BdrvCoDrainData data; Coroutine *self = qemu_coroutine_self(); @@ -329,6 +338,8 @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs, .begin = begin, .parent = parent, .poll = poll, + .timeout_ns = timeout_ns, + .ret = 0 }; if (bs) { @@ -342,16 +353,27 @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs, /* If we are resumed from some other event (such as an aio completion or a * timer callback), it is a bug in the caller that should be fixed. */ assert(data.done); + return data.ret; } -static void bdrv_do_drained_begin(BlockDriverState *bs, BdrvChild *parent, - bool poll) +static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs, + bool begin, + BdrvChild *parent, + bool poll) +{ + bdrv_co_yield_to_drain_timeout(bs, begin, parent, poll, 0); +} + +static int bdrv_do_drained_begin_timeout(BlockDriverState *bs, + BdrvChild *parent, + bool poll, + uint64_t timeout_ns) { IO_OR_GS_CODE(); if (qemu_in_coroutine()) { - bdrv_co_yield_to_drain(bs, true, parent, poll); - return; + return bdrv_co_yield_to_drain_timeout(bs, true, parent, poll, + timeout_ns); } GLOBAL_STATE_CODE(); @@ -375,8 +397,17 @@ static void bdrv_do_drained_begin(BlockDriverState *bs, BdrvChild *parent, * nodes. */ if (poll) { - BDRV_POLL_WHILE(bs, bdrv_drain_poll_top_level(bs, parent)); + return BDRV_POLL_WHILE_TIMEOUT(bs, + bdrv_drain_poll_top_level(bs, parent), + timeout_ns); } + return 0; +} + +static void bdrv_do_drained_begin(BlockDriverState *bs, BdrvChild *parent, + bool poll) +{ + bdrv_do_drained_begin_timeout(bs, parent, poll, 0); } void bdrv_do_drained_begin_quiesce(BlockDriverState *bs, BdrvChild *parent) @@ -391,6 +422,13 @@ bdrv_drained_begin(BlockDriverState *bs) bdrv_do_drained_begin(bs, NULL, true); } +int coroutine_mixed_fn +bdrv_drained_begin_timeout(BlockDriverState *bs, uint64_t timeout_ns) +{ + IO_OR_GS_CODE(); + return bdrv_do_drained_begin_timeout(bs, NULL, true, timeout_ns); +} + /** * This function does not poll, nor must any of its recursively called * functions. diff --git a/include/block/aio-wait.h b/include/block/aio-wait.h index cf5e8bde1c..7610880b61 100644 --- a/include/block/aio-wait.h +++ b/include/block/aio-wait.h @@ -59,10 +59,12 @@ typedef struct { extern AioWait global_aio_wait; /** - * AIO_WAIT_WHILE_INTERNAL: + * AIO_WAIT_WHILE_TIMEOUT: * @ctx: the aio context, or NULL if multiple aio contexts (for which the * caller does not hold a lock) are involved in the polling condition. * @cond: wait while this conditional expression is true + * @timeout_ns: maximum duration to wait, in nanoseconds, except the value + * is unsigned, 0 means infinite. * * Wait while a condition is true. Use this to implement synchronous * operations that require event loop activity. @@ -74,37 +76,54 @@ extern AioWait global_aio_wait; * thread (with @ctx acquired exactly once). This function cannot be used to * wait on conditions between two IOThreads since that could lead to deadlock, * go via the main loop instead. + * + * Returns: 0 if succeeded; -ETIMEDOUT when a timeout occurs. */ -#define AIO_WAIT_WHILE_INTERNAL(ctx, cond) ({ \ - bool waited_ = false; \ +#define AIO_WAIT_WHILE_TIMEOUT(ctx, cond, timeout_ns) ({ \ + int ret_ = 0; \ + uint64_t timeout_ = (timeout_ns); \ AioWait *wait_ = &global_aio_wait; \ AioContext *ctx_ = (ctx); \ + AioContext *current_ctx_ = NULL; \ + QEMUTimer timer_; \ /* Increment wait_->num_waiters before evaluating cond. */ \ qatomic_inc(&wait_->num_waiters); \ /* Paired with smp_mb in aio_wait_kick(). */ \ smp_mb__after_rmw(); \ if (ctx_ && in_aio_context_home_thread(ctx_)) { \ - while ((cond)) { \ - aio_poll(ctx_, true); \ - waited_ = true; \ - } \ + current_ctx_ = ctx_; \ } else { \ assert(qemu_get_current_aio_context() == \ qemu_get_aio_context()); \ - while ((cond)) { \ - aio_poll(qemu_get_aio_context(), true); \ - waited_ = true; \ + current_ctx_ = qemu_get_aio_context(); \ + } \ + if (timeout_ > 0) { \ + timer_init_full(&timer_, ¤t_ctx_->tlg, \ + QEMU_CLOCK_REALTIME, \ + SCALE_NS, 0, aio_wait_timer_cb, NULL); \ + timer_mod_ns(&timer_, \ + qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + \ + timeout_); \ + } \ + while ((cond)) { \ + aio_poll(current_ctx_, true); \ + if (timeout_ > 0 && !timer_pending(&timer_)) { \ + ret_ = -ETIMEDOUT; \ + break; \ } \ } \ + if (timeout_ > 0) { \ + timer_del(&timer_); \ + } \ qatomic_dec(&wait_->num_waiters); \ - waited_; }) + ret_; }) #define AIO_WAIT_WHILE(ctx, cond) \ - AIO_WAIT_WHILE_INTERNAL(ctx, cond) + AIO_WAIT_WHILE_TIMEOUT(ctx, cond, 0) /* TODO replace this with AIO_WAIT_WHILE() in a future patch */ #define AIO_WAIT_WHILE_UNLOCKED(ctx, cond) \ - AIO_WAIT_WHILE_INTERNAL(ctx, cond) + AIO_WAIT_WHILE_TIMEOUT(ctx, cond, 0) /** * aio_wait_kick: @@ -149,4 +168,6 @@ static inline bool in_aio_context_home_thread(AioContext *ctx) } } +void aio_wait_timer_cb(void *opaque); + #endif /* QEMU_AIO_WAIT_H */ diff --git a/include/block/block-io.h b/include/block/block-io.h index b49e0537dd..844e9cf350 100644 --- a/include/block/block-io.h +++ b/include/block/block-io.h @@ -354,6 +354,11 @@ bdrv_co_copy_range(BdrvChild *src, int64_t src_offset, AIO_WAIT_WHILE(bdrv_get_aio_context(bs_), \ cond); }) +#define BDRV_POLL_WHILE_TIMEOUT(bs, cond, timeout_ns) ({ \ + BlockDriverState *bs_ = (bs); \ + AIO_WAIT_WHILE_TIMEOUT(bdrv_get_aio_context(bs_), \ + cond, timeout_ns); }) + void bdrv_drain(BlockDriverState *bs); int co_wrapper_mixed_bdrv_rdlock @@ -432,7 +437,22 @@ bdrv_drain_poll(BlockDriverState *bs, BdrvChild *ignore_parent, void bdrv_drained_begin(BlockDriverState *bs); /** - * bdrv_do_drained_begin_quiesce: + * bdrv_drained_begin_timeout: + * + * Added timeout parameter for bdrv_drained_begin() to make a time limited. + * + * @timeout_ns: maximum duration to wait; 0 means infinite, equal to call + * bdrv_drained_begin(). + * + * Returns: 0 if succeeded; -ETIMEDOUT when a timeout occurs. + * + * Note: when the timeout fails, we've already begin aquiesced section, so we + * still need to call bdrv_drained_end() to end the quiescent section. + */ +int bdrv_drained_begin_timeout(BlockDriverState *bs, uint64_t timeout_ns); + +/** + * bdrv_do_drained_badegin_quiesce: * * Quiesces a BDS like bdrv_drained_begin(), but does not wait for already * running requests to complete. diff --git a/util/aio-wait.c b/util/aio-wait.c index b5336cf5fd..64c3714fb8 100644 --- a/util/aio-wait.c +++ b/util/aio-wait.c @@ -84,3 +84,8 @@ void aio_wait_bh_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque) aio_bh_schedule_oneshot(ctx, aio_wait_bh, &data); AIO_WAIT_WHILE_UNLOCKED(NULL, !data.done); } + +void aio_wait_timer_cb(void *opaque) +{ + /* The point is to make AIO_WAIT_WHILE_TIMEOUT()'s aio_poll() return */ +} -- 2.33.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 2/2] qapi/throttle: add timeout parameter for qmp_block_set_io_throttle() 2025-03-26 9:26 [PATCH v3 0/2] qapi/throttle: Fix qmp_block_set_io_throttle blocked for too long zoudongjie via 2025-03-26 9:26 ` [PATCH v3 1/2] io/block: Refactoring the bdrv_drained_begin() function and implement a timeout mechanism zoudongjie via @ 2025-03-26 9:26 ` zoudongjie via 2025-03-26 9:53 ` Markus Armbruster 2025-03-26 15:06 ` [PATCH v3 0/2] qapi/throttle: Fix qmp_block_set_io_throttle blocked for too long Stefan Hajnoczi 2025-05-12 9:40 ` Michael Tokarev 3 siblings, 1 reply; 13+ messages in thread From: zoudongjie via @ 2025-03-26 9:26 UTC (permalink / raw) To: qemu-devel Cc: stefanha, kwolf, fam, hreitz, alex.chen, chenjianfei3, eric.fangyi, luolongmin, mujinsheng, qemu-block, qemu-stable, renxuming, suxiaodong1, wangjian161, wangyan122, yebiaoxiang, zhuyangyang14, zoudongjie From: Zhu Yangyang <zhuyangyang14@huawei.com> Calling qmp_block_set_io_throttle() will be blocked for a long time when a network disk is configured and the network failure is just about to occur. Therefore, we add a timeout parameter for qmp_block_set_io_throttle 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 <zhuyangyang14@huawei.com> --- block/block-backend.c | 14 +++++++++++++- block/qapi-system.c | 10 +++++++++- include/system/block-backend-global-state.h | 1 + qapi/block-core.json | 5 ++++- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/block/block-backend.c b/block/block-backend.c index a402db13f2..fc1554ea55 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -2679,20 +2679,32 @@ void blk_set_io_limits(BlockBackend *blk, ThrottleConfig *cfg) } void blk_io_limits_disable(BlockBackend *blk) +{ + blk_io_limits_disable_timeout(blk, 0); +} + +int blk_io_limits_disable_timeout(BlockBackend *blk, uint64_t timeout_ns) { BlockDriverState *bs = blk_bs(blk); ThrottleGroupMember *tgm = &blk->public.throttle_group_member; + int ret = 0; + assert(tgm->throttle_state); GLOBAL_STATE_CODE(); if (bs) { bdrv_ref(bs); - bdrv_drained_begin(bs); + ret = bdrv_drained_begin_timeout(bs, timeout_ns); + if (ret < 0) { + goto out; + } } throttle_group_unregister_tgm(tgm); +out: if (bs) { bdrv_drained_end(bs); bdrv_unref(bs); } + return ret; } /* should be called before blk_set_io_limits if a limit is set */ diff --git a/block/qapi-system.c b/block/qapi-system.c index 54b7409b2b..3b7ba0959c 100644 --- a/block/qapi-system.c +++ b/block/qapi-system.c @@ -423,6 +423,7 @@ void qmp_block_set_io_throttle(BlockIOThrottle *arg, Error **errp) ThrottleConfig cfg; BlockDriverState *bs; BlockBackend *blk; + uint64_t timeout_ns; blk = qmp_get_blk(arg->device, arg->id, errp); if (!blk) { @@ -444,6 +445,10 @@ void qmp_block_set_io_throttle(BlockIOThrottle *arg, Error **errp) cfg.buckets[THROTTLE_OPS_READ].avg = arg->iops_rd; cfg.buckets[THROTTLE_OPS_WRITE].avg = arg->iops_wr; + timeout_ns = 0; /* 0 means infinite */ + if (arg->has_timeout) { + timeout_ns = arg->timeout * NANOSECONDS_PER_SECOND; + } if (arg->has_bps_max) { cfg.buckets[THROTTLE_BPS_TOTAL].max = arg->bps_max; } @@ -502,7 +507,10 @@ void qmp_block_set_io_throttle(BlockIOThrottle *arg, Error **errp) blk_set_io_limits(blk, &cfg); } else if (blk_get_public(blk)->throttle_group_member.throttle_state) { /* If all throttling settings are set to 0, disable I/O limits */ - blk_io_limits_disable(blk); + if (blk_io_limits_disable_timeout(blk, timeout_ns) < 0) { + error_setg(errp, "Blk io limits disable timeout"); + return; + } } } diff --git a/include/system/block-backend-global-state.h b/include/system/block-backend-global-state.h index 35b5e8380b..8a2a6cbda4 100644 --- a/include/system/block-backend-global-state.h +++ b/include/system/block-backend-global-state.h @@ -110,6 +110,7 @@ int blk_probe_geometry(BlockBackend *blk, HDGeometry *geo); void blk_set_io_limits(BlockBackend *blk, ThrottleConfig *cfg); void blk_io_limits_disable(BlockBackend *blk); +int blk_io_limits_disable_timeout(BlockBackend *blk, uint64_t timeout_ns); void blk_io_limits_enable(BlockBackend *blk, const char *group); void blk_io_limits_update_group(BlockBackend *blk, const char *group); void blk_set_force_allow_inactivate(BlockBackend *blk); diff --git a/qapi/block-core.json b/qapi/block-core.json index b1937780e1..88ef593efd 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -2626,6 +2626,9 @@ # # @group: throttle group name (Since 2.4) # +# @timeout: In seconds. Timeout for block_set_io_throttle, +# 0 means no limit. Defaults to 0. (Since 10.0) +# # Features: # # @deprecated: Member @device is deprecated. Use @id instead. @@ -2642,7 +2645,7 @@ '*bps_max_length': 'int', '*bps_rd_max_length': 'int', '*bps_wr_max_length': 'int', '*iops_max_length': 'int', '*iops_rd_max_length': 'int', '*iops_wr_max_length': 'int', - '*iops_size': 'int', '*group': 'str' } } + '*iops_size': 'int', '*group': 'str', '*timeout': 'uint32'} } ## # @ThrottleLimits: -- 2.33.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v3 2/2] qapi/throttle: add timeout parameter for qmp_block_set_io_throttle() 2025-03-26 9:26 ` [PATCH v3 2/2] qapi/throttle: add timeout parameter for qmp_block_set_io_throttle() zoudongjie via @ 2025-03-26 9:53 ` Markus Armbruster 2025-03-27 7:56 ` zoudongjie via 0 siblings, 1 reply; 13+ messages in thread From: Markus Armbruster @ 2025-03-26 9:53 UTC (permalink / raw) To: zoudongjie via Cc: zoudongjie, stefanha, kwolf, fam, hreitz, alex.chen, chenjianfei3, eric.fangyi, luolongmin, mujinsheng, qemu-block, qemu-stable, renxuming, suxiaodong1, wangjian161, wangyan122, yebiaoxiang, zhuyangyang14 zoudongjie via <qemu-devel@nongnu.org> writes: > From: Zhu Yangyang <zhuyangyang14@huawei.com> > > Calling qmp_block_set_io_throttle() will be blocked for a long time > when a network disk is configured and the network failure is just about > to occur. > > Therefore, we add a timeout parameter for qmp_block_set_io_throttle to control > its execution duration. What's the QMP reply when a block_set_io_throttle command times out? > > The default value of timeout is 0, that is infinite wait, consistent with > previous behavior. > > Signed-off-by: Zhu Yangyang <zhuyangyang14@huawei.com> [...] > diff --git a/qapi/block-core.json b/qapi/block-core.json > index b1937780e1..88ef593efd 100644 > --- a/qapi/block-core.json > +++ b/qapi/block-core.json > @@ -2626,6 +2626,9 @@ > # > # @group: throttle group name (Since 2.4) > # > +# @timeout: In seconds. Timeout for block_set_io_throttle, > +# 0 means no limit. Defaults to 0. (Since 10.0) Make that 10.1, since it won't make 10.0. > +# > # Features: > # > # @deprecated: Member @device is deprecated. Use @id instead. > @@ -2642,7 +2645,7 @@ > '*bps_max_length': 'int', '*bps_rd_max_length': 'int', > '*bps_wr_max_length': 'int', '*iops_max_length': 'int', > '*iops_rd_max_length': 'int', '*iops_wr_max_length': 'int', > - '*iops_size': 'int', '*group': 'str' } } > + '*iops_size': 'int', '*group': 'str', '*timeout': 'uint32'} } > > ## > # @ThrottleLimits: ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 2/2] qapi/throttle: add timeout parameter for qmp_block_set_io_throttle() 2025-03-26 9:53 ` Markus Armbruster @ 2025-03-27 7:56 ` zoudongjie via 2025-03-27 8:04 ` Markus Armbruster 0 siblings, 1 reply; 13+ messages in thread From: zoudongjie via @ 2025-03-27 7:56 UTC (permalink / raw) To: armbru Cc: alex.chen, chenjianfei3, eric.fangyi, fam, hreitz, kwolf, luolongmin, mujinsheng, qemu-block, qemu-devel, qemu-stable, renxuming, stefanha, suxiaodong1, wangjian161, wangyan122, yebiaoxiang, zhuyangyang14, zoudongjie On Wed, Mar 26, 2025 at 10:53:20 +0100, Markus wrote: > zoudongjie via <qemu-devel@nongnu.org> writes: > > > From: Zhu Yangyang <zhuyangyang14@huawei.com> > > > > Calling qmp_block_set_io_throttle() will be blocked for a long time > > when a network disk is configured and the network failure is just about > > to occur. > > > > Therefore, we add a timeout parameter for qmp_block_set_io_throttle to control > > its execution duration. > > What's the QMP reply when a block_set_io_throttle command times out? The reply is: {"id":"libvirt-484","error":{"class":"GenericError","desc":"Blk io limits disable timeout"}} > > > > > The default value of timeout is 0, that is infinite wait, consistent with > > previous behavior. > > > > Signed-off-by: Zhu Yangyang <zhuyangyang14@huawei.com> > > [...] > > > diff --git a/qapi/block-core.json b/qapi/block-core.json > > index b1937780e1..88ef593efd 100644 > > --- a/qapi/block-core.json > > +++ b/qapi/block-core.json > > @@ -2626,6 +2626,9 @@ > > # > > # @group: throttle group name (Since 2.4) > > # > > +# @timeout: In seconds. Timeout for block_set_io_throttle, > > +# 0 means no limit. Defaults to 0. (Since 10.0) > > Make that 10.1, since it won't make 10.0. Ok, I'll correct it in the next version. > > > +# > > # Features: > > # > > # @deprecated: Member @device is deprecated. Use @id instead. > > @@ -2642,7 +2645,7 @@ > > '*bps_max_length': 'int', '*bps_rd_max_length': 'int', > > '*bps_wr_max_length': 'int', '*iops_max_length': 'int', > > '*iops_rd_max_length': 'int', '*iops_wr_max_length': 'int', > > - '*iops_size': 'int', '*group': 'str' } } > > + '*iops_size': 'int', '*group': 'str', '*timeout': 'uint32'} } > > > > ## > > # @ThrottleLimits: ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 2/2] qapi/throttle: add timeout parameter for qmp_block_set_io_throttle() 2025-03-27 7:56 ` zoudongjie via @ 2025-03-27 8:04 ` Markus Armbruster 2025-03-27 12:34 ` zoudongjie via 2025-04-01 7:21 ` zoudongjie via 0 siblings, 2 replies; 13+ messages in thread From: Markus Armbruster @ 2025-03-27 8:04 UTC (permalink / raw) To: zoudongjie Cc: alex.chen, chenjianfei3, eric.fangyi, fam, hreitz, kwolf, luolongmin, mujinsheng, qemu-block, qemu-devel, qemu-stable, renxuming, stefanha, suxiaodong1, wangjian161, wangyan122, yebiaoxiang, zhuyangyang14 zoudongjie <zoudongjie@huawei.com> writes: > On Wed, Mar 26, 2025 at 10:53:20 +0100, Markus wrote: >> zoudongjie via <qemu-devel@nongnu.org> writes: >> >> > From: Zhu Yangyang <zhuyangyang14@huawei.com> >> > >> > Calling qmp_block_set_io_throttle() will be blocked for a long time >> > when a network disk is configured and the network failure is just about >> > to occur. What other commands could similarly block? >> > Therefore, we add a timeout parameter for qmp_block_set_io_throttle to control >> > its execution duration. >> >> What's the QMP reply when a block_set_io_throttle command times out? > > The reply is: > {"id":"libvirt-484","error":{"class":"GenericError","desc":"Blk io limits disable timeout"}} I find the error message confusing. Suggest "command timed out". >> > >> > The default value of timeout is 0, that is infinite wait, consistent with >> > previous behavior. >> > >> > Signed-off-by: Zhu Yangyang <zhuyangyang14@huawei.com> [...] ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 2/2] qapi/throttle: add timeout parameter for qmp_block_set_io_throttle() 2025-03-27 8:04 ` Markus Armbruster @ 2025-03-27 12:34 ` zoudongjie via 2025-03-27 13:43 ` Markus Armbruster 2025-04-01 7:21 ` zoudongjie via 1 sibling, 1 reply; 13+ messages in thread From: zoudongjie via @ 2025-03-27 12:34 UTC (permalink / raw) To: armbru Cc: alex.chen, chenjianfei3, eric.fangyi, fam, hreitz, kwolf, luolongmin, mujinsheng, qemu-block, qemu-devel, qemu-stable, renxuming, stefanha, suxiaodong1, wangjian161, wangyan122, yebiaoxiang, zhuyangyang14, zoudongjie On Thu, 27 Mar 2025 09:04:51 +0100, Markus wrote: > zoudongjie <zoudongjie@huawei.com> writes: > > > On Wed, Mar 26, 2025 at 10:53:20 +0100, Markus wrote: > >> zoudongjie via <qemu-devel@nongnu.org> writes: > >> > >> > From: Zhu Yangyang <zhuyangyang14@huawei.com> > >> > > >> > Calling qmp_block_set_io_throttle() will be blocked for a long time > >> > when a network disk is configured and the network failure is just about > >> > to occur. > > What other commands could similarly block? In theory, any command may be blocked if it calls bdrv_drained_begin(). I did a quick check, qmp_block_resize() could similarly block, since it called bdrv_drained_begin(), I'm going to verify it later. > > >> > Therefore, we add a timeout parameter for qmp_block_set_io_throttle to control > >> > its execution duration. > >> > >> What's the QMP reply when a block_set_io_throttle command times out? > > > > The reply is: > > {"id":"libvirt-484","error":{"class":"GenericError","desc":"Blk io limits disable timeout"}} > > I find the error message confusing. Suggest "command timed out". This message doesn't provide more details about the error, especially for developers. How about using "command timed out: disable I/O limits" > > >> > > >> > The default value of timeout is 0, that is infinite wait, consistent with > >> > previous behavior. > >> > > >> > Signed-off-by: Zhu Yangyang <zhuyangyang14@huawei.com> > > [...] ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 2/2] qapi/throttle: add timeout parameter for qmp_block_set_io_throttle() 2025-03-27 12:34 ` zoudongjie via @ 2025-03-27 13:43 ` Markus Armbruster 2025-04-01 8:15 ` zoudongjie via 0 siblings, 1 reply; 13+ messages in thread From: Markus Armbruster @ 2025-03-27 13:43 UTC (permalink / raw) To: zoudongjie Cc: alex.chen, chenjianfei3, eric.fangyi, fam, hreitz, kwolf, luolongmin, mujinsheng, qemu-block, qemu-devel, qemu-stable, renxuming, stefanha, suxiaodong1, wangjian161, wangyan122, yebiaoxiang, zhuyangyang14 zoudongjie <zoudongjie@huawei.com> writes: > On Thu, 27 Mar 2025 09:04:51 +0100, Markus wrote: >> zoudongjie <zoudongjie@huawei.com> writes: >> >> > On Wed, Mar 26, 2025 at 10:53:20 +0100, Markus wrote: >> >> zoudongjie via <qemu-devel@nongnu.org> writes: >> >> >> >> > From: Zhu Yangyang <zhuyangyang14@huawei.com> >> >> > >> >> > Calling qmp_block_set_io_throttle() will be blocked for a long time >> >> > when a network disk is configured and the network failure is just about >> >> > to occur. >> >> What other commands could similarly block? > > In theory, any command may be blocked if it calls bdrv_drained_begin(). > I did a quick check, qmp_block_resize() could similarly block, since it called > bdrv_drained_begin(), I'm going to verify it later. Please do. Should all these commands support time out? >> >> > Therefore, we add a timeout parameter for qmp_block_set_io_throttle to control >> >> > its execution duration. >> >> >> >> What's the QMP reply when a block_set_io_throttle command times out? >> > >> > The reply is: >> > {"id":"libvirt-484","error":{"class":"GenericError","desc":"Blk io limits disable timeout"}} >> >> I find the error message confusing. Suggest "command timed out". > > This message doesn't provide more details about the error, especially for developers. > How about using "command timed out: disable I/O limits" I don't get what "disable I/O limits" is trying to tell the user. Can you explain? >> >> > The default value of timeout is 0, that is infinite wait, consistent with >> >> > previous behavior. >> >> > >> >> > Signed-off-by: Zhu Yangyang <zhuyangyang14@huawei.com> >> >> [...] ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 2/2] qapi/throttle: add timeout parameter for qmp_block_set_io_throttle() 2025-03-27 13:43 ` Markus Armbruster @ 2025-04-01 8:15 ` zoudongjie via 0 siblings, 0 replies; 13+ messages in thread From: zoudongjie via @ 2025-04-01 8:15 UTC (permalink / raw) To: armbru Cc: alex.chen, chenjianfei3, eric.fangyi, fam, hreitz, kwolf, luolongmin, mujinsheng, qemu-block, qemu-devel, qemu-stable, renxuming, stefanha, suxiaodong1, wangjian161, wangyan122, yebiaoxiang, zhuyangyang14, zoudongjie I'm sorry for the delay in replying. On Thu, 27 Mar 2025 14:43:54 +0100, Markus wrote: > zoudongjie <zoudongjie@huawei.com> writes: > > On Thu, 27 Mar 2025 09:04:51 +0100, Markus wrote: > >> zoudongjie <zoudongjie@huawei.com> writes: > >> > >> > On Wed, Mar 26, 2025 at 10:53:20 +0100, Markus wrote: > >> >> zoudongjie via <qemu-devel@nongnu.org> writes: > >> >> > >> >> > From: Zhu Yangyang <zhuyangyang14@huawei.com> > >> >> > > >> >> > Calling qmp_block_set_io_throttle() will be blocked for a long time > >> >> > when a network disk is configured and the network failure is just about > >> >> > to occur. > >> > >> What other commands could similarly block? > > > > In theory, any command may be blocked if it calls bdrv_drained_begin(). > > I did a quick check, qmp_block_resize() could similarly block, since it called > > bdrv_drained_begin(), I'm going to verify it later. > > Please do. > > Should all these commands support time out? Yes, I think it is. Later in v4, I'll add timeout support for qmp_block_resize(). If I find a similar block command in the future, I'll email again. > > >> >> > Therefore, we add a timeout parameter for qmp_block_set_io_throttle to control > >> >> > its execution duration. > >> >> > >> >> What's the QMP reply when a block_set_io_throttle command times out? > >> > > >> > The reply is: > >> > {"id":"libvirt-484","error":{"class":"GenericError","desc":"Blk io limits disable timeout"}} > >> > >> I find the error message confusing. Suggest "command timed out". > > > > This message doesn't provide more details about the error, especially for developers. > > How about using "command timed out: disable I/O limits" > > I don't get what "disable I/O limits" is trying to tell the user. Can > you explain? In fact, block_set_io_throttle() has two branches: enable io limits and disable io limits. If there is a possibility of timeout in both branches in command, detailed reason may be useful. But now "command timed out" is enough and I will use it in v4. > > >> >> > The default value of timeout is 0, that is infinite wait, consistent with > >> >> > previous behavior. > >> >> > > >> >> > Signed-off-by: Zhu Yangyang <zhuyangyang14@huawei.com> > >> > >> [...] ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 2/2] qapi/throttle: add timeout parameter for qmp_block_set_io_throttle() 2025-03-27 8:04 ` Markus Armbruster 2025-03-27 12:34 ` zoudongjie via @ 2025-04-01 7:21 ` zoudongjie via 1 sibling, 0 replies; 13+ messages in thread From: zoudongjie via @ 2025-04-01 7:21 UTC (permalink / raw) To: armbru Cc: alex.chen, chenjianfei3, eric.fangyi, fam, hreitz, kwolf, luolongmin, mujinsheng, qemu-block, qemu-devel, qemu-stable, renxuming, stefanha, suxiaodong1, wangjian161, wangyan122, yebiaoxiang, zhuyangyang14, zoudongjie On Thu, 27 Mar 2025 09:04:51 +0100, Markus wrote: > zoudongjie <zoudongjie@huawei.com> writes: > > > On Wed, Mar 26, 2025 at 10:53:20 +0100, Markus wrote: > >> zoudongjie via <qemu-devel@nongnu.org> writes: > >> > >> > From: Zhu Yangyang <zhuyangyang14@huawei.com> > >> > > >> > Calling qmp_block_set_io_throttle() will be blocked for a long time > >> > when a network disk is configured and the network failure is just about > >> > to occur. > > What other commands could similarly block? In theory, any command may be blocked if it calls bdrv_drained_begin(). I did a quick check, qmp_block_resize() could similarly block, since it called bdrv_drained_begin(), I'm going to verify it later. > > >> > Therefore, we add a timeout parameter for qmp_block_set_io_throttle to control > >> > its execution duration. > >> > >> What's the QMP reply when a block_set_io_throttle command times out? > > > > The reply is: > > {"id":"libvirt-484","error":{"class":"GenericError","desc":"Blk io limits disable timeout"}} > > I find the error message confusing. Suggest "command timed out". This message doesn't provide more details about the error, especially for developers. How about using "command timed out: disable I/O limits" > > >> > > >> > The default value of timeout is 0, that is infinite wait, consistent with > >> > previous behavior. > >> > > >> > Signed-off-by: Zhu Yangyang <zhuyangyang14@huawei.com> > > [...] ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 0/2] qapi/throttle: Fix qmp_block_set_io_throttle blocked for too long 2025-03-26 9:26 [PATCH v3 0/2] qapi/throttle: Fix qmp_block_set_io_throttle blocked for too long zoudongjie via 2025-03-26 9:26 ` [PATCH v3 1/2] io/block: Refactoring the bdrv_drained_begin() function and implement a timeout mechanism zoudongjie via 2025-03-26 9:26 ` [PATCH v3 2/2] qapi/throttle: add timeout parameter for qmp_block_set_io_throttle() zoudongjie via @ 2025-03-26 15:06 ` Stefan Hajnoczi 2025-05-12 9:40 ` Michael Tokarev 3 siblings, 0 replies; 13+ messages in thread From: Stefan Hajnoczi @ 2025-03-26 15:06 UTC (permalink / raw) To: zoudongjie Cc: qemu-devel, kwolf, fam, hreitz, alex.chen, chenjianfei3, eric.fangyi, luolongmin, mujinsheng, qemu-block, qemu-stable, renxuming, suxiaodong1, wangjian161, wangyan122, yebiaoxiang, zhuyangyang14 [-- Attachment #1: Type: text/plain, Size: 2110 bytes --] On Wed, Mar 26, 2025 at 05:26:32PM +0800, zoudongjie wrote: > From: Zhu Yangyang <zhuyangyang14@huawei.com> > > Calling qmp_block_set_io_throttle() will be blocked for a long time > when a network disk is configured and the network failure is just about > to occur. > > This series add a timeout parameter for qmp_block_set_io_throttle to control > its execution duration. > > Changelog > v3 --- > Unify AIO_WAIT_WHILE_{TIMEOUT/INTERNAL} by replacing AIO_WAIT_WHILE_INTERNAL() with > AIO_WAIT_WHILE_TIMEOUT(..., 0). > > v2 ---- > 1. Support 0 in BDRV_POLL_WHILE_TIMEOUT(), 0 means infinite. > 2. Use uint64_t timeout_ns instead of int64 timeout to name variables. > 3. Use timer_pending() to check for expiry instead of explicitly checking > against the deadline for BDRV_POLL_WHILE_TIMEOUT(). > 4. Add documentation for bdrv_drained_begin_timeout(), note that bdrv_drained_end() > must be called when -ETIMEDOUT is returned. > 5. Add a timeout parameter to the qmp_block_set_io_throttle() instead of hardcoding > the timeout, and the default value is 0, mean an infinite timeout. > > v1 patch link: > https://lore.kernel.org/qemu-devel/20250308101618.721954-1-zoudongjie@huawei.com/ > > Zhu Yangyang (2): > io/block: Refactoring the bdrv_drained_begin() function and implement > a timeout mechanism. > qapi/throttle: add timeout parameter for qmp_block_set_io_throttle() > > block/block-backend.c | 14 ++++- > block/io.c | 58 +++++++++++++++++---- > block/qapi-system.c | 10 +++- > include/block/aio-wait.h | 47 ++++++++++++----- > include/block/block-io.h | 22 +++++++- > include/system/block-backend-global-state.h | 1 + > qapi/block-core.json | 5 +- > util/aio-wait.c | 5 ++ > 8 files changed, 135 insertions(+), 27 deletions(-) > > -- > 2.33.0 > Aside from Markus' comments: Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 488 bytes --] ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 0/2] qapi/throttle: Fix qmp_block_set_io_throttle blocked for too long 2025-03-26 9:26 [PATCH v3 0/2] qapi/throttle: Fix qmp_block_set_io_throttle blocked for too long zoudongjie via ` (2 preceding siblings ...) 2025-03-26 15:06 ` [PATCH v3 0/2] qapi/throttle: Fix qmp_block_set_io_throttle blocked for too long Stefan Hajnoczi @ 2025-05-12 9:40 ` Michael Tokarev 2025-05-12 10:31 ` Markus Armbruster 3 siblings, 1 reply; 13+ messages in thread From: Michael Tokarev @ 2025-05-12 9:40 UTC (permalink / raw) To: zoudongjie, qemu-devel Cc: stefanha, kwolf, fam, hreitz, alex.chen, chenjianfei3, eric.fangyi, luolongmin, mujinsheng, qemu-block, qemu-stable, renxuming, suxiaodong1, wangjian161, wangyan122, yebiaoxiang, zhuyangyang14 On 26.03.2025 12:26, zoudongjie via wrote: > From: Zhu Yangyang <zhuyangyang14@huawei.com> > > Calling qmp_block_set_io_throttle() will be blocked for a long time > when a network disk is configured and the network failure is just about > to occur. > > This series add a timeout parameter for qmp_block_set_io_throttle to control > its execution duration. > > Changelog > v3 --- > Unify AIO_WAIT_WHILE_{TIMEOUT/INTERNAL} by replacing AIO_WAIT_WHILE_INTERNAL() with > AIO_WAIT_WHILE_TIMEOUT(..., 0). > > v2 ---- > 1. Support 0 in BDRV_POLL_WHILE_TIMEOUT(), 0 means infinite. > 2. Use uint64_t timeout_ns instead of int64 timeout to name variables. > 3. Use timer_pending() to check for expiry instead of explicitly checking > against the deadline for BDRV_POLL_WHILE_TIMEOUT(). > 4. Add documentation for bdrv_drained_begin_timeout(), note that bdrv_drained_end() > must be called when -ETIMEDOUT is returned. > 5. Add a timeout parameter to the qmp_block_set_io_throttle() instead of hardcoding > the timeout, and the default value is 0, mean an infinite timeout. > > v1 patch link: > https://lore.kernel.org/qemu-devel/20250308101618.721954-1-zoudongjie@huawei.com/ > > Zhu Yangyang (2): > io/block: Refactoring the bdrv_drained_begin() function and implement > a timeout mechanism. > qapi/throttle: add timeout parameter for qmp_block_set_io_throttle() Hi! Is this series still relevant? It's Cc'ed qemu-stable@, but not yet applied to master branch.. Thanks, /mjt ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 0/2] qapi/throttle: Fix qmp_block_set_io_throttle blocked for too long 2025-05-12 9:40 ` Michael Tokarev @ 2025-05-12 10:31 ` Markus Armbruster 0 siblings, 0 replies; 13+ messages in thread From: Markus Armbruster @ 2025-05-12 10:31 UTC (permalink / raw) To: Michael Tokarev Cc: zoudongjie, qemu-devel, stefanha, kwolf, fam, hreitz, alex.chen, chenjianfei3, eric.fangyi, luolongmin, mujinsheng, qemu-block, qemu-stable, renxuming, suxiaodong1, wangjian161, wangyan122, yebiaoxiang, zhuyangyang14 Michael Tokarev <mjt@tls.msk.ru> writes: > On 26.03.2025 12:26, zoudongjie via wrote: >> From: Zhu Yangyang <zhuyangyang14@huawei.com> >> Calling qmp_block_set_io_throttle() will be blocked for a long time >> when a network disk is configured and the network failure is just about >> to occur. >> This series add a timeout parameter for qmp_block_set_io_throttle to control >> its execution duration. >> Changelog >> v3 --- >> Unify AIO_WAIT_WHILE_{TIMEOUT/INTERNAL} by replacing AIO_WAIT_WHILE_INTERNAL() with >> AIO_WAIT_WHILE_TIMEOUT(..., 0). >> v2 ---- >> 1. Support 0 in BDRV_POLL_WHILE_TIMEOUT(), 0 means infinite. >> 2. Use uint64_t timeout_ns instead of int64 timeout to name variables. >> 3. Use timer_pending() to check for expiry instead of explicitly checking >> against the deadline for BDRV_POLL_WHILE_TIMEOUT(). >> 4. Add documentation for bdrv_drained_begin_timeout(), note that bdrv_drained_end() >> must be called when -ETIMEDOUT is returned. >> 5. Add a timeout parameter to the qmp_block_set_io_throttle() instead of hardcoding >> the timeout, and the default value is 0, mean an infinite timeout. >> v1 patch link: >> https://lore.kernel.org/qemu-devel/20250308101618.721954-1-zoudongjie@huawei.com/ >> Zhu Yangyang (2): >> io/block: Refactoring the bdrv_drained_begin() function and implement >> a timeout mechanism. >> qapi/throttle: add timeout parameter for qmp_block_set_io_throttle() > > Hi! > > Is this series still relevant? It's Cc'ed qemu-stable@, but not yet > applied to master branch.. I understand Zoudongjie intends to respin. Issues I pointed out: * Incorrect Since: tag * Confusing error message * What other commands could similarly block? The last one should be investigated, but that need not block the patch. A partial fix can be better than no fix. ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2025-05-12 10:32 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-03-26 9:26 [PATCH v3 0/2] qapi/throttle: Fix qmp_block_set_io_throttle blocked for too long zoudongjie via 2025-03-26 9:26 ` [PATCH v3 1/2] io/block: Refactoring the bdrv_drained_begin() function and implement a timeout mechanism zoudongjie via 2025-03-26 9:26 ` [PATCH v3 2/2] qapi/throttle: add timeout parameter for qmp_block_set_io_throttle() zoudongjie via 2025-03-26 9:53 ` Markus Armbruster 2025-03-27 7:56 ` zoudongjie via 2025-03-27 8:04 ` Markus Armbruster 2025-03-27 12:34 ` zoudongjie via 2025-03-27 13:43 ` Markus Armbruster 2025-04-01 8:15 ` zoudongjie via 2025-04-01 7:21 ` zoudongjie via 2025-03-26 15:06 ` [PATCH v3 0/2] qapi/throttle: Fix qmp_block_set_io_throttle blocked for too long Stefan Hajnoczi 2025-05-12 9:40 ` Michael Tokarev 2025-05-12 10:31 ` Markus Armbruster
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.