aboutsummaryrefslogtreecommitdiff
path: root/block/block-backend.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/block-backend.c')
-rw-r--r--block/block-backend.c31
1 files changed, 22 insertions, 9 deletions
diff --git a/block/block-backend.c b/block/block-backend.c
index 14a1b7ac6a..7b1ec5071b 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -88,7 +88,6 @@ struct BlockBackend {
* Accessed with atomic ops.
*/
unsigned int in_flight;
- AioWait wait;
};
typedef struct BlockBackendAIOCB {
@@ -121,6 +120,7 @@ static void blk_root_inherit_options(int *child_flags, QDict *child_options,
abort();
}
static void blk_root_drained_begin(BdrvChild *child);
+static bool blk_root_drained_poll(BdrvChild *child);
static void blk_root_drained_end(BdrvChild *child);
static void blk_root_change_media(BdrvChild *child, bool load);
@@ -294,6 +294,7 @@ static const BdrvChildRole child_root = {
.get_parent_desc = blk_root_get_parent_desc,
.drained_begin = blk_root_drained_begin,
+ .drained_poll = blk_root_drained_poll,
.drained_end = blk_root_drained_end,
.activate = blk_root_activate,
@@ -433,6 +434,7 @@ int blk_get_refcnt(BlockBackend *blk)
*/
void blk_ref(BlockBackend *blk)
{
+ assert(blk->refcnt > 0);
blk->refcnt++;
}
@@ -445,7 +447,13 @@ void blk_unref(BlockBackend *blk)
{
if (blk) {
assert(blk->refcnt > 0);
- if (!--blk->refcnt) {
+ if (blk->refcnt > 1) {
+ blk->refcnt--;
+ } else {
+ blk_drain(blk);
+ /* blk_drain() cannot resurrect blk, nobody held a reference */
+ assert(blk->refcnt == 1);
+ blk->refcnt = 0;
blk_delete(blk);
}
}
@@ -1289,7 +1297,7 @@ static void blk_inc_in_flight(BlockBackend *blk)
static void blk_dec_in_flight(BlockBackend *blk)
{
atomic_dec(&blk->in_flight);
- aio_wait_kick(&blk->wait);
+ aio_wait_kick();
}
static void error_callback_bh(void *opaque)
@@ -1330,8 +1338,8 @@ static const AIOCBInfo blk_aio_em_aiocb_info = {
static void blk_aio_complete(BlkAioEmAIOCB *acb)
{
if (acb->has_returned) {
- blk_dec_in_flight(acb->rwco.blk);
acb->common.cb(acb->common.opaque, acb->rwco.ret);
+ blk_dec_in_flight(acb->rwco.blk);
qemu_aio_unref(acb);
}
}
@@ -1590,9 +1598,8 @@ void blk_drain(BlockBackend *blk)
}
/* We may have -ENOMEDIUM completions in flight */
- AIO_WAIT_WHILE(&blk->wait,
- blk_get_aio_context(blk),
- atomic_mb_read(&blk->in_flight) > 0);
+ AIO_WAIT_WHILE(blk_get_aio_context(blk),
+ atomic_mb_read(&blk->in_flight) > 0);
if (bs) {
bdrv_drained_end(bs);
@@ -1611,8 +1618,7 @@ void blk_drain_all(void)
aio_context_acquire(ctx);
/* We may have -ENOMEDIUM completions in flight */
- AIO_WAIT_WHILE(&blk->wait, ctx,
- atomic_mb_read(&blk->in_flight) > 0);
+ AIO_WAIT_WHILE(ctx, atomic_mb_read(&blk->in_flight) > 0);
aio_context_release(ctx);
}
@@ -2189,6 +2195,13 @@ static void blk_root_drained_begin(BdrvChild *child)
}
}
+static bool blk_root_drained_poll(BdrvChild *child)
+{
+ BlockBackend *blk = child->opaque;
+ assert(blk->quiesce_counter);
+ return !!blk->in_flight;
+}
+
static void blk_root_drained_end(BdrvChild *child)
{
BlockBackend *blk = child->opaque;