mirror of
https://github.com/mii443/qemu.git
synced 2025-12-03 11:08:25 +00:00
block: Don't notify parents in drain call chain
This is in preparation for subtree drains, i.e. drained sections that affect not only a single node, but recursively all child nodes, too. Calling the parent callbacks for drain is pointless when we just came from that parent node recursively and leads to multiple increases of bs->quiesce_counter in a single drain call. Don't do it. In order for this to work correctly, the parent callback must be called for every bdrv_drain_begin/end() call, not only for the outermost one: If we have a node N with two parents A and B, recursive draining of A should cause the quiesce_counter of B to increase because its child N is drained independently of B. If now B is recursively drained, too, A must increase its quiesce_counter because N is drained independently of A only now, even if N is going from quiesce_counter 1 to 2. Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
13
block.c
13
block.c
@@ -1972,13 +1972,16 @@ static void bdrv_replace_child_noperm(BdrvChild *child,
|
||||
BlockDriverState *new_bs)
|
||||
{
|
||||
BlockDriverState *old_bs = child->bs;
|
||||
int i;
|
||||
|
||||
if (old_bs && new_bs) {
|
||||
assert(bdrv_get_aio_context(old_bs) == bdrv_get_aio_context(new_bs));
|
||||
}
|
||||
if (old_bs) {
|
||||
if (old_bs->quiesce_counter && child->role->drained_end) {
|
||||
child->role->drained_end(child);
|
||||
for (i = 0; i < old_bs->quiesce_counter; i++) {
|
||||
child->role->drained_end(child);
|
||||
}
|
||||
}
|
||||
if (child->role->detach) {
|
||||
child->role->detach(child);
|
||||
@@ -1991,7 +1994,9 @@ static void bdrv_replace_child_noperm(BdrvChild *child,
|
||||
if (new_bs) {
|
||||
QLIST_INSERT_HEAD(&new_bs->parents, child, next_parent);
|
||||
if (new_bs->quiesce_counter && child->role->drained_begin) {
|
||||
child->role->drained_begin(child);
|
||||
for (i = 0; i < new_bs->quiesce_counter; i++) {
|
||||
child->role->drained_begin(child);
|
||||
}
|
||||
}
|
||||
|
||||
if (child->role->attach) {
|
||||
@@ -4759,7 +4764,7 @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
|
||||
AioContext *ctx = bdrv_get_aio_context(bs);
|
||||
|
||||
aio_disable_external(ctx);
|
||||
bdrv_parent_drained_begin(bs);
|
||||
bdrv_parent_drained_begin(bs, NULL);
|
||||
bdrv_drain(bs); /* ensure there are no in-flight requests */
|
||||
|
||||
while (aio_poll(ctx, false)) {
|
||||
@@ -4773,7 +4778,7 @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
|
||||
*/
|
||||
aio_context_acquire(new_context);
|
||||
bdrv_attach_aio_context(bs, new_context);
|
||||
bdrv_parent_drained_end(bs);
|
||||
bdrv_parent_drained_end(bs, NULL);
|
||||
aio_enable_external(ctx);
|
||||
aio_context_release(new_context);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user