When destroying a domain we need to make sure we will be able to start a
job no matter what other operations are running or even stuck in a job.
This is done by killing the domain before starting the destroy job.
Let's introduce qemuProcessBeginStopJob which combines killing a domain
and starting a job in a single API which can be called everywhere we
need a job to stop a domain.
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
src/qemu/qemu_driver.c | 43 ++++++++++---------------------------------
src/qemu/qemu_process.c | 39 +++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_process.h | 4 ++++
3 files changed, 53 insertions(+), 33 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 2bbc724..1770f81 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2272,44 +2272,21 @@ qemuDomainDestroyFlags(virDomainPtr dom,
if (virDomainDestroyFlagsEnsureACL(dom->conn, vm->def) < 0)
goto cleanup;
+ if (qemuProcessBeginStopJob(driver, vm, QEMU_JOB_DESTROY,
+ !(flags & VIR_DOMAIN_DESTROY_GRACEFUL)) < 0)
+ goto cleanup;
+
+ if (!virDomainObjIsActive(vm)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("domain is not running"));
+ goto endjob;
+ }
+
qemuDomainSetFakeReboot(driver, vm, false);
if (priv->job.asyncJob == QEMU_ASYNC_JOB_MIGRATION_IN)
stopFlags |= VIR_QEMU_PROCESS_STOP_MIGRATED;
- /* We need to prevent monitor EOF callback from doing our work (and sending
- * misleading events) while the vm is unlocked inside BeginJob/ProcessKill API
- */
- priv->beingDestroyed = true;
-
- /* Although qemuProcessStop does this already, there may
- * be an outstanding job active. We want to make sure we
- * can kill the process even if a job is active. Killing
- * it now means the job will be released
- */
- if (flags & VIR_DOMAIN_DESTROY_GRACEFUL) {
- if (qemuProcessKill(vm, 0) < 0) {
- priv->beingDestroyed = false;
- goto cleanup;
- }
- } else {
- if (qemuProcessKill(vm, VIR_QEMU_PROCESS_KILL_FORCE) < 0) {
- priv->beingDestroyed = false;
- goto cleanup;
- }
- }
-
- if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_DESTROY) < 0)
- goto cleanup;
-
- priv->beingDestroyed = false;
-
- if (!virDomainObjIsActive(vm)) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- "%s", _("domain is not running"));
- goto endjob;
- }
-
qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED, stopFlags);
event = virDomainEventLifecycleNewFromObj(vm,
VIR_DOMAIN_EVENT_STOPPED,
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 6a44073..2f9df7c 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5348,6 +5348,45 @@ qemuProcessKill(virDomainObjPtr vm, unsigned int flags)
}
+/**
+ * qemuProcessBeginStopJob:
+ *
+ * Stop all current jobs by killing the domain and start a new one for
+ * qemuProcessStop.
+ */
+int
+qemuProcessBeginStopJob(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ qemuDomainJob job,
+ bool forceKill)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ unsigned int killFlags = forceKill ? VIR_QEMU_PROCESS_KILL_FORCE : 0;
+ int ret = -1;
+
+ /* We need to prevent monitor EOF callback from doing our work (and
+ * sending misleading events) while the vm is unlocked inside
+ * BeginJob/ProcessKill API
+ */
+ priv->beingDestroyed = true;
+
+ if (qemuProcessKill(vm, killFlags) < 0)
+ goto cleanup;
+
+ /* Wake up anything waiting on domain condition */
+ virDomainObjBroadcast(vm);
+
+ if (qemuDomainObjBeginJob(driver, vm, job) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+ cleanup:
+ priv->beingDestroyed = false;
+ return ret;
+}
+
+
void qemuProcessStop(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainShutoffReason reason,
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index b16919d..69be99e 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -114,6 +114,10 @@ typedef enum {
VIR_QEMU_PROCESS_STOP_NO_RELABEL = 1 << 1,
} qemuProcessStopFlags;
+int qemuProcessBeginStopJob(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ qemuDomainJob job,
+ bool forceKill);
void qemuProcessStop(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainShutoffReason reason,
--
2.7.1