]> git.ipfire.org Git - thirdparty/qemu.git/commit
block: Don't inactivate children before parents
authorKevin Wolf <kwolf@redhat.com>
Fri, 23 Nov 2018 14:11:14 +0000 (15:11 +0100)
committerKevin Wolf <kwolf@redhat.com>
Tue, 27 Nov 2018 11:59:00 +0000 (12:59 +0100)
commit9e37271f50ec2e95f299dc297ac08f9be0096b48
treef2a42b04288c50f4b77bb7917ab391f73ca2b766
parentd5d31c9a8ab5e87db4230602a6fd5da8eb13135c
block: Don't inactivate children before parents

bdrv_child_cb_inactivate() asserts that parents are already inactive
when children get inactivated. This precondition is necessary because
parents could still issue requests in their inactivation code.

When block nodes are created individually with -blockdev, all of them
are monitor owned and will be returned by bdrv_next() in an undefined
order (in practice, in the order of their creation, which is usually
children before parents), which obviously fails the assertion:

qemu: block.c:899: bdrv_child_cb_inactivate: Assertion `bs->open_flags & BDRV_O_INACTIVE' failed.

This patch fixes the ordering by skipping nodes with still active
parents in bdrv_inactivate_recurse() because we know that they will be
covered by recursion when the last active parent becomes inactive.

With the correct parents-before-children ordering, we also got rid of
the reason why commit aad0b7a0bfb introduced two passes, so we can go
back to a single-pass recursion. This is necessary so we can rely on the
BDRV_O_INACTIVE flag to skip nodes with active parents (the flag used
to be set only in pass 2, so we would always skip non-root nodes in
pass 1 because all parents would still be considered active; setting the
flag in pass 1 would mean, that we never skip anything in pass 2 because
all parents are already considered inactive).

Because of the change to single pass, this patch is best reviewed with
whitespace changes ignored.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
block.c