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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list