qemu/include
Max Reitz 804db8ea00 block: Introduce BdrvChild.parent_quiesce_counter
Commit 5cb2737e92 laid out why
bdrv_do_drained_end() must decrement the quiesce_counter after
bdrv_drain_invoke().  It did not give a very good reason why it has to
happen after bdrv_parent_drained_end(), instead only claiming symmetry
to bdrv_do_drained_begin().

It turns out that delaying it for so long is wrong.

Situation: We have an active commit job (i.e. a mirror job) from top to
base for the following graph:

                  filter
                    |
                  [file]
                    |
                    v
top --[backing]--> base

Now the VM is closed, which results in the job being cancelled and a
bdrv_drain_all() happening pretty much simultaneously.

Beginning the drain means the job is paused once whenever one of its
nodes is quiesced.  This is reversed when the drain ends.

With how the code currently is, after base's drain ends (which means
that it will have unpaused the job once), its quiesce_counter remains at
1 while it goes to undrain its parents (bdrv_parent_drained_end()).  For
some reason or another, undraining filter causes the job to be kicked
and enter mirror_exit_common(), where it proceeds to invoke
block_job_remove_all_bdrv().

Now base will be detached from the job.  Because its quiesce_counter is
still 1, it will unpause the job once more.  So in total, undraining
base will unpause the job twice.  Eventually, this will lead to the
job's pause_count going negative -- well, it would, were there not an
assertion against this, which crashes qemu.

The general problem is that if in bdrv_parent_drained_end() we undrain
parent A, and then undrain parent B, which then leads to A detaching the
child, bdrv_replace_child_noperm() will undrain A as if we had not done
so yet; that is, one time too many.

It follows that we cannot decrement the quiesce_counter after invoking
bdrv_parent_drained_end().

Unfortunately, decrementing it before bdrv_parent_drained_end() would be
wrong, too.  Imagine the above situation in reverse: Undraining A leads
to B detaching the child.  If we had already decremented the
quiesce_counter by that point, bdrv_replace_child_noperm() would undrain
B one time too little; because it expects bdrv_parent_drained_end() to
issue this undrain.  But bdrv_parent_drained_end() won't do that,
because B is no longer a parent.

Therefore, we have to do something else.  This patch opts for
introducing a second quiesce_counter that counts how many times a
child's parent has been quiesced (though c->role->drained_*).  With
that, bdrv_replace_child_noperm() just has to undrain the parent exactly
that many times when removing a child, and it will always be right.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2019-07-19 13:19:16 +02:00
..
authz Include qemu-common.h exactly where needed 2019-06-12 13:20:20 +02:00
block block: Introduce BdrvChild.parent_quiesce_counter 2019-07-19 13:19:16 +02:00
chardev Include qemu-common.h exactly where needed 2019-06-12 13:20:20 +02:00
crypto Include qemu-common.h exactly where needed 2019-06-12 13:20:20 +02:00
disas Clean up a few header guard symbols 2019-06-12 13:20:20 +02:00
exec linux-user: check valid address in access_ok() 2019-07-18 13:57:28 +02:00
fpu Supply missing header guards 2019-06-12 13:20:21 +02:00
hw pl031: Correctly migrate state when using -rtc clock=host 2019-07-15 14:17:04 +01:00
io Include qemu-common.h exactly where needed 2019-06-12 13:20:20 +02:00
libdecnumber Clean up ill-advised or unusual header guards 2016-07-12 16:20:46 +02:00
migration vmstate: Add support for kernel integer types 2019-06-21 13:23:47 +02:00
monitor hw/core: Collect HMP command handlers in hw/core/ 2019-07-02 13:37:00 +02:00
net net/announce: Add optional ID 2019-07-02 10:21:06 +08:00
qapi qapi: remove qmp_unregister_command() 2019-02-18 14:44:05 +01:00
qemu bitmap: Add bitmap_copy_with_{src|dst}_offset() 2019-07-15 15:39:02 +02:00
qom Include qemu/module.h where needed, drop it from qemu-common.h 2019-06-12 13:18:33 +02:00
scsi scsi: explicitly list guest-recoverable sense codes 2019-07-15 11:20:42 +02:00
standard-headers virtio-pmem: sync linux headers 2019-07-04 17:00:32 -04:00
sysemu kvm: Introduce slots lock for memory listener 2019-07-15 15:39:03 +02:00
ui Supply missing header guards 2019-06-12 13:20:21 +02:00
elf.h linux-user: elf: ELF_HWCAP for s390x 2019-06-07 14:53:26 +02:00
glib-compat.h slirp: Move g_spawn_async_with_fds_qemu compatibility to slirp/ 2019-02-07 15:49:08 +02:00
qemu-common.h Include qemu-common.h exactly where needed 2019-06-12 13:20:20 +02:00
qemu-io.h Include qemu-common.h exactly where needed 2019-06-12 13:20:20 +02:00
trace-tcg.h trace: get rid of generated-events.h/generated-events.c 2016-10-12 09:54:52 +02:00