[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC PATCH 4/7] block-backend: add I/O hang drain when disbale
From: |
Ying Fang |
Subject: |
[RFC PATCH 4/7] block-backend: add I/O hang drain when disbale |
Date: |
Sun, 27 Sep 2020 21:04:17 +0800 |
To disable I/O hang, all hanging AIOs need to be drained. A rehandle status
field is introduced to notify rehandle mechanism not to rehandle failed AIOs
when I/O hang is disabled.
Signed-off-by: Ying Fang <fangying1@huawei.com>
Signed-off-by: Jiahui Cen <cenjiahui@huawei.com>
---
block/block-backend.c | 85 ++++++++++++++++++++++++++++++++--
include/sysemu/block-backend.h | 3 ++
2 files changed, 84 insertions(+), 4 deletions(-)
diff --git a/block/block-backend.c b/block/block-backend.c
index d0b2b59f55..95b2d6a679 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -37,6 +37,9 @@ static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb);
/* block backend rehandle timer interval 5s */
#define BLOCK_BACKEND_REHANDLE_TIMER_INTERVAL 5000
+#define BLOCK_BACKEND_REHANDLE_NORMAL 1
+#define BLOCK_BACKEND_REHANDLE_DRAIN_REQUESTED 2
+#define BLOCK_BACKEND_REHANDLE_DRAINED 3
enum BlockIOHangStatus {
BLOCK_IO_HANG_STATUS_NORMAL = 0,
@@ -50,6 +53,8 @@ typedef struct BlockBackendRehandleInfo {
unsigned int in_flight;
QTAILQ_HEAD(, BlkAioEmAIOCB) re_aios;
+
+ int status;
} BlockBackendRehandleInfo;
typedef struct BlockBackendAioNotifier {
@@ -471,6 +476,8 @@ static void blk_delete(BlockBackend *blk)
assert(!blk->refcnt);
assert(!blk->name);
assert(!blk->dev);
+ assert(atomic_read(&blk->reinfo.in_flight) == 0);
+ blk_rehandle_disable(blk);
if (blk->public.throttle_group_member.throttle_state) {
blk_io_limits_disable(blk);
}
@@ -2460,6 +2467,37 @@ static void blk_rehandle_remove_aiocb(BlockBackend *blk,
BlkAioEmAIOCB *acb)
atomic_dec(&blk->reinfo.in_flight);
}
+static void blk_rehandle_drain(BlockBackend *blk)
+{
+ if (blk_bs(blk)) {
+ bdrv_drained_begin(blk_bs(blk));
+ BDRV_POLL_WHILE(blk_bs(blk), atomic_read(&blk->reinfo.in_flight) > 0);
+ bdrv_drained_end(blk_bs(blk));
+ }
+}
+
+static bool blk_rehandle_is_paused(BlockBackend *blk)
+{
+ return blk->reinfo.status == BLOCK_BACKEND_REHANDLE_DRAIN_REQUESTED ||
+ blk->reinfo.status == BLOCK_BACKEND_REHANDLE_DRAINED;
+}
+
+static void blk_rehandle_pause(BlockBackend *blk)
+{
+ BlockBackendRehandleInfo *reinfo = &blk->reinfo;
+
+ aio_context_acquire(blk_get_aio_context(blk));
+ if (!reinfo->enable || reinfo->status == BLOCK_BACKEND_REHANDLE_DRAINED) {
+ aio_context_release(blk_get_aio_context(blk));
+ return;
+ }
+
+ reinfo->status = BLOCK_BACKEND_REHANDLE_DRAIN_REQUESTED;
+ blk_rehandle_drain(blk);
+ reinfo->status = BLOCK_BACKEND_REHANDLE_DRAINED;
+ aio_context_release(blk_get_aio_context(blk));
+}
+
static void blk_rehandle_timer_cb(void *opaque)
{
BlockBackend *blk = opaque;
@@ -2559,10 +2597,12 @@ static void blk_rehandle_aio_complete(BlkAioEmAIOCB
*acb)
if (acb->has_returned) {
blk_dec_in_flight(acb->rwco.blk);
- need_rehandle = blk_rehandle_aio(acb, &has_timeout);
- if (need_rehandle) {
- blk_rehandle_insert_aiocb(acb->rwco.blk, acb);
- return;
+ if (!blk_rehandle_is_paused(acb->rwco.blk)) {
+ need_rehandle = blk_rehandle_aio(acb, &has_timeout);
+ if (need_rehandle) {
+ blk_rehandle_insert_aiocb(acb->rwco.blk, acb);
+ return;
+ }
}
acb->common.cb(acb->common.opaque, acb->rwco.ret);
@@ -2576,6 +2616,42 @@ static void blk_rehandle_aio_complete(BlkAioEmAIOCB *acb)
}
}
+void blk_rehandle_enable(BlockBackend *blk)
+{
+ BlockBackendRehandleInfo *reinfo = &blk->reinfo;
+
+ aio_context_acquire(blk_get_aio_context(blk));
+ if (reinfo->enable) {
+ aio_context_release(blk_get_aio_context(blk));
+ return;
+ }
+
+ reinfo->ts = aio_timer_new(blk_get_aio_context(blk), QEMU_CLOCK_REALTIME,
+ SCALE_MS, blk_rehandle_timer_cb, blk);
+ reinfo->timer_interval_ms = BLOCK_BACKEND_REHANDLE_TIMER_INTERVAL;
+ reinfo->status = BLOCK_BACKEND_REHANDLE_NORMAL;
+ reinfo->enable = true;
+ aio_context_release(blk_get_aio_context(blk));
+}
+
+void blk_rehandle_disable(BlockBackend *blk)
+{
+ if (!blk->reinfo.enable) {
+ return;
+ }
+
+ blk_rehandle_pause(blk);
+ timer_del(blk->reinfo.ts);
+ timer_free(blk->reinfo.ts);
+ blk->reinfo.ts = NULL;
+ blk->reinfo.enable = false;
+}
+
+bool blk_iohang_is_enabled(BlockBackend *blk)
+{
+ return blk->iohang_timeout != 0;
+}
+
void blk_iohang_init(BlockBackend *blk, int64_t iohang_timeout)
{
if (!blk) {
@@ -2588,6 +2664,7 @@ void blk_iohang_init(BlockBackend *blk, int64_t
iohang_timeout)
blk->iohang_status = BLOCK_IO_HANG_STATUS_NORMAL;
if (iohang_timeout > 0) {
blk->iohang_timeout = iohang_timeout;
+ blk_rehandle_enable(blk);
}
}
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index bfebe3a960..375ae13b0b 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -268,6 +268,9 @@ const BdrvChild *blk_root(BlockBackend *blk);
int blk_make_empty(BlockBackend *blk, Error **errp);
+void blk_rehandle_enable(BlockBackend *blk);
+void blk_rehandle_disable(BlockBackend *blk);
+bool blk_iohang_is_enabled(BlockBackend *blk);
void blk_iohang_init(BlockBackend *blk, int64_t iohang_timeout);
#endif
--
2.23.0
- [RFC PATCH 0/7] block-backend: Introduce I/O hang, Ying Fang, 2020/09/27
- [RFC PATCH 6/7] qemu-option: add I/O hang timeout option, Ying Fang, 2020/09/27
- [RFC PATCH 7/7] qapi: add I/O hang and I/O hang timeout qapi event, Ying Fang, 2020/09/27
- [RFC PATCH 1/7] block-backend: introduce I/O rehandle info, Ying Fang, 2020/09/27
- [RFC PATCH 4/7] block-backend: add I/O hang drain when disbale,
Ying Fang <=
- [RFC PATCH 2/7] block-backend: rehandle block aios when EIO, Ying Fang, 2020/09/27
- [RFC PATCH 3/7] block-backend: add I/O hang timeout, Ying Fang, 2020/09/27
- [RFC PATCH 5/7] virtio-blk: disable I/O hang when resetting, Ying Fang, 2020/09/27
- Re: [RFC PATCH 0/7] block-backend: Introduce I/O hang, no-reply, 2020/09/27
- Re: [RFC PATCH 0/7] block-backend: Introduce I/O hang, no-reply, 2020/09/27
- Re: [RFC PATCH 0/7] block-backend: Introduce I/O hang, Kevin Wolf, 2020/09/28