From nobody Sun Nov 16 04:12:33 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1743512819; cv=none; d=zohomail.com; s=zohoarc; b=nHV2/88bRPPnAz2BefIF288rp0XLbE/eCzcV9Z357YC1q2aubJx93dji+rXTqgelO+jrDJ6lB0TkfibjHTH5nGtyGvCXJkcLZw5gggVfPOeBFgv9n6mI0jwntVV4l6Z5MZ4ySloVbw9STlc4/WfNY34G/CG/ycDbpMEDHiYING0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1743512819; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Sender:Subject:Subject:To:To:Message-Id; bh=GSuWQ5xsQ7qQXmK3cRDVJmDRLlC+ZAaqhVdCxNrLegc=; b=dIJ1iUEnWn4+OxF/xJAA9l0X5nAjmXTviMQtyoEO4ImEcIB9Mw50wXirM9mvkeIML6xa1R+78bBIYsImb9qPNqZewY5eEkGPcDLduOYFsVhqM+rmYlcF7aDoSF0NNOV4YSU/TvMeHghgsAKL+c8W8etuqAokcrSW6Vx4HdK/z5w= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1743512819765294.2399155215809; Tue, 1 Apr 2025 06:06:59 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tzbJP-0006Cc-VE; Tue, 01 Apr 2025 09:05:52 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tzbIf-0005YZ-0f; Tue, 01 Apr 2025 09:05:05 -0400 Received: from szxga07-in.huawei.com ([45.249.212.35]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tzbIU-0008Bk-2o; Tue, 01 Apr 2025 09:05:02 -0400 Received: from mail.maildlp.com (unknown [172.19.163.44]) by szxga07-in.huawei.com (SkyGuard) with ESMTP id 4ZRp4V1mdPz1f1dW; Tue, 1 Apr 2025 20:59:54 +0800 (CST) Received: from kwepemk500007.china.huawei.com (unknown [7.202.194.92]) by mail.maildlp.com (Postfix) with ESMTPS id 07A021400E8; Tue, 1 Apr 2025 21:04:42 +0800 (CST) Received: from huawei.com (10.246.99.19) by kwepemk500007.china.huawei.com (7.202.194.92) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Tue, 1 Apr 2025 21:04:40 +0800 To: CC: , , , , , , , , , , , , , , , , , , Subject: [PATCH v4 1/3] io/block: Refactoring the bdrv_drained_begin() function and implement a timeout mechanism. Date: Tue, 1 Apr 2025 21:02:58 +0800 Message-ID: <20250401130300.1457584-2-zoudongjie@huawei.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20250401130300.1457584-1-zoudongjie@huawei.com> References: <20250401130300.1457584-1-zoudongjie@huawei.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.246.99.19] X-ClientProxiedBy: dggems704-chm.china.huawei.com (10.3.19.181) To kwepemk500007.china.huawei.com (7.202.194.92) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=45.249.212.35; envelope-from=zoudongjie@huawei.com; helo=szxga07-in.huawei.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: zoudongjie From: zoudongjie via Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1743512822951019100 Content-Type: text/plain; charset="utf-8" From: Zhu Yangyang The bdrv_drained_begin() function is a blocking function. In scenarios wher= e 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 --- 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; =20 /* 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); } =20 +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 =3D 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); } =20 -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 *b= s, + bool begin, + BdrvChild *parent, + bool poll, + uint64_t timeout_ns) { BdrvCoDrainData data; Coroutine *self =3D qemu_coroutine_self(); @@ -329,6 +338,8 @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDr= iverState *bs, .begin =3D begin, .parent =3D parent, .poll =3D poll, + .timeout_ns =3D timeout_ns, + .ret =3D 0 }; =20 if (bs) { @@ -342,16 +353,27 @@ static void coroutine_fn bdrv_co_yield_to_drain(Block= DriverState *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; } =20 -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(); =20 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); } =20 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, paren= t), + 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); } =20 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); } =20 +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; =20 /** - * 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 conditio= n. * @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 deadl= ock, * go via the main loop instead. + * + * Returns: 0 if succeeded; -ETIMEDOUT when a timeout occurs. */ -#define AIO_WAIT_WHILE_INTERNAL(ctx, cond) ({ \ - bool waited_ =3D false; \ +#define AIO_WAIT_WHILE_TIMEOUT(ctx, cond, timeout_ns) ({ \ + int ret_ =3D 0; \ + uint64_t timeout_ =3D (timeout_ns); \ AioWait *wait_ =3D &global_aio_wait; \ AioContext *ctx_ =3D (ctx); \ + AioContext *current_ctx_ =3D 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_ =3D true; \ - } \ + current_ctx_ =3D ctx_; \ } else { \ assert(qemu_get_current_aio_context() =3D=3D \ qemu_get_aio_context()); \ - while ((cond)) { \ - aio_poll(qemu_get_aio_context(), true); \ - waited_ =3D true; \ + current_ctx_ =3D 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_ =3D -ETIMEDOUT; \ + break; \ } \ } \ + if (timeout_ > 0) { \ + timer_del(&timer_); \ + } \ qatomic_dec(&wait_->num_waiters); \ - waited_; }) + ret_; }) =20 #define AIO_WAIT_WHILE(ctx, cond) \ - AIO_WAIT_WHILE_INTERNAL(ctx, cond) + AIO_WAIT_WHILE_TIMEOUT(ctx, cond, 0) =20 /* 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) =20 /** * aio_wait_kick: @@ -149,4 +168,6 @@ static inline bool in_aio_context_home_thread(AioContex= t *ctx) } } =20 +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); }) =20 +#define BDRV_POLL_WHILE_TIMEOUT(bs, cond, timeout_ns) ({ \ + BlockDriverState *bs_ =3D (bs); \ + AIO_WAIT_WHILE_TIMEOUT(bdrv_get_aio_context(bs_), \ + cond, timeout_ns); }) + void bdrv_drain(BlockDriverState *bs); =20 int co_wrapper_mixed_bdrv_rdlock @@ -432,7 +437,22 @@ bdrv_drain_poll(BlockDriverState *bs, BdrvChild *ignor= e_parent, void bdrv_drained_begin(BlockDriverState *bs); =20 /** - * 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 */ +} --=20 2.33.0 From nobody Sun Nov 16 04:12:33 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1743512761; cv=none; d=zohomail.com; s=zohoarc; b=Tm6CNDOqVgM5ADh56KfnC4/7WrB5PyoQuYu3tDIUBbUW8hAqUXDyllvoYscMQqfokze1V448zDsPsuNyxDbv0QH8KJnPXTzfM8WGY/itoFh7tdSGGoz6xoOkfLIhXIqkFlwoQ2CrIeUb0FseRbJv6HEzC71GANqBVJnKlfXlQIE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1743512761; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Sender:Subject:Subject:To:To:Message-Id; bh=OYDzuBR7sOVnflibQd2fdVRsUiCS62JYeu56lFXToco=; b=J/BXMnooHBOJOk/3doV9WWNZi72QFE8zDy/x+3WlKPS2jvyRVdBtaJRGciR318EDOLSkBljHg4qrFmaj3PafQXzjNHdoVhqdgChC/2+j7qNuiOGmdNA4ldoNKKCKkDb4Bb7WHuCrNDXCAyD6UucJVoiGJGLM0+oiy41q+ygakBo= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1743512761525134.5508881448509; Tue, 1 Apr 2025 06:06:01 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tzbJG-00062k-O9; Tue, 01 Apr 2025 09:05:43 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tzbIe-0005YS-1V; Tue, 01 Apr 2025 09:05:05 -0400 Received: from szxga08-in.huawei.com ([45.249.212.255]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tzbIT-0008Bv-HY; Tue, 01 Apr 2025 09:05:03 -0400 Received: from mail.maildlp.com (unknown [172.19.88.194]) by szxga08-in.huawei.com (SkyGuard) with ESMTP id 4ZRp9S5cVqz1d0vp; Tue, 1 Apr 2025 21:04:12 +0800 (CST) Received: from kwepemk500007.china.huawei.com (unknown [7.202.194.92]) by mail.maildlp.com (Postfix) with ESMTPS id 4FBDD14010D; Tue, 1 Apr 2025 21:04:43 +0800 (CST) Received: from huawei.com (10.246.99.19) by kwepemk500007.china.huawei.com (7.202.194.92) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Tue, 1 Apr 2025 21:04:41 +0800 To: CC: , , , , , , , , , , , , , , , , , , Subject: [PATCH v4 2/3] qapi/throttle: add timeout parameter for qmp_block_set_io_throttle() Date: Tue, 1 Apr 2025 21:02:59 +0800 Message-ID: <20250401130300.1457584-3-zoudongjie@huawei.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20250401130300.1457584-1-zoudongjie@huawei.com> References: <20250401130300.1457584-1-zoudongjie@huawei.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.246.99.19] X-ClientProxiedBy: dggems704-chm.china.huawei.com (10.3.19.181) To kwepemk500007.china.huawei.com (7.202.194.92) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=45.249.212.255; envelope-from=zoudongjie@huawei.com; helo=szxga08-in.huawei.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: zoudongjie From: zoudongjie via Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1743512762674019000 Content-Type: text/plain; charset="utf-8" From: Zhu Yangyang 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 cont= rol its execution duration. The default value of timeout is 0, that is infinite wait, consistent with previous behavior. Signed-off-by: Zhu Yangyang --- 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, ThrottleC= onfig *cfg) } =20 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 =3D blk_bs(blk); ThrottleGroupMember *tgm =3D &blk->public.throttle_group_member; + int ret =3D 0; + assert(tgm->throttle_state); GLOBAL_STATE_CODE(); if (bs) { bdrv_ref(bs); - bdrv_drained_begin(bs); + ret =3D 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; } =20 /* 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..195cbc74c3 100644 --- a/block/qapi-system.c +++ b/block/qapi-system.c @@ -423,6 +423,7 @@ void qmp_block_set_io_throttle(BlockIOThrottle *arg, Er= ror **errp) ThrottleConfig cfg; BlockDriverState *bs; BlockBackend *blk; + uint64_t timeout_ns; =20 blk =3D qmp_get_blk(arg->device, arg->id, errp); if (!blk) { @@ -444,6 +445,10 @@ void qmp_block_set_io_throttle(BlockIOThrottle *arg, E= rror **errp) cfg.buckets[THROTTLE_OPS_READ].avg =3D arg->iops_rd; cfg.buckets[THROTTLE_OPS_WRITE].avg =3D arg->iops_wr; =20 + timeout_ns =3D 0; /* 0 means infinite */ + if (arg->has_timeout) { + timeout_ns =3D arg->timeout * NANOSECONDS_PER_SECOND; + } if (arg->has_bps_max) { cfg.buckets[THROTTLE_BPS_TOTAL].max =3D arg->bps_max; } @@ -502,7 +507,10 @@ void qmp_block_set_io_throttle(BlockIOThrottle *arg, E= rror **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, "command timed out"); + return; + } } } =20 diff --git a/include/system/block-backend-global-state.h b/include/system/b= lock-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 *g= eo); =20 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..a75ff1cb0c 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.1) +# # 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'} } =20 ## # @ThrottleLimits: --=20 2.33.0 From nobody Sun Nov 16 04:12:33 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1743512799; cv=none; d=zohomail.com; s=zohoarc; b=HJiRQAq1WbvDVB2fbQJHxXZ5t0q/Bb+ppx0R6o+u0RYMr9yb894Y3bxxTBNzkR/StB9gmw5fdjZnTkHUBrOqQjW7UHlbhHSH2wJrF9DT6lt00EThHRblF5lP1h1WbLLGPdhPcDR7aRusZPq+uZNDjeiuTn635dUwkjhHNSR4ZUc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1743512799; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Sender:Subject:Subject:To:To:Message-Id; bh=95rwKeUXqpoewLrjYYBKpmhXYGsU1L6qkY5mlINxkTw=; b=JAYXarR9n8Xeq4efdUOV//EMXDu7d7geeVPHHwoGsb3Zk8CZKHdS/sVMqSI00sLfj48Whbn6Bqar8fz9+QgwzPlMfr+rDhGMVmiILrkKVTeN/qZhjF3/cvKLTRXMahNOx+ZVpzjDH0uSgFdND5BbvgI0Degrlf/tfpJENA0qRw0= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 17435127991583.5737644347143487; Tue, 1 Apr 2025 06:06:39 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tzbIr-0005ji-H9; Tue, 01 Apr 2025 09:05:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tzbIY-0005Wc-2R; Tue, 01 Apr 2025 09:04:59 -0400 Received: from szxga07-in.huawei.com ([45.249.212.35]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tzbIT-0008CE-3T; Tue, 01 Apr 2025 09:04:56 -0400 Received: from mail.maildlp.com (unknown [172.19.88.234]) by szxga07-in.huawei.com (SkyGuard) with ESMTP id 4ZRp4X68Lrz1f1XG; Tue, 1 Apr 2025 20:59:56 +0800 (CST) Received: from kwepemk500007.china.huawei.com (unknown [7.202.194.92]) by mail.maildlp.com (Postfix) with ESMTPS id 9A19F1402C7; Tue, 1 Apr 2025 21:04:44 +0800 (CST) Received: from huawei.com (10.246.99.19) by kwepemk500007.china.huawei.com (7.202.194.92) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Tue, 1 Apr 2025 21:04:43 +0800 To: CC: , , , , , , , , , , , , , , , , , , Subject: [PATCH v4 3/3] qapi/resize: add timeout parameter for qmp_block_resize() Date: Tue, 1 Apr 2025 21:03:00 +0800 Message-ID: <20250401130300.1457584-4-zoudongjie@huawei.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20250401130300.1457584-1-zoudongjie@huawei.com> References: <20250401130300.1457584-1-zoudongjie@huawei.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.246.99.19] X-ClientProxiedBy: dggems704-chm.china.huawei.com (10.3.19.181) To kwepemk500007.china.huawei.com (7.202.194.92) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=45.249.212.35; envelope-from=zoudongjie@huawei.com; helo=szxga07-in.huawei.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: zoudongjie From: zoudongjie via Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1743512800995019000 Content-Type: text/plain; charset="utf-8" From: Zhu Yangyang 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 --- 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 =3D qdict_get_int(qdict, "size"); Error *err =3D NULL; =20 - qmp_block_resize(device, NULL, size, &err); + qmp_block_resize(device, NULL, size, false, 0, &err); hmp_handle_error(mon, err); } =20 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_bit= map_sha256(const char *node, } =20 void coroutine_fn qmp_block_resize(const char *device, const char *node_na= me, - int64_t size, Error **errp) + int64_t size, + bool has_timeout, uint32_t timeout, + Error **errp) { Error *local_err =3D NULL; BlockBackend *blk; BlockDriverState *bs; AioContext *old_ctx; + uint64_t timeout_ns; =20 bs =3D bdrv_lookup_bs(device, node_name, &local_err); if (local_err) { @@ -2282,12 +2285,21 @@ void coroutine_fn qmp_block_resize(const char *devi= ce, const char *node_name, return; } =20 - bdrv_drained_begin(bs); + /* Default is 0, that means infinite */ + timeout_ns =3D 0; + if (has_timeout) { + timeout_ns =3D timeout * NANOSECONDS_PER_SECOND; + } + if (bdrv_drained_begin_timeout(bs, timeout_ns) < 0) { + error_setg(errp, "command timed out"); + goto out; + } =20 old_ctx =3D bdrv_co_enter(bs); blk_co_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp); bdrv_co_leave(bs, old_ctx); =20 +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 } =20 --=20 2.33.0