From patchwork Sat Feb 9 16:44:58 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [for-1.4,stable] block: handle spurious coroutine entries Date: Sat, 09 Feb 2013 06:44:58 -0000 From: Stefan Hajnoczi X-Patchwork-Id: 219414 Message-Id: <1360428298-15829-1-git-send-email-stefanha@redhat.com> To: Cc: Kevin Wolf , Paolo Bonzini , Anthony Liguori , Stefan Hajnoczi , Juan Quintela bdrv_co_io_em(), bdrv_co_flush(), and bdrv_co_discard() yield the coroutine when waiting for aio to complete. They do not check that the request has actually finished. In simple cases this works, but it returns early when we get spurious wake-ups due to qemu_coroutine_enter() being called from other sources. One such example is block-migration.c:process_incoming_migration(). This patch fixes a segfault on incoming block migration. Reported-by: David Pravec Signed-off-by: Stefan Hajnoczi Reviewed-by: Paolo Bonzini --- This patch is partially fixes block migration. There is another issue that causes block migration to fail with "Unknown flags" at 99%. block.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/block.c b/block.c index 50dab8e..f2f3b80 100644 --- a/block.c +++ b/block.c @@ -3961,6 +3961,7 @@ void qemu_aio_release(void *p) typedef struct CoroutineIOCompletion { Coroutine *coroutine; int ret; + bool done; } CoroutineIOCompletion; static void bdrv_co_io_em_complete(void *opaque, int ret) @@ -3968,6 +3969,7 @@ static void bdrv_co_io_em_complete(void *opaque, int ret) CoroutineIOCompletion *co = opaque; co->ret = ret; + co->done = true; qemu_coroutine_enter(co->coroutine, NULL); } @@ -3992,7 +3994,9 @@ static int coroutine_fn bdrv_co_io_em(BlockDriverState *bs, int64_t sector_num, if (!acb) { return -EIO; } - qemu_coroutine_yield(); + while (!co.done) { + qemu_coroutine_yield(); + } return co.ret; } @@ -4051,7 +4055,9 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs) if (acb == NULL) { ret = -EIO; } else { - qemu_coroutine_yield(); + while (!co.done) { + qemu_coroutine_yield(); + } ret = co.ret; } } else { @@ -4161,7 +4167,9 @@ int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num, if (acb == NULL) { return -EIO; } else { - qemu_coroutine_yield(); + while (!co.done) { + qemu_coroutine_yield(); + } return co.ret; } } else {