If a migration fails, we need to stop all block jobs running so
qemu doesn't try to send data to destination over and over again.
---
src/qemu/qemu_migration.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index ba602e4..95b6102 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -1645,6 +1645,46 @@ qemuMigrationStopNBDServer(virQEMUDriverPtr driver,
priv->nbdPort = 0;
}
+static void
+qemuMigrationCancelDriveMirror(qemuMigrationCookiePtr mig,
+ virQEMUDriverPtr driver,
+ virDomainObjPtr vm)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ size_t i;
+ char *diskAlias = NULL;
+
+ VIR_DEBUG("mig=%p nbdPort=%d", mig->nbd, priv->nbdPort);
+
+ for (i = 0; i < vm->def->ndisks; i++) {
+ virDomainDiskDefPtr disk = vm->def->disks[i];
+
+ /* skip shared, RO and source-less disks */
+ if (disk->shared || disk->readonly || !disk->src)
+ continue;
+
+ VIR_FREE(diskAlias);
+ if (virAsprintf(&diskAlias, "%s%s",
+ QEMU_DRIVE_HOST_PREFIX, disk->info.alias) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (qemuDomainObjEnterMonitorAsync(driver, vm,
+ QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
+ goto cleanup;
+
+ if (qemuMonitorBlockJob(priv->mon, diskAlias, NULL, 0,
+ NULL, BLOCK_JOB_ABORT, true) < 0)
+ VIR_WARN("Unable to stop block job on %s", diskAlias);
+ qemuDomainObjExitMonitor(driver, vm);
+ }
+
+cleanup:
+ VIR_FREE(diskAlias);
+ return;
+}
+
/* Validate whether the domain is safe to migrate. If vm is NULL,
* then this is being run in the v2 Prepare stage on the destination
* (where we only have the target xml); if vm is provided, then this
@@ -3054,6 +3094,9 @@ cleanup:
if (ret < 0 && !orig_err)
orig_err = virSaveLastError();
+ /* cancel any outstanding NBD jobs */
+ qemuMigrationCancelDriveMirror(mig, driver, vm);
+
if (spec->fwdType != MIGRATION_FWD_DIRECT) {
if (iothread && qemuMigrationStopTunnel(iothread, ret < 0) < 0)
ret = -1;
@@ -4261,6 +4304,9 @@ int qemuMigrationConfirm(virQEMUDriverPtr driver,
VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
} else {
+ /* cancel any outstanding NBD jobs */
+ qemuMigrationCancelDriveMirror(mig, driver, vm);
+
/* run 'cont' on the destination, which allows migration on qemu
* >= 0.10.6 to work properly. This isn't strictly necessary on
* older qemu's, but it also doesn't hurt anything there
--
1.8.0.2