]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: migration: Don't crash on access to 'current' job
authorPeter Krempa <pkrempa@redhat.com>
Fri, 27 Apr 2018 14:20:15 +0000 (16:20 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Mon, 30 Apr 2018 12:43:42 +0000 (14:43 +0200)
When a VM is destroyed while being migrated (waiting in
qemuMigrationSrcWaitForCompletion) the private object cleanup code frees
the 'current' job info. Since the migration code attempts to setup
various aspects of the current job even on failure this results into a
crash.

Job data is cleared in qemuDomainObjPrivateDataClear since commit
888aa4b6b9db

Fix this by skipping all of the code which requires the qemu process to
be alive if the VM is not active any more.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
src/qemu/qemu_migration.c

index b913e999289320191db3649b690218e2986935fc..1a857329ec6311834a74dc2cd6a1bf689ee82db5 100644 (file)
@@ -3561,27 +3561,28 @@ qemuMigrationSrcRun(virQEMUDriverPtr driver,
  error:
     orig_err = virSaveLastError();
 
-    if (cancel &&
-        priv->job.current->status != QEMU_DOMAIN_JOB_STATUS_QEMU_COMPLETED &&
-        virDomainObjIsActive(vm) &&
-        qemuDomainObjEnterMonitorAsync(driver, vm,
-                                       QEMU_ASYNC_JOB_MIGRATION_OUT) == 0) {
-        qemuMonitorMigrateCancel(priv->mon);
-        ignore_value(qemuDomainObjExitMonitor(driver, vm));
-    }
+    if (virDomainObjIsActive(vm)) {
+        if (cancel &&
+            priv->job.current->status != QEMU_DOMAIN_JOB_STATUS_QEMU_COMPLETED &&
+            qemuDomainObjEnterMonitorAsync(driver, vm,
+                                           QEMU_ASYNC_JOB_MIGRATION_OUT) == 0) {
+            qemuMonitorMigrateCancel(priv->mon);
+            ignore_value(qemuDomainObjExitMonitor(driver, vm));
+        }
 
-    /* cancel any outstanding NBD jobs */
-    if (mig && mig->nbd)
-        qemuMigrationSrcCancelDriveMirror(driver, vm, false,
-                                          QEMU_ASYNC_JOB_MIGRATION_OUT,
-                                          dconn);
+        /* cancel any outstanding NBD jobs */
+        if (mig && mig->nbd)
+            qemuMigrationSrcCancelDriveMirror(driver, vm, false,
+                                              QEMU_ASYNC_JOB_MIGRATION_OUT,
+                                              dconn);
+
+        if (priv->job.current->status != QEMU_DOMAIN_JOB_STATUS_CANCELED)
+            priv->job.current->status = QEMU_DOMAIN_JOB_STATUS_FAILED;
+    }
 
     if (iothread)
         qemuMigrationSrcStopTunnel(iothread, true);
 
-    if (priv->job.current->status != QEMU_DOMAIN_JOB_STATUS_CANCELED)
-        priv->job.current->status = QEMU_DOMAIN_JOB_STATUS_FAILED;
-
     goto cleanup;
 
  exit_monitor: