aboutsummaryrefslogtreecommitdiff
path: root/block
diff options
context:
space:
mode:
authorKevin Wolf <kwolf@redhat.com>2017-12-13 18:14:18 +0100
committerKevin Wolf <kwolf@redhat.com>2017-12-22 15:05:32 +0100
commit0f115168943e5bf2219497abfbf5f7a9c271b9b0 (patch)
tree4e732225a93d7e87b6f7c6e8b1669d70d6c1da16 /block
parent8119334918e86f45877cfc139192d54f2449a239 (diff)
block: Nested drain_end must still call callbacks
bdrv_do_drained_begin() restricts the call of parent callbacks and aio_disable_external() to the outermost drain section, but the block driver callbacks are always called. bdrv_do_drained_end() must match this behaviour, otherwise nodes stay drained even if begin/end calls were balanced. Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'block')
-rw-r--r--block/io.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/block/io.c b/block/io.c
index 74d2e5278e..6038a16c58 100644
--- a/block/io.c
+++ b/block/io.c
@@ -273,19 +273,21 @@ void bdrv_drained_begin(BlockDriverState *bs)
void bdrv_drained_end(BlockDriverState *bs)
{
+ int old_quiesce_counter;
+
if (qemu_in_coroutine()) {
bdrv_co_yield_to_drain(bs, false);
return;
}
assert(bs->quiesce_counter > 0);
- if (atomic_fetch_dec(&bs->quiesce_counter) > 1) {
- return;
- }
+ old_quiesce_counter = atomic_fetch_dec(&bs->quiesce_counter);
/* Re-enable things in child-to-parent order */
bdrv_drain_invoke(bs, false, false);
- bdrv_parent_drained_end(bs);
- aio_enable_external(bdrv_get_aio_context(bs));
+ if (old_quiesce_counter == 1) {
+ bdrv_parent_drained_end(bs);
+ aio_enable_external(bdrv_get_aio_context(bs));
+ }
}
/*