From: Andrey Drobyshev <[email protected]> CPR migration with a vhost-vsock device currently crashes the target QEMU. The device ownership is not handed over, so while the source QEMU still holds the guest CID hashed in the kernel, the target's freshly opened vhost-vsock device fails to set the same CID in realize():
qemu-system-x86_64: -device vhost-vsock-pci,id=vsock0,guest-cid=3: vhost-vsock: unable to set guest cid: Address already in use Add an unconditional migration blocker for the CPR modes, so that such a migration fails early and gracefully instead. The following patches implement the actual vhost-vsock CPR support, and the blocker is lifted once it's fully working. Signed-off-by: Andrey Drobyshev <[email protected]> Reviewed-by: Michael S. Tsirkin <[email protected]> Signed-off-by: Michael S. Tsirkin <[email protected]> Message-ID: <[email protected]> --- include/hw/virtio/vhost-vsock.h | 1 + hw/virtio/vhost-vsock.c | 27 +++++++++++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/include/hw/virtio/vhost-vsock.h b/include/hw/virtio/vhost-vsock.h index 84f4e727c7..a964d57e1b 100644 --- a/include/hw/virtio/vhost-vsock.h +++ b/include/hw/virtio/vhost-vsock.h @@ -29,6 +29,7 @@ struct VHostVSock { /*< private >*/ VHostVSockCommon parent; VHostVSockConf conf; + Error *migration_blocker; /* CPR migration is not supported */ /*< public >*/ }; diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c index da244eb165..503d248a61 100644 --- a/hw/virtio/vhost-vsock.c +++ b/hw/virtio/vhost-vsock.c @@ -20,6 +20,8 @@ #include "hw/core/qdev-properties.h" #include "hw/virtio/vhost-vsock.h" #include "monitor/monitor.h" +#include "migration/blocker.h" +#include "migration/misc.h" static void vhost_vsock_get_config(VirtIODevice *vdev, uint8_t *config) { @@ -140,25 +142,38 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp) return; } + /* + * CPR migration of a vhost-vsock device is not supported yet: the + * device ownership is not handed over, so the target fails to set + * up its device. Fail the migration early and gracefully instead. + */ + error_setg(&vsock->migration_blocker, + "vhost-vsock: CPR migration is not supported"); + if (migrate_add_blocker_modes(&vsock->migration_blocker, + BIT(MIG_MODE_CPR_TRANSFER) | + BIT(MIG_MODE_CPR_EXEC), errp) < 0) { + return; + } + if (vsock->conf.vhostfd) { vhostfd = monitor_fd_param(monitor_cur(), vsock->conf.vhostfd, errp); if (vhostfd == -1) { error_prepend(errp, "vhost-vsock: unable to parse vhostfd: "); - return; + goto err_blocker; } if (!qemu_set_blocking(vhostfd, false, errp)) { - return; + goto err_blocker; } } else { vhostfd = open("/dev/vhost-vsock", O_RDWR); if (vhostfd < 0) { error_setg_file_open(errp, errno, "/dev/vhost-vsock"); - return; + goto err_blocker; } if (!qemu_set_blocking(vhostfd, false, errp)) { - return; + goto err_blocker; } } @@ -187,16 +202,20 @@ err_vhost_dev: vhost_dev_cleanup(&vvc->vhost_dev); err_virtio: vhost_vsock_common_unrealize(vdev); +err_blocker: + migrate_del_blocker(&vsock->migration_blocker); } static void vhost_vsock_device_unrealize(DeviceState *dev) { VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(dev); VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VHostVSock *vsock = VHOST_VSOCK(dev); /* This will stop vhost backend if appropriate. */ vhost_vsock_set_status(vdev, 0); + migrate_del_blocker(&vsock->migration_blocker); vhost_dev_cleanup(&vvc->vhost_dev); vhost_vsock_common_unrealize(vdev); } -- MST
