From: Andrey Drobyshev <[email protected]>
During CPR (checkpoint-restore) migration the guest keeps running on the
same host, so instead of reopening /dev/vhost-vsock on the destination,
we should reuse the FD from the source. The FD is saved in the CPR
namespace (hash table) with cpr_save_fd() and then reclaimed on the
target via cpr_find_fd().
Since the key in CPR hash table is device ID, CPR needs a unique ID.
Thus we only preserve the FD with cpr_{save,find} if this ID is present.
In a following patch, when we lift the CPR migration blocker, we're
going to condition it on the presence of ID.
vhost_dev_init() (and thus VHOST_SET_OWNER) still runs in realize() here.
Deferring the ownership handoff to pre_save/post_load is done in a
following patch. Until then CPR remains blocked, so the restore path
added here is not reachable yet.
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]>
---
hw/virtio/vhost-vsock.c | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c
index 3ec20d8760..cec2c31f0c 100644
--- a/hw/virtio/vhost-vsock.c
+++ b/hw/virtio/vhost-vsock.c
@@ -143,6 +143,7 @@ static void vhost_vsock_device_realize(DeviceState *dev,
Error **errp)
VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(dev);
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VHostVSock *vsock = VHOST_VSOCK(dev);
+ DeviceState *proxy = qdev_get_parent_bus(DEVICE(vsock))->parent;
int vhostfd;
int ret;
@@ -170,7 +171,19 @@ static void vhost_vsock_device_realize(DeviceState *dev,
Error **errp)
return;
}
- if (vsock->conf.vhostfd) {
+ if (cpr_is_incoming()) {
+ /* Reuse the fd handed over from the source QEMU. */
+ if (!proxy->id) {
+ error_setg(errp, "vhost-vsock: device ID is required for "
+ "CPR migration");
+ goto err_blocker;
+ }
+ vhostfd = cpr_find_fd(proxy->id, 0);
+ if (vhostfd < 0) {
+ error_setg(errp, "vhost-vsock: could not find restored vhost FD");
+ goto err_blocker;
+ }
+ } else 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: ");
@@ -207,6 +220,11 @@ static void vhost_vsock_device_realize(DeviceState *dev,
Error **errp)
goto err_vhost_dev;
}
+ /* Register the fd for a future CPR after a fully successful realize */
+ if (proxy->id) {
+ cpr_save_fd(proxy->id, 0, vhostfd);
+ }
+
return;
err_vhost_dev:
@@ -223,10 +241,14 @@ static void vhost_vsock_device_unrealize(DeviceState *dev)
VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(dev);
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VHostVSock *vsock = VHOST_VSOCK(dev);
+ DeviceState *proxy = qdev_get_parent_bus(dev)->parent;
/* This will stop vhost backend if appropriate. */
vhost_vsock_set_status(vdev, 0);
+ if (proxy->id) {
+ cpr_delete_fd(proxy->id, 0);
+ }
migrate_del_blocker(&vsock->migration_blocker);
vhost_dev_cleanup(&vvc->vhost_dev);
vhost_vsock_common_unrealize(vdev);
--
MST