Add support for registering cleanup callbacks to be run when a domain
transitions to shutoff state.
---
src/qemu/qemu_domain.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_domain.h | 15 +++++++++
src/qemu/qemu_process.c | 2 +
3 files changed, 90 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 625c595..a9469cf 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -232,6 +232,7 @@ static void qemuDomainObjPrivateFree(void *data)
VIR_ERROR(_("Unexpected QEMU agent still active during domain
deletion"));
qemuAgentClose(priv->agent);
}
+ VIR_FREE(priv->cleanupCallbacks);
VIR_FREE(priv);
}
@@ -1769,3 +1770,75 @@ qemuDomainCheckDiskPresence(struct qemud_driver *driver,
cleanup:
return ret;
}
+
+/*
+ * The vm must be locked when any of the following cleanup functions is
+ * called.
+ */
+int
+qemuDomainCleanupAdd(virDomainObjPtr vm,
+ qemuDomainCleanupCallback cb)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ int i;
+
+ VIR_DEBUG("vm=%s, cb=%p", vm->def->name, cb);
+
+ for (i = 0; i < priv->ncleanupCallbacks; i++) {
+ if (priv->cleanupCallbacks[i] == cb)
+ return 0;
+ }
+
+ if (VIR_RESIZE_N(priv->cleanupCallbacks,
+ priv->ncleanupCallbacks_max,
+ priv->ncleanupCallbacks, 1) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ priv->cleanupCallbacks[priv->ncleanupCallbacks++] = cb;
+ return 0;
+}
+
+void
+qemuDomainCleanupRemove(virDomainObjPtr vm,
+ qemuDomainCleanupCallback cb)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ int i;
+
+ VIR_DEBUG("vm=%s, cb=%p", vm->def->name, cb);
+
+ for (i = 0; i < priv->ncleanupCallbacks; i++) {
+ if (priv->cleanupCallbacks[i] == cb) {
+ memmove(priv->cleanupCallbacks + i,
+ priv->cleanupCallbacks + i + 1,
+ priv->ncleanupCallbacks - i - 1);
+ priv->ncleanupCallbacks--;
+ }
+ }
+
+ VIR_SHRINK_N(priv->cleanupCallbacks,
+ priv->ncleanupCallbacks_max,
+ priv->ncleanupCallbacks_max - priv->ncleanupCallbacks);
+}
+
+void
+qemuDomainCleanupRun(struct qemud_driver *driver,
+ virDomainObjPtr vm)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ int i;
+
+ VIR_DEBUG("driver=%p, vm=%s", driver, vm->def->name);
+
+ /* run cleanup callbacks in reverse order */
+ for (i = priv->ncleanupCallbacks - 1; i >= 0; i--) {
+ if (priv->cleanupCallbacks[i])
+ priv->cleanupCallbacks[i](driver, vm);
+ }
+
+ VIR_FREE(priv->cleanupCallbacks);
+ priv->ncleanupCallbacks = 0;
+ priv->ncleanupCallbacks_max = 0;
+}
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index f8e943f..af83c0e 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -94,6 +94,9 @@ struct qemuDomainJobObj {
typedef struct _qemuDomainPCIAddressSet qemuDomainPCIAddressSet;
typedef qemuDomainPCIAddressSet *qemuDomainPCIAddressSetPtr;
+typedef void (*qemuDomainCleanupCallback)(struct qemud_driver *driver,
+ virDomainObjPtr vm);
+
typedef struct _qemuDomainObjPrivate qemuDomainObjPrivate;
typedef qemuDomainObjPrivate *qemuDomainObjPrivatePtr;
struct _qemuDomainObjPrivate {
@@ -130,6 +133,10 @@ struct _qemuDomainObjPrivate {
char *origname;
virConsolesPtr cons;
+
+ qemuDomainCleanupCallback *cleanupCallbacks;
+ size_t ncleanupCallbacks;
+ size_t ncleanupCallbacks_max;
};
struct qemuDomainWatchdogEvent
@@ -307,4 +314,12 @@ bool qemuDomainJobAllowed(qemuDomainObjPrivatePtr priv,
int qemuDomainCheckDiskPresence(struct qemud_driver *driver,
virDomainObjPtr vm,
bool start_with_state);
+
+int qemuDomainCleanupAdd(virDomainObjPtr vm,
+ qemuDomainCleanupCallback cb);
+void qemuDomainCleanupRemove(virDomainObjPtr vm,
+ qemuDomainCleanupCallback cb);
+void qemuDomainCleanupRun(struct qemud_driver *driver,
+ virDomainObjPtr vm);
+
#endif /* __QEMU_DOMAIN_H__ */
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 0af3751..1945864 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3803,6 +3803,8 @@ void qemuProcessStop(struct qemud_driver *driver,
/* shut it off for sure */
ignore_value(qemuProcessKill(driver, vm, VIR_QEMU_PROCESS_KILL_FORCE));
+ qemuDomainCleanupRun(driver, vm);
+
/* Stop autodestroy in case guest is restarted */
qemuProcessAutoDestroyRemove(driver, vm);
--
1.7.8.5