@@ -3107,6 +3107,14 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
vdev->device_endian = virtio_default_endian();
}
+ if (vdc->missing_features_migrated) {
+ uint64_t missing = (vdev->guest_features & ~(vdev->host_features));
+ if (missing && vdc->missing_features_migrated(vdev, missing)) {
+ vdev->host_features =
+ vdc->get_features(vdev, vdev->host_features, NULL);
+ }
+ }
+
if (virtio_64bit_features_needed(vdev)) {
/*
* Subsection load filled vdev->guest_features. Run them
@@ -158,6 +158,14 @@ struct VirtioDeviceClass {
* processed, e.g. for bounds checking.
*/
int (*post_load)(VirtIODevice *vdev);
+ /* In case when some of negotiated features are missing on the destination
+ system, the migration is expected to fail. To avoid such failure, the
+ device may implement this callback and apply graceful configuration
+ change to extend host features (for example, disable vhost).
+ If the device returns true the virtio reinitializes the host features
+ and further set_features call may succeed.
+ */
+ bool (*missing_features_migrated)(VirtIODevice *vdev, uint64_t val);
const VMStateDescription *vmsd;
bool (*primary_unplug_pending)(void *opaque);
};
This optional callback addresses migration problem in case some of negotiated features not present on the destination system. The device has a chance to avoid migration failure. Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com> --- hw/virtio/virtio.c | 8 ++++++++ include/hw/virtio/virtio.h | 8 ++++++++ 2 files changed, 16 insertions(+)