-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1 iQEcBAABAgAGBQJXDLICAAoJEJykq7OBq3PIw+EH/06hfnEuvpI06IE831MDoBtY PiBg6R8oVQLYjC2LLLRfOUqcr2oqxrRMgN6SIOVrAX3TPFDIVjY2iEEjHcxHbOQw MGAXuXsJCLLkJNDuDlUB44AeiU3V98K0Rh6+hieVZQBuj6yeYA/cuIsz0sWwYUhU 69hFeAgZO9tmSG2zWYqnhMGpbyjD7YYBLmcid+9pxUD1xB2YOuLgOqAGo7RYTEuE 2aaUoaUR4zVWwugLxgBqb6P02apN3afK6mA6QP1eEROMdrXNd/tgCQrWQflxlSP6 Kdnd0RE6iY4Sw8RSX+H3EEehyP+DtpNVgIIRLt1g/GNXJ2ZHfORXv/JSgx43OjU= =+1pC -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging # gpg: Signature made Tue 12 Apr 2016 09:29:54 BST using RSA key ID 81AB73C8 # gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" # gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" * remotes/stefanha/tags/block-pull-request: MAINTAINERS: Add Fam Zheng as a co-maintainer of block I/O path mirror: Replace bdrv_drain(bs) with bdrv_co_drain(bs) block: Fix bdrv_drain in coroutine Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
42bb626f7e
@ -998,6 +998,7 @@ T: git git://repo.or.cz/qemu/kevin.git block
|
||||
|
||||
Block I/O path
|
||||
M: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
M: Fam Zheng <famz@redhat.com>
|
||||
L: qemu-block@nongnu.org
|
||||
S: Supported
|
||||
F: async.c
|
||||
|
45
block/io.c
45
block/io.c
@ -253,6 +253,47 @@ static void bdrv_drain_recurse(BlockDriverState *bs)
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
Coroutine *co;
|
||||
BlockDriverState *bs;
|
||||
QEMUBH *bh;
|
||||
bool done;
|
||||
} BdrvCoDrainData;
|
||||
|
||||
static void bdrv_co_drain_bh_cb(void *opaque)
|
||||
{
|
||||
BdrvCoDrainData *data = opaque;
|
||||
Coroutine *co = data->co;
|
||||
|
||||
qemu_bh_delete(data->bh);
|
||||
bdrv_drain(data->bs);
|
||||
data->done = true;
|
||||
qemu_coroutine_enter(co, NULL);
|
||||
}
|
||||
|
||||
void coroutine_fn bdrv_co_drain(BlockDriverState *bs)
|
||||
{
|
||||
BdrvCoDrainData data;
|
||||
|
||||
/* Calling bdrv_drain() from a BH ensures the current coroutine yields and
|
||||
* other coroutines run if they were queued from
|
||||
* qemu_co_queue_run_restart(). */
|
||||
|
||||
assert(qemu_in_coroutine());
|
||||
data = (BdrvCoDrainData) {
|
||||
.co = qemu_coroutine_self(),
|
||||
.bs = bs,
|
||||
.done = false,
|
||||
.bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_co_drain_bh_cb, &data),
|
||||
};
|
||||
qemu_bh_schedule(data.bh);
|
||||
|
||||
qemu_coroutine_yield();
|
||||
/* If we are resumed from some other event (such as an aio completion or a
|
||||
* timer callback), it is a bug in the caller that should be fixed. */
|
||||
assert(data.done);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for pending requests to complete on a single BlockDriverState subtree,
|
||||
* and suspend block driver's internal I/O until next request arrives.
|
||||
@ -269,6 +310,10 @@ void bdrv_drain(BlockDriverState *bs)
|
||||
bool busy = true;
|
||||
|
||||
bdrv_drain_recurse(bs);
|
||||
if (qemu_in_coroutine()) {
|
||||
bdrv_co_drain(bs);
|
||||
return;
|
||||
}
|
||||
while (busy) {
|
||||
/* Keep iterating */
|
||||
bdrv_flush_io_queue(bs);
|
||||
|
@ -650,7 +650,7 @@ static void coroutine_fn mirror_run(void *opaque)
|
||||
* mirror_populate runs.
|
||||
*/
|
||||
trace_mirror_before_drain(s, cnt);
|
||||
bdrv_drain(bs);
|
||||
bdrv_co_drain(bs);
|
||||
cnt = bdrv_get_dirty_count(s->dirty_bitmap);
|
||||
}
|
||||
|
||||
|
@ -372,6 +372,7 @@ int bdrv_flush(BlockDriverState *bs);
|
||||
int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
|
||||
void bdrv_close_all(void);
|
||||
void bdrv_drain(BlockDriverState *bs);
|
||||
void coroutine_fn bdrv_co_drain(BlockDriverState *bs);
|
||||
void bdrv_drain_all(void);
|
||||
|
||||
int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors);
|
||||
|
Loading…
Reference in New Issue
Block a user