[libvirt PATCH 22/80] qemu: Handle 'postcopy-paused' migration state

Jiri Denemark jdenemar at redhat.com
Tue May 10 15:20:43 UTC 2022


When connection breaks during post-copy migration, QEMU enters
'postcopy-paused' state. We need to handle this state and make the
situation visible to upper layers.

Signed-off-by: Jiri Denemark <jdenemar at redhat.com>
---
 src/hypervisor/domain_job.c  |  1 +
 src/hypervisor/domain_job.h  |  1 +
 src/qemu/qemu_driver.c       |  1 +
 src/qemu/qemu_migration.c    | 11 +++++++++++
 src/qemu/qemu_monitor.c      |  1 +
 src/qemu/qemu_monitor.h      |  1 +
 src/qemu/qemu_monitor_json.c |  1 +
 src/qemu/qemu_process.c      | 33 ++++++++++++++++++++-------------
 8 files changed, 37 insertions(+), 13 deletions(-)

diff --git a/src/hypervisor/domain_job.c b/src/hypervisor/domain_job.c
index ff4e008cb5..49867c3982 100644
--- a/src/hypervisor/domain_job.c
+++ b/src/hypervisor/domain_job.c
@@ -93,6 +93,7 @@ virDomainJobStatusToType(virDomainJobStatus status)
     case VIR_DOMAIN_JOB_STATUS_MIGRATING:
     case VIR_DOMAIN_JOB_STATUS_HYPERVISOR_COMPLETED:
     case VIR_DOMAIN_JOB_STATUS_POSTCOPY:
+    case VIR_DOMAIN_JOB_STATUS_POSTCOPY_PAUSED:
     case VIR_DOMAIN_JOB_STATUS_PAUSED:
         return VIR_DOMAIN_JOB_UNBOUNDED;
 
diff --git a/src/hypervisor/domain_job.h b/src/hypervisor/domain_job.h
index db8b8b1390..fce35ffbf5 100644
--- a/src/hypervisor/domain_job.h
+++ b/src/hypervisor/domain_job.h
@@ -78,6 +78,7 @@ typedef enum {
     VIR_DOMAIN_JOB_STATUS_HYPERVISOR_COMPLETED,
     VIR_DOMAIN_JOB_STATUS_PAUSED,
     VIR_DOMAIN_JOB_STATUS_POSTCOPY,
+    VIR_DOMAIN_JOB_STATUS_POSTCOPY_PAUSED,
     VIR_DOMAIN_JOB_STATUS_COMPLETED,
     VIR_DOMAIN_JOB_STATUS_FAILED,
     VIR_DOMAIN_JOB_STATUS_CANCELED,
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 9e6cf26001..d19115473a 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -12514,6 +12514,7 @@ qemuDomainGetJobInfoMigrationStats(virQEMUDriver *driver,
     case VIR_DOMAIN_JOB_STATUS_HYPERVISOR_COMPLETED:
     case VIR_DOMAIN_JOB_STATUS_POSTCOPY:
     case VIR_DOMAIN_JOB_STATUS_PAUSED:
+    case VIR_DOMAIN_JOB_STATUS_POSTCOPY_PAUSED:
         if (events &&
             jobData->status != VIR_DOMAIN_JOB_STATUS_ACTIVE &&
             qemuMigrationAnyFetchStats(driver, vm, VIR_ASYNC_JOB_NONE,
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 72a2846d1f..e5e33556e3 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -1757,6 +1757,10 @@ qemuMigrationUpdateJobType(virDomainJobData *jobData)
         jobData->status = VIR_DOMAIN_JOB_STATUS_POSTCOPY;
         break;
 
+    case QEMU_MONITOR_MIGRATION_STATUS_POSTCOPY_PAUSED:
+        jobData->status = VIR_DOMAIN_JOB_STATUS_POSTCOPY_PAUSED;
+        break;
+
     case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED:
         jobData->status = VIR_DOMAIN_JOB_STATUS_HYPERVISOR_COMPLETED;
         break;
@@ -1883,6 +1887,12 @@ qemuMigrationJobCheckStatus(virQEMUDriver *driver,
                        qemuMigrationJobName(vm), _("canceled by client"));
         return -1;
 
+    case VIR_DOMAIN_JOB_STATUS_POSTCOPY_PAUSED:
+        virReportError(VIR_ERR_OPERATION_FAILED, _("%s: %s"),
+                       qemuMigrationJobName(vm),
+                       _("post-copy phase failed"));
+        return -1;
+
     case VIR_DOMAIN_JOB_STATUS_COMPLETED:
     case VIR_DOMAIN_JOB_STATUS_ACTIVE:
     case VIR_DOMAIN_JOB_STATUS_MIGRATING:
@@ -1985,6 +1995,7 @@ qemuMigrationAnyCompleted(virQEMUDriver *driver,
 
     case VIR_DOMAIN_JOB_STATUS_FAILED:
     case VIR_DOMAIN_JOB_STATUS_CANCELED:
+    case VIR_DOMAIN_JOB_STATUS_POSTCOPY_PAUSED:
         /* QEMU aborted the migration. */
         return -1;
 
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 98cf1c949e..36cf4e57b5 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -149,6 +149,7 @@ VIR_ENUM_IMPL(qemuMonitorMigrationStatus,
               "inactive", "setup",
               "active", "pre-switchover",
               "device", "postcopy-active",
+              "postcopy-paused",
               "completed", "failed",
               "cancelling", "cancelled",
               "wait-unplug",
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index abc29eaf4c..46cdc04925 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -831,6 +831,7 @@ typedef enum {
     QEMU_MONITOR_MIGRATION_STATUS_PRE_SWITCHOVER,
     QEMU_MONITOR_MIGRATION_STATUS_DEVICE,
     QEMU_MONITOR_MIGRATION_STATUS_POSTCOPY,
+    QEMU_MONITOR_MIGRATION_STATUS_POSTCOPY_PAUSED,
     QEMU_MONITOR_MIGRATION_STATUS_COMPLETED,
     QEMU_MONITOR_MIGRATION_STATUS_ERROR,
     QEMU_MONITOR_MIGRATION_STATUS_CANCELLING,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 532aad348e..ac3ec42fdd 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -3242,6 +3242,7 @@ qemuMonitorJSONGetMigrationStatsReply(virJSONValue *reply,
 
     case QEMU_MONITOR_MIGRATION_STATUS_ACTIVE:
     case QEMU_MONITOR_MIGRATION_STATUS_POSTCOPY:
+    case QEMU_MONITOR_MIGRATION_STATUS_POSTCOPY_PAUSED:
     case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED:
     case QEMU_MONITOR_MIGRATION_STATUS_CANCELLING:
     case QEMU_MONITOR_MIGRATION_STATUS_PRE_SWITCHOVER:
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 53221ea9ff..fc61aa71a0 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -1568,19 +1568,26 @@ qemuProcessHandleMigrationStatus(qemuMonitor *mon G_GNUC_UNUSED,
     privJob->stats.mig.status = status;
     virDomainObjBroadcast(vm);
 
-    if (status == QEMU_MONITOR_MIGRATION_STATUS_POSTCOPY &&
-        priv->job.asyncJob == VIR_ASYNC_JOB_MIGRATION_OUT &&
-        virDomainObjGetState(vm, &reason) == VIR_DOMAIN_PAUSED &&
-        reason == VIR_DOMAIN_PAUSED_MIGRATION) {
-        VIR_DEBUG("Correcting paused state reason for domain %s to %s",
-                  vm->def->name,
-                  virDomainPausedReasonTypeToString(VIR_DOMAIN_PAUSED_POSTCOPY));
-
-        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_POSTCOPY);
-        event = virDomainEventLifecycleNewFromObj(vm,
-                                                  VIR_DOMAIN_EVENT_SUSPENDED,
-                                                  VIR_DOMAIN_EVENT_SUSPENDED_POSTCOPY);
-        qemuDomainSaveStatus(vm);
+    if (priv->job.asyncJob == VIR_ASYNC_JOB_MIGRATION_OUT &&
+        virDomainObjGetState(vm, &reason) == VIR_DOMAIN_PAUSED) {
+        if (status == QEMU_MONITOR_MIGRATION_STATUS_POSTCOPY_PAUSED) {
+            /* At this point no thread is watching the migration progress on
+             * the source as it is just waiting for the Finish phase to end.
+             * Thus we need to handle the event here. */
+            qemuMigrationSrcPostcopyFailed(vm);
+            qemuDomainSaveStatus(vm);
+        } else if (status == QEMU_MONITOR_MIGRATION_STATUS_POSTCOPY &&
+                   reason == VIR_DOMAIN_PAUSED_MIGRATION) {
+            VIR_DEBUG("Correcting paused state reason for domain %s to %s",
+                      vm->def->name,
+                      virDomainPausedReasonTypeToString(VIR_DOMAIN_PAUSED_POSTCOPY));
+
+            virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_POSTCOPY);
+            event = virDomainEventLifecycleNewFromObj(vm,
+                                                      VIR_DOMAIN_EVENT_SUSPENDED,
+                                                      VIR_DOMAIN_EVENT_SUSPENDED_POSTCOPY);
+            qemuDomainSaveStatus(vm);
+        }
     }
 
  cleanup:
-- 
2.35.1



More information about the libvir-list mailing list