From ea76b33ca7a8c2fd39f50b6d1bb6702ab0a4fc87 Mon Sep 17 00:00:00 2001 From: fangyi Date: Sat, 22 Jun 2024 07:02:48 +0000 Subject: [PATCH 1/6] vdpa: fix vdpa device migrate rollback wrong when suspend device failed. 1. set vdpa->suspended before call vhost_dev_suspend to make sure vdpa device will resume when suspend failed. 2. using state == RUN_STATE_FINISH_MIGRATE instead of ms->state == MIGRATION_STATUS_ACTIVE to judge vm in migration. As migrate_fd_cancel will change ms->state, which will result in some vdpa devices not being suspended. Signed-off-by: fangyi --- hw/virtio/vdpa-dev-mig.c | 81 ++++------------------------------------ 1 file changed, 7 insertions(+), 74 deletions(-) diff --git a/hw/virtio/vdpa-dev-mig.c b/hw/virtio/vdpa-dev-mig.c index 887c96a201..7de996c835 100644 --- a/hw/virtio/vdpa-dev-mig.c +++ b/hw/virtio/vdpa-dev-mig.c @@ -130,100 +130,33 @@ free: static int vhost_vdpa_device_suspend(VhostVdpaDevice *vdpa) { VirtIODevice *vdev = VIRTIO_DEVICE(vdpa); - BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); - VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); - int ret; if (!vdpa->started || vdpa->suspended) { return 0; } - if (!k->set_guest_notifiers) { - return -EFAULT; - } - - vdpa->started = false; vdpa->suspended = true; - ret = vhost_dev_suspend(&vdpa->dev, vdev, false); - if (ret) { - goto suspend_fail; - } - - ret = k->set_guest_notifiers(qbus->parent, vdpa->dev.nvqs, false); - if (ret < 0) { - error_report("vhost guest notifier cleanup failed: %d\n", ret); - goto set_guest_notifiers_fail; - } - - vhost_dev_disable_notifiers(&vdpa->dev, vdev); - return ret; - -set_guest_notifiers_fail: - ret = k->set_guest_notifiers(qbus->parent, vdpa->dev.nvqs, true); - if (ret) { - error_report("vhost guest notifier restore failed: %d\n", ret); - } - -suspend_fail: - vdpa->suspended = false; - vdpa->started = true; - return ret; + return vhost_dev_suspend(&vdpa->dev, vdev, false); } static int vhost_vdpa_device_resume(VhostVdpaDevice *vdpa) { VirtIODevice *vdev = VIRTIO_DEVICE(vdpa); - BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); - VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); - int i, ret; + MigrationIncomingState *mis = migration_incoming_get_current(); + int ret; - if (vdpa->started || !vdpa->suspended) { + if (!vdpa->started || + (!vdpa->suspended && mis->state != RUN_STATE_RESTORE_VM)) { return 0; } - if (!k->set_guest_notifiers) { - error_report("binding does not support guest notifiers\n"); - return -ENOSYS; - } - - ret = vhost_dev_enable_notifiers(&vdpa->dev, vdev); + ret = vhost_dev_resume(&vdpa->dev, vdev, false); if (ret < 0) { - error_report("Error enabling host notifiers: %d\n", ret); return ret; } - ret = k->set_guest_notifiers(qbus->parent, vdpa->dev.nvqs, true); - if (ret < 0) { - error_report("Error binding guest notifier: %d\n", ret); - goto err_host_notifiers; - } - - vdpa->dev.acked_features = vdev->guest_features; - - ret = vhost_dev_resume(&vdpa->dev, vdev, false); - if (ret < 0) { - error_report("Error starting vhost: %d\n", ret); - goto err_guest_notifiers; - } - vdpa->started = true; vdpa->suspended = false; - - /* - * guest_notifier_mask/pending not used yet, so just unmask - * everything here. virtio-pci will do the right thing by - * enabling/disabling irqfd. - */ - for (i = 0; i < vdpa->dev.nvqs; i++) { - vhost_virtqueue_mask(&vdpa->dev, vdev, i, false); - } - - return ret; - -err_guest_notifiers: - k->set_guest_notifiers(qbus->parent, vdpa->dev.nvqs, false); -err_host_notifiers: - vhost_dev_disable_notifiers(&vdpa->dev, vdev); return ret; } @@ -248,7 +181,7 @@ static void vdpa_dev_vmstate_change(void *opaque, bool running, RunState state) MigrationIncomingState *mis = migration_incoming_get_current(); if (!running) { - if (ms->state == MIGRATION_STATUS_ACTIVE || state == RUN_STATE_PAUSED) { + if (state == RUN_STATE_FINISH_MIGRATE || state == RUN_STATE_PAUSED) { ret = vhost_vdpa_device_suspend(vdpa); if (ret) { error_report("suspend vdpa device failed: %d\n", ret); -- 2.43.0