From: Marco Cavenati Date: Fri, 10 Oct 2025 11:59:53 +0000 (+0200) Subject: migration: add FEATURE_SEEKABLE to QIOChannelBlock X-Git-Tag: v10.2.0-rc1~22^2~32 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=04a191cb36e71f4bb44d28af2b56b9624b36b0a1;p=thirdparty%2Fqemu.git migration: add FEATURE_SEEKABLE to QIOChannelBlock Enable the use of the mapped-ram migration feature with savevm/loadvm snapshots by adding the QIO_CHANNEL_FEATURE_SEEKABLE feature to QIOChannelBlock. Implement io_preadv and io_pwritev methods to provide positioned I/O capabilities that don't modify the channel's position pointer. Signed-off-by: Marco Cavenati Link: https://lore.kernel.org/r/20251010115954.1995298-2-Marco.Cavenati@eurecom.fr Signed-off-by: Peter Xu --- diff --git a/migration/channel-block.c b/migration/channel-block.c index 97de5a691b..9cf383d4b5 100644 --- a/migration/channel-block.c +++ b/migration/channel-block.c @@ -30,6 +30,7 @@ qio_channel_block_new(BlockDriverState *bs) QIOChannelBlock *ioc; ioc = QIO_CHANNEL_BLOCK(object_new(TYPE_QIO_CHANNEL_BLOCK)); + qio_channel_set_feature(QIO_CHANNEL(ioc), QIO_CHANNEL_FEATURE_SEEKABLE); bdrv_ref(bs); ioc->bs = bs; @@ -96,6 +97,47 @@ qio_channel_block_writev(QIOChannel *ioc, return qiov.size; } +static ssize_t +qio_channel_block_preadv(QIOChannel *ioc, + const struct iovec *iov, + size_t niov, + off_t offset, + Error **errp) +{ + QIOChannelBlock *bioc = QIO_CHANNEL_BLOCK(ioc); + QEMUIOVector qiov; + int ret; + + qemu_iovec_init_external(&qiov, (struct iovec *)iov, niov); + ret = bdrv_readv_vmstate(bioc->bs, &qiov, offset); + if (ret < 0) { + error_setg_errno(errp, -ret, "bdrv_readv_vmstate failed"); + return -1; + } + + return qiov.size; +} + +static ssize_t +qio_channel_block_pwritev(QIOChannel *ioc, + const struct iovec *iov, + size_t niov, + off_t offset, + Error **errp) +{ + QIOChannelBlock *bioc = QIO_CHANNEL_BLOCK(ioc); + QEMUIOVector qiov; + int ret; + + qemu_iovec_init_external(&qiov, (struct iovec *)iov, niov); + ret = bdrv_writev_vmstate(bioc->bs, &qiov, offset); + if (ret < 0) { + error_setg_errno(errp, -ret, "bdrv_writev_vmstate failed"); + return -1; + } + + return qiov.size; +} static int qio_channel_block_set_blocking(QIOChannel *ioc, @@ -177,6 +219,8 @@ qio_channel_block_class_init(ObjectClass *klass, ioc_klass->io_writev = qio_channel_block_writev; ioc_klass->io_readv = qio_channel_block_readv; ioc_klass->io_set_blocking = qio_channel_block_set_blocking; + ioc_klass->io_preadv = qio_channel_block_preadv; + ioc_klass->io_pwritev = qio_channel_block_pwritev; ioc_klass->io_seek = qio_channel_block_seek; ioc_klass->io_close = qio_channel_block_close; ioc_klass->io_set_aio_fd_handler = qio_channel_block_set_aio_fd_handler;