There are times when the QEMU main loop wishes to drain I/O requests. Up until now bdrv_drain_all() meant that no new guest I/O will be processed until the next event loop iteration.
This is no longer true with dataplane since it runs outside the QEMU global mutex. The BlockDevOps->drain_threads_cb() interface allows the device model to drain and stop threads. Once draining completes, the QEMU main loop can be sure that no further I/O will take place until next main loop iteration. Signed-off-by: Stefan Hajnoczi <stefa...@redhat.com> --- block.c | 6 ++++++ include/block/block.h | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/block.c b/block.c index 1c9df27..a3323b2 100644 --- a/block.c +++ b/block.c @@ -1430,6 +1430,12 @@ void bdrv_drain_all(void) BlockDriverState *bs; bool busy; + QTAILQ_FOREACH(bs, &bdrv_states, list) { + if (bs->dev_ops && bs->dev_ops->drain_threads_cb) { + bs->dev_ops->drain_threads_cb(bs->dev_opaque); + } + } + do { busy = qemu_aio_wait(); diff --git a/include/block/block.h b/include/block/block.h index 2307f67..85147bb 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -60,6 +60,15 @@ typedef struct BlockDevOps { * Runs when the size changed (e.g. monitor command block_resize) */ void (*resize_cb)(void *opaque); + /* + * Notifies the device model to drain any emulation threads + * + * Upon return, there must be no new or pending requests outside the QEMU + * main loop. The device model may restart emulation threads after this + * main loop iteration, for example in a hardware register handler + * function. + */ + void (*drain_threads_cb)(void *opaque); } BlockDevOps; #define BDRV_O_RDWR 0x0002 -- 1.8.1.4