job->mask = DEFAULT_JOB_MASK;
job->start = 0;
job->dump_memory_only = false;
+ job->asyncAbort = false;
memset(&job->info, 0, sizeof(job->info));
}
return virObjectUnref(obj);
}
+void
+qemuDomainObjAbortAsyncJob(virDomainObjPtr obj)
+{
+ qemuDomainObjPrivatePtr priv = obj->privateData;
+
+ VIR_DEBUG("Requesting abort of async job: %s",
+ qemuDomainAsyncJobTypeToString(priv->job.asyncJob));
+
+ priv->job.asyncAbort = true;
+}
+
static int
qemuDomainObjEnterMonitorInternal(struct qemud_driver *driver,
bool driver_locked,
unsigned long long start; /* When the async job started */
bool dump_memory_only; /* use dump-guest-memory to do dump */
virDomainJobInfo info; /* Async job progress data */
+ bool asyncAbort; /* abort of async job requested */
};
typedef struct _qemuDomainPCIAddressSet qemuDomainPCIAddressSet;
bool qemuDomainObjEndAsyncJob(struct qemud_driver *driver,
virDomainObjPtr obj)
ATTRIBUTE_RETURN_CHECK;
+void qemuDomainObjAbortAsyncJob(virDomainObjPtr obj);
void qemuDomainObjSetJobPhase(struct qemud_driver *driver,
virDomainObjPtr obj,
int phase);
}
VIR_DEBUG("Cancelling job at client request");
+ qemuDomainObjAbortAsyncJob(vm);
qemuDomainObjEnterMonitor(driver, vm);
ret = qemuMonitorMigrateCancel(priv->mon);
qemuDomainObjExitMonitor(driver, vm);
QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
goto cleanup;
+ if (priv->job.asyncAbort) {
+ /* explicitly do this *after* we entered the monitor,
+ * as this is a critical section so we are guaranteed
+ * priv->job.asyncAbort will not change */
+ qemuDomainObjExitMonitorWithDriver(driver, vm);
+ virReportError(VIR_ERR_OPERATION_ABORTED, _("%s: %s"),
+ qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
+ _("canceled by client"));
+ goto cleanup;
+ }
+
if (qemuMonitorSetMigrationSpeed(priv->mon, migrate_speed) < 0) {
qemuDomainObjExitMonitorWithDriver(driver, vm);
goto cleanup;