qemu-e2k/block
Kevin Wolf e424aff5f3 mirror: Fix coroutine reentrance
This fixes a regression introduced by commit dcfb3beb ("mirror: Do zero
write on target if sectors not allocated"), which was reported to cause
aborts with the message "Co-routine re-entered recursively".

The cause for this bug is the following code in mirror_iteration_done():

    if (s->common.busy) {
        qemu_coroutine_enter(s->common.co, NULL);
    }

This has always been ugly because - unlike most places that reenter - it
doesn't have a specific yield that it pairs with, but is more
uncontrolled.  What we really mean here is "reenter the coroutine if
it's in one of the four explicit yields in mirror.c".

This used to be equivalent with s->common.busy because neither
mirror_run() nor mirror_iteration() call any function that could yield.
However since commit dcfb3beb this doesn't hold true any more:
bdrv_get_block_status_above() can yield.

So what happens is that bdrv_get_block_status_above() wants to take a
lock that is already held, so it adds itself to the queue of waiting
coroutines and yields. Instead of being woken up by the unlock function,
however, it gets woken up by mirror_iteration_done(), which is obviously
wrong.

In most cases the code actually happens to cope fairly well with such
cases, but in this specific case, the unlock must already have scheduled
the coroutine for wakeup when mirror_iteration_done() reentered it. And
then the coroutine happened to process the scheduled restarts and tried
to reenter itself recursively.

This patch fixes the problem by pairing the reenter in
mirror_iteration_done() with specific yields instead of abusing
s->common.busy.

Cc: qemu-stable@nongnu.org
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
Message-id: 1439455310-11263-1-git-send-email-kwolf@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
2015-08-14 09:51:31 -04:00
..
accounting.c
archipelago.c block: remove superfluous '\n' around error_report/error_setg 2015-03-10 08:15:33 +03:00
backup.c block: keep bitmap if incremental backup job is cancelled 2015-07-14 21:50:13 -04:00
blkdebug.c block: Move flag inheritance to bdrv_open_inherit() 2015-06-12 17:04:59 +02:00
blkverify.c block: Move flag inheritance to bdrv_open_inherit() 2015-06-12 17:04:59 +02:00
block-backend.c block-backend: Introduce blk_drain() 2015-06-23 15:06:16 +01:00
bochs.c
cloop.c
commit.c Include qapi/qmp/qerror.h exactly where needed 2015-06-22 18:20:41 +02:00
curl.c block/curl: Don't lose original error when a connection fails. 2015-07-14 21:50:13 -04:00
dmg.c qerror: Move #include out of qerror.h 2015-06-22 18:20:40 +02:00
gluster.c
io.c block: update bdrv_drain_all()/bdrv_drain() comments 2015-07-07 10:31:08 +01:00
iscsi.c block/iscsi: restore compatiblity with libiscsi 1.9.0 2015-07-02 10:06:23 +01:00
linux-aio.c
Makefile.objs block: convert quorum blockdrv to use crypto APIs 2015-07-08 13:11:01 +02:00
mirror.c mirror: Fix coroutine reentrance 2015-08-14 09:51:31 -04:00
nbd-client.c nbd: Set block size to BDRV_SECTOR_SIZE 2015-03-18 12:07:01 +01:00
nbd-client.h nbd: Set block size to BDRV_SECTOR_SIZE 2015-03-18 12:07:01 +01:00
nbd.c nbd: Fix nbd_establish_connection()'s return value 2015-03-18 12:05:38 +01:00
nfs.c block/nfs: limit maximum readahead size to 1MB 2015-07-02 10:06:23 +01:00
null.c block/null: Support reopen 2015-04-28 15:36:09 +02:00
parallels.c block/parallels: improve image writing performance further 2015-05-22 09:37:32 +01:00
qapi.c qerror: Finally unused, clean up 2015-06-22 18:20:40 +02:00
qcow2-cache.c qcow2: remove unnecessary check 2015-07-07 10:31:04 +01:00
qcow2-cluster.c block: convert qcow/qcow2 to use generic cipher API 2015-07-08 13:11:01 +02:00
qcow2-refcount.c qcow2: Handle EAGAIN returned from update_refcount 2015-07-02 09:20:18 +01:00
qcow2-snapshot.c qerror: Move #include out of qerror.h 2015-06-22 18:20:40 +02:00
qcow2.c block: convert qcow/qcow2 to use generic cipher API 2015-07-08 13:11:01 +02:00
qcow2.h block: convert qcow/qcow2 to use generic cipher API 2015-07-08 13:11:01 +02:00
qcow.c block: convert qcow/qcow2 to use generic cipher API 2015-07-08 13:11:01 +02:00
qed-check.c
qed-cluster.c
qed-gencb.c
qed-l2-cache.c
qed-table.c
qed.c qerror: Clean up QERR_ macros to expand into a single string 2015-06-22 18:20:40 +02:00
qed.h
quorum.c block: don't register quorum driver if SHA256 support is unavailable 2015-08-05 15:19:32 +01:00
raw_bsd.c block: Add driver methods to probe blocksizes and geometry 2015-03-10 14:02:22 +01:00
raw-aio.h
raw-posix.c block/raw-posix: Don't think /dev/fd/<NN> is a floppy drive. 2015-07-07 14:27:14 +01:00
raw-win32.c qerror: Move #include out of qerror.h 2015-06-22 18:20:40 +02:00
rbd.c rbd: fix ceph settings precedence 2015-07-14 17:15:23 +02:00
sheepdog.c sheepdog: serialize requests to overwrapping area 2015-07-28 00:16:57 -04:00
snapshot.c block: Use bdrv_drain to replace uncessary bdrv_drain_all 2015-07-07 14:27:14 +01:00
ssh.c block/ssh: Avoid segfault if inet_connect doesn't set errno. 2015-07-28 00:19:05 -04:00
stream.c Include qapi/qmp/qerror.h exactly where needed 2015-06-22 18:20:41 +02:00
throttle-groups.c throttle: Check current timers before updating any_timer_armed[] 2015-06-23 15:06:16 +01:00
vdi.c block: use bdrv_get_device_or_node_name() in error messages 2015-04-28 15:36:09 +02:00
vhdx-endian.c
vhdx-log.c qerror: Move #include out of qerror.h 2015-06-22 18:20:40 +02:00
vhdx.c block: use bdrv_get_device_or_node_name() in error messages 2015-04-28 15:36:09 +02:00
vhdx.h
vmdk.c Include qapi/qmp/qerror.h exactly where needed 2015-06-22 18:20:41 +02:00
vpc.c block: vpc - prevent overflow if max_table_entries >= 0x40000000 2015-07-27 17:19:06 +02:00
vvfat.c vvfat: add a label option 2015-06-23 15:06:17 +01:00
win32-aio.c
write-threshold.c block: Fix block-set-write-threshold not to use funky error class 2015-03-16 17:07:25 +01:00