When preserving a vhost fd using CPR, call VHOST_RESET_OWNER prior to CPR in old QEMU. Otherwise, new QEMU will fail when it calls VHOST_SET_OWNER during vhost_dev_init.
Signed-off-by: Mark Kanda <mark.ka...@oracle.com> Signed-off-by: Steve Sistare <steven.sist...@oracle.com> --- include/hw/virtio/vhost.h | 1 + hw/virtio/vhost.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index 38800a7..88a4838 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -132,6 +132,7 @@ struct vhost_dev { QLIST_ENTRY(vhost_dev) logdev_entry; QLIST_HEAD(, vhost_iommu) iommu_list; IOMMUNotifier n; + NotifierWithReturn cpr_transfer_notifier; const VhostDevConfigOps *config_ops; }; diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index fc43853..a562e0c 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -24,6 +24,7 @@ #include "standard-headers/linux/vhost_types.h" #include "hw/virtio/virtio-bus.h" #include "hw/mem/memory-device.h" +#include "migration/misc.h" #include "migration/blocker.h" #include "migration/qemu-file-types.h" #include "system/dma.h" @@ -1506,6 +1507,32 @@ static void vhost_virtqueue_cleanup(struct vhost_virtqueue *vq) } } +static int vhost_cpr_notifier(NotifierWithReturn *notifier, + MigrationEvent *e, Error **errp) +{ + struct vhost_dev *dev; + int r; + + dev = container_of(notifier, struct vhost_dev, cpr_transfer_notifier); + + if (dev->vhost_ops->backend_type != VHOST_BACKEND_TYPE_KERNEL) { + return 0; + } + + if (e->type == MIG_EVENT_PRECOPY_SETUP) { + r = dev->vhost_ops->vhost_reset_device(dev); + if (r < 0) { + VHOST_OPS_DEBUG(r, "vhost_reset_device failed"); + } + } else if (e->type == MIG_EVENT_PRECOPY_FAILED) { + r = dev->vhost_ops->vhost_set_owner(dev); + if (r < 0) { + VHOST_OPS_DEBUG(r, "vhost_set_owner failed"); + } + } + return 0; +} + int vhost_dev_init(struct vhost_dev *hdev, void *opaque, VhostBackendType backend_type, uint32_t busyloop_timeout, Error **errp) @@ -1516,6 +1543,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, hdev->vdev = NULL; hdev->migration_blocker = NULL; + hdev->cpr_transfer_notifier.notify = NULL; r = vhost_set_backend_type(hdev, backend_type); assert(r >= 0); @@ -1616,6 +1644,9 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, hdev->log_enabled = false; hdev->started = false; memory_listener_register(&hdev->memory_listener, &address_space_memory); + migration_add_notifier_mode(&hdev->cpr_transfer_notifier, + vhost_cpr_notifier, + MIG_MODE_CPR_TRANSFER); QLIST_INSERT_HEAD(&vhost_devices, hdev, entry); /* @@ -1672,6 +1703,7 @@ void vhost_dev_cleanup(struct vhost_dev *hdev) QLIST_REMOVE(hdev, entry); } migrate_del_blocker(&hdev->migration_blocker); + migration_remove_notifier(&hdev->cpr_transfer_notifier); g_free(hdev->mem); g_free(hdev->mem_sections); if (hdev->vhost_ops) { -- 1.8.3.1