diff --git a/block.c b/block.c index 6521eaa546..b1a462956f 100644 --- a/block.c +++ b/block.c @@ -2789,11 +2789,22 @@ static void coroutine_fn bdrv_flush_co_entry(void *opaque) int coroutine_fn bdrv_co_flush(BlockDriverState *bs) { + int ret; + if (bs->open_flags & BDRV_O_NO_FLUSH) { return 0; } else if (!bs->drv) { return 0; - } else if (bs->drv->bdrv_co_flush_to_disk) { + } + + if (bs->drv->bdrv_co_flush_to_os) { + ret = bs->drv->bdrv_co_flush_to_os(bs); + if (ret < 0) { + return ret; + } + } + + if (bs->drv->bdrv_co_flush_to_disk) { return bs->drv->bdrv_co_flush_to_disk(bs); } else if (bs->drv->bdrv_aio_flush) { BlockDriverAIOCB *acb; diff --git a/block/qcow2.c b/block/qcow2.c index f7f73fe376..5c784eee51 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1105,7 +1105,7 @@ fail: return ret; } -static int qcow2_co_flush(BlockDriverState *bs) +static int qcow2_co_flush_to_os(BlockDriverState *bs) { BDRVQcowState *s = bs->opaque; int ret; @@ -1124,6 +1124,11 @@ static int qcow2_co_flush(BlockDriverState *bs) } qemu_co_mutex_unlock(&s->lock); + return 0; +} + +static int qcow2_co_flush_to_disk(BlockDriverState *bs) +{ return bdrv_co_flush(bs->file); } @@ -1245,7 +1250,8 @@ static BlockDriver bdrv_qcow2 = { .bdrv_co_readv = qcow2_co_readv, .bdrv_co_writev = qcow2_co_writev, - .bdrv_co_flush_to_disk = qcow2_co_flush, + .bdrv_co_flush_to_os = qcow2_co_flush_to_os, + .bdrv_co_flush_to_disk = qcow2_co_flush_to_disk, .bdrv_co_discard = qcow2_co_discard, .bdrv_truncate = qcow2_truncate, diff --git a/block_int.h b/block_int.h index 5aadc1fcee..1ec4921cc6 100644 --- a/block_int.h +++ b/block_int.h @@ -93,6 +93,13 @@ struct BlockDriver { */ int coroutine_fn (*bdrv_co_flush_to_disk)(BlockDriverState *bs); + /* + * Flushes all internal caches to the OS. The data may still sit in a + * writeback cache of the host OS, but it will survive a crash of the qemu + * process. + */ + int coroutine_fn (*bdrv_co_flush_to_os)(BlockDriverState *bs); + int (*bdrv_aio_multiwrite)(BlockDriverState *bs, BlockRequest *reqs, int num_reqs); int (*bdrv_merge_requests)(BlockDriverState *bs, BlockRequest* a,