[libvirt] [PATCH v4 3/5] qemu: Track domain quiesced status

Tomoki Sekiyama tomoki.sekiyama at hds.com
Wed Mar 26 22:28:51 UTC 2014


Adds an quiesced flag into qemuDomainObjPrivate that tracks whether guest
filesystems of the domain is quiesced or not.

It also modify error code from qemuDomainSnapshotFSFreeze and
qemuDomainSnapshotFSThaw, so that a caller can know whether the command is
actually sent to the guest agent. If the error is caused before sending a
freeze command, a counterpart thaw command shouldn't be sent either, not to
thaw the guest unexpectedly by error handling code.

Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama at hds.com>
---
 src/qemu/qemu_domain.c |    5 ++++
 src/qemu/qemu_domain.h |    2 +
 src/qemu/qemu_driver.c |   66 +++++++++++++++++++++++++++++++++++++++---------
 3 files changed, 60 insertions(+), 13 deletions(-)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 36cb2c6..52aa09d 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -357,6 +357,9 @@ qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data)
         virBufferAddLit(buf, "</devices>\n");
     }
 
+    if (priv->quiesced)
+        virBufferAddLit(buf, "<quiesced/>\n");
+
     return 0;
 }
 
@@ -518,6 +521,8 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, void *data)
     }
     VIR_FREE(nodes);
 
+    priv->quiesced = virXPathBoolean("boolean(./quiesced)", ctxt) == 1;
+
     return 0;
 
  error:
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index b2830c4..5fb1665 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -176,6 +176,8 @@ struct _qemuDomainObjPrivate {
     char **qemuDevices; /* NULL-terminated list of devices aliases known to QEMU */
 
     bool hookRun;  /* true if there was a hook run over this domain */
+
+    bool quiesced; /* true if the domain filesystems are quiesced */
 };
 
 typedef enum {
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b032441..7fd8b6d 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -12100,32 +12100,61 @@ qemuDomainPrepareDiskChainElement(virQEMUDriverPtr driver,
 }
 
 
+/* Return -1 if request is not sent to agent due to misconfig, -2 if request
+ * is sent but failed, and number of frozen filesystems on success. */
 static int
-qemuDomainSnapshotFSFreeze(virDomainObjPtr vm)
+qemuDomainSnapshotFSFreeze(virQEMUDriverPtr driver, virDomainObjPtr vm)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
+    virQEMUDriverConfigPtr cfg;
     int freezed;
 
     if (!qemuDomainAgentAvailable(priv, true))
         return -1;
 
+    if (priv->quiesced) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("domain is already quiesced"));
+        return -1;
+    }
+
     qemuDomainObjEnterAgent(vm);
     freezed = qemuAgentFSFreeze(priv->agent);
     qemuDomainObjExitAgent(vm);
 
-    return freezed;
+    if (freezed >= 0)
+        priv->quiesced = true;
+
+    cfg = virQEMUDriverGetConfig(driver);
+    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) {
+        virObjectUnref(cfg);
+        return -2;
+    }
+    virObjectUnref(cfg);
+
+    return freezed < 0 ? -2 : freezed;
 }
 
+/* Return -1 if request is not sent to agent due to misconfig, -2 if request
+ * is send but failed, and number of thawed filesystems on success. */
 static int
-qemuDomainSnapshotFSThaw(virDomainObjPtr vm, bool report)
+qemuDomainSnapshotFSThaw(virQEMUDriverPtr driver,
+                         virDomainObjPtr vm, bool report)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
+    virQEMUDriverConfigPtr cfg;
     int thawed;
     virErrorPtr err = NULL;
 
     if (!qemuDomainAgentAvailable(priv, report))
         return -1;
 
+    if (!priv->quiesced && report) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("domain is not quiesced"));
+        return -1;
+    }
+
     qemuDomainObjEnterAgent(vm);
     if (!report)
         err = virSaveLastError();
@@ -12134,8 +12163,18 @@ qemuDomainSnapshotFSThaw(virDomainObjPtr vm, bool report)
         virSetError(err);
     qemuDomainObjExitAgent(vm);
 
+    if (thawed >= 0)
+        priv->quiesced = false;
+
+    cfg = virQEMUDriverGetConfig(driver);
+    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) {
+        virObjectUnref(cfg);
+        return -2;
+    }
+    virObjectUnref(cfg);
+
     virFreeError(err);
-    return thawed;
+    return thawed < 0 ? -2 : thawed;
 }
 
 /* The domain is expected to be locked and inactive. */
@@ -13114,17 +13153,18 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn,
         goto cleanup;
 
     /* If quiesce was requested, then issue a freeze command, and a
-     * counterpart thaw command, no matter what.  The command will
-     * fail if the guest is paused or the guest agent is not
-     * running.  */
+     * counterpart thaw command when it is actually sent to agent.
+     * The command will fail if the guest is paused or the guest agent
+     * is not running, or is already quiesced.  */
     if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) {
-        if (qemuDomainSnapshotFSFreeze(vm) < 0) {
-            /* helper reported the error */
-            thaw = -1;
+        int freeze = qemuDomainSnapshotFSFreeze(driver, vm);
+        if (freeze < 0) {
+            /* the helper reported the error */
+            if (freeze == -2)
+                thaw = -1; /* the command is sent but agent failed */
             goto endjob;
-        } else {
-            thaw = 1;
         }
+        thaw = 1;
     }
 
     /* We need to track what state the guest is in, since taking the
@@ -13265,7 +13305,7 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn,
         goto cleanup;
     }
     if (vm && thaw != 0 &&
-        qemuDomainSnapshotFSThaw(vm, thaw > 0) < 0) {
+        qemuDomainSnapshotFSThaw(driver, vm, thaw > 0) < 0) {
         /* helper reported the error, if it was needed */
         if (thaw > 0)
             ret = -1;




More information about the libvir-list mailing list