]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: Add support for domain cleanup callbacks
authorJiri Denemark <jdenemar@redhat.com>
Fri, 16 Mar 2012 06:52:26 +0000 (07:52 +0100)
committerJiri Denemark <jdenemar@redhat.com>
Wed, 21 Mar 2012 16:31:08 +0000 (17:31 +0100)
Add support for registering cleanup callbacks to be run when a domain
transitions to shutoff state.

src/qemu/qemu_domain.c
src/qemu/qemu_domain.h
src/qemu/qemu_process.c

index 625c59546fb65da9a9ce8ee5eb21fe8341b0f795..a9469cf4c7b65e89f55897e29d9083117f70dfb6 100644 (file)
@@ -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;
+}
index be9e34df6c7ded4355b03a150386e51eaa3a9264..4fdec6255fe054ccab470cc861122be2c0ec6e23 100644 (file)
@@ -101,6 +101,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 {
@@ -137,6 +140,10 @@ struct _qemuDomainObjPrivate {
     char *origname;
 
     virConsolesPtr cons;
+
+    qemuDomainCleanupCallback *cleanupCallbacks;
+    size_t ncleanupCallbacks;
+    size_t ncleanupCallbacks_max;
 };
 
 struct qemuDomainWatchdogEvent
@@ -314,4 +321,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__ */
index 0af3751a6eef940c27783aa7d2f12f0c6106e9af..19458644f58bf67d438ba11946ab5ab2b53a468e 100644 (file)
@@ -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);