From: Pavel Butsykin <pbutsy...@virtuozzo.com> This patch just adds the interface to the bdrv_co_pwritev_compressed, which is currently not used but will be useful for safe implementation of the bdrv_co_write_compressed callback in format drivers.
Signed-off-by: Pavel Butsykin <pbutsy...@virtuozzo.com> Signed-off-by: Denis V. Lunev <d...@openvz.org> CC: Jeff Cody <jc...@redhat.com> CC: Markus Armbruster <arm...@redhat.com> CC: Eric Blake <ebl...@redhat.com> CC: John Snow <js...@redhat.com> CC: Stefan Hajnoczi <stefa...@redhat.com> CC: Kevin Wolf <kw...@redhat.com> --- block/io.c | 78 +++++++++++++++++++++++++++++++++++++++++++---- include/block/block_int.h | 5 +++ qemu-img.c | 2 +- 3 files changed, 78 insertions(+), 7 deletions(-) diff --git a/block/io.c b/block/io.c index c5bb6ae..54cd9a4 100644 --- a/block/io.c +++ b/block/io.c @@ -1779,8 +1779,8 @@ int bdrv_is_allocated_above(BlockDriverState *top, return 0; } -int bdrv_pwrite_compressed(BlockDriverState *bs, int64_t offset, - const void *buf, int count) +int coroutine_fn bdrv_co_pwritev_compressed(BlockDriverState *bs, + int64_t offset, unsigned int bytes, QEMUIOVector *qiov) { BlockDriver *drv = bs->drv; int ret; @@ -1788,18 +1788,84 @@ int bdrv_pwrite_compressed(BlockDriverState *bs, int64_t offset, if (!drv) { return -ENOMEDIUM; } - if (!drv->bdrv_write_compressed) { + + if (!drv->bdrv_co_write_compressed) { return -ENOTSUP; } - ret = bdrv_check_byte_request(bs, offset, count); + + ret = bdrv_check_byte_request(bs, offset, bytes); if (ret < 0) { return ret; } assert(QLIST_EMPTY(&bs->dirty_bitmaps)); + assert(qemu_in_coroutine()); + + return drv->bdrv_co_write_compressed(bs, offset >> BDRV_SECTOR_BITS, + bytes >> BDRV_SECTOR_BITS, qiov); +} + +typedef struct BdrvWriteCompressedCo { + BlockDriverState *bs; + int64_t offset; + QEMUIOVector *qiov; + int ret; +} BdrvWriteCompressedCo; + +static void bdrv_write_compressed_co_entry(void *opaque) +{ + BdrvWriteCompressedCo *co = opaque; + + co->ret = bdrv_co_pwritev_compressed(co->bs, co->offset, co->qiov->size, + co->qiov); +} + +int bdrv_pwrite_compressed(BlockDriverState *bs, int64_t offset, + const void *buf, int count) +{ + BdrvWriteCompressedCo data; + QEMUIOVector qiov; + BlockDriver *drv = bs->drv; + struct iovec iov = { + .iov_base = (void *)buf, + .iov_len = count, + }; + qemu_iovec_init_external(&qiov, &iov, 1); - return drv->bdrv_write_compressed(bs, offset >> BDRV_SECTOR_BITS, buf, - count >> BDRV_SECTOR_BITS); + data = (BdrvWriteCompressedCo) { + .bs = bs, + .offset = offset, + .qiov = &qiov, + .ret = -EINPROGRESS, + }; + + if (!drv) { + return -ENOMEDIUM; + } + + if (drv->bdrv_write_compressed) { + int ret = bdrv_check_byte_request(bs, offset, count); + if (ret < 0) { + return ret; + } + assert(QLIST_EMPTY(&bs->dirty_bitmaps)); + return drv->bdrv_write_compressed(bs, offset >> BDRV_SECTOR_BITS, buf, + count >> BDRV_SECTOR_BITS); + } + + if (qemu_in_coroutine()) { + /* Fast-path if already in coroutine context */ + bdrv_write_compressed_co_entry(&data); + } else { + AioContext *aio_context = bdrv_get_aio_context(bs); + + Coroutine *co = qemu_coroutine_create(bdrv_write_compressed_co_entry); + qemu_coroutine_enter(co, &data); + while (data.ret == -EINPROGRESS) { + aio_poll(aio_context, true); + } + } + return data.ret; } int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf, diff --git a/include/block/block_int.h b/include/block/block_int.h index 30a9717..ccba9c9 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -207,6 +207,9 @@ struct BlockDriver { int (*bdrv_write_compressed)(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors); + int coroutine_fn (*bdrv_co_write_compressed)(BlockDriverState *bs, + int64_t sector_num, int nb_sectors, QEMUIOVector *qiov); + int (*bdrv_snapshot_create)(BlockDriverState *bs, QEMUSnapshotInfo *sn_info); int (*bdrv_snapshot_goto)(BlockDriverState *bs, @@ -535,6 +538,8 @@ int coroutine_fn bdrv_co_preadv(BlockDriverState *bs, int coroutine_fn bdrv_co_pwritev(BlockDriverState *bs, int64_t offset, unsigned int bytes, QEMUIOVector *qiov, BdrvRequestFlags flags); +int coroutine_fn bdrv_co_pwritev_compressed(BlockDriverState *bs, + int64_t offset, unsigned int bytes, QEMUIOVector *qiov); int get_tmp_filename(char *filename, int size); BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size, diff --git a/qemu-img.c b/qemu-img.c index eb744d4..ab54027 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -2024,7 +2024,7 @@ static int img_convert(int argc, char **argv) const char *preallocation = qemu_opt_get(opts, BLOCK_OPT_PREALLOC); - if (!drv->bdrv_write_compressed) { + if (!drv->bdrv_write_compressed && !drv->bdrv_co_write_compressed) { error_report("Compression not supported for this file format"); ret = -1; goto out; -- 2.1.4