[libvirt] [PATCH 07/19] qemu: Add support for job phase

Jiri Denemark jdenemar at redhat.com
Thu Jul 7 23:34:12 UTC 2011


Asynchronous jobs may take long time to finish and may consist of
several phases which we need to now about to help with recovery/rollback
after libvirtd restarts.
---
 src/qemu/qemu_domain.c |   75 +++++++++++++++++++++++++++++++++++++++++++++++-
 src/qemu/qemu_domain.h |    9 ++++++
 2 files changed, 83 insertions(+), 1 deletions(-)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index b26308e..d0dd764 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -65,6 +65,46 @@ VIR_ENUM_IMPL(qemuDomainAsyncJob, QEMU_ASYNC_JOB_LAST,
 );
 
 
+const char *
+qemuDomainAsyncJobPhaseToString(enum qemuDomainAsyncJob job,
+                                int phase ATTRIBUTE_UNUSED)
+{
+    switch (job) {
+    case QEMU_ASYNC_JOB_MIGRATION_OUT:
+    case QEMU_ASYNC_JOB_MIGRATION_IN:
+    case QEMU_ASYNC_JOB_SAVE:
+    case QEMU_ASYNC_JOB_DUMP:
+    case QEMU_ASYNC_JOB_NONE:
+    case QEMU_ASYNC_JOB_LAST:
+        ; /* fall through */
+    }
+
+    return "none";
+}
+
+int
+qemuDomainAsyncJobPhaseFromString(enum qemuDomainAsyncJob job,
+                                  const char *phase)
+{
+    if (!phase)
+        return 0;
+
+    switch (job) {
+    case QEMU_ASYNC_JOB_MIGRATION_OUT:
+    case QEMU_ASYNC_JOB_MIGRATION_IN:
+    case QEMU_ASYNC_JOB_SAVE:
+    case QEMU_ASYNC_JOB_DUMP:
+    case QEMU_ASYNC_JOB_NONE:
+    case QEMU_ASYNC_JOB_LAST:
+        ; /* fall through */
+    }
+
+    if (STREQ(phase, "none"))
+        return 0;
+    else
+        return -1;
+}
+
 static void qemuDomainEventDispatchFunc(virConnectPtr conn,
                                         virDomainEventPtr event,
                                         virConnectDomainEventGenericCallback cb,
@@ -135,6 +175,7 @@ qemuDomainObjResetAsyncJob(qemuDomainObjPrivatePtr priv)
     struct qemuDomainJobObj *job = &priv->job;
 
     job->asyncJob = QEMU_ASYNC_JOB_NONE;
+    job->phase = 0;
     job->mask = DEFAULT_JOB_MASK;
     job->start = 0;
     memset(&job->info, 0, sizeof(job->info));
@@ -151,6 +192,7 @@ qemuDomainObjRestoreJob(virDomainObjPtr obj,
     memset(job, 0, sizeof(*job));
     job->active = priv->job.active;
     job->asyncJob = priv->job.asyncJob;
+    job->phase = priv->job.phase;
 
     qemuDomainObjResetJob(priv);
     qemuDomainObjResetAsyncJob(priv);
@@ -249,9 +291,15 @@ static int qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data)
         virBufferAsprintf(buf, "  <lockstate>%s</lockstate>\n", priv->lockState);
 
     if (priv->job.active || priv->job.asyncJob) {
-        virBufferAsprintf(buf, "  <job type='%s' async='%s'/>\n",
+        virBufferAsprintf(buf, "  <job type='%s' async='%s'",
                           qemuDomainJobTypeToString(priv->job.active),
                           qemuDomainAsyncJobTypeToString(priv->job.asyncJob));
+        if (priv->job.phase) {
+            virBufferAsprintf(buf, " phase='%s'",
+                              qemuDomainAsyncJobPhaseToString(
+                                    priv->job.asyncJob, priv->job.phase));
+        }
+        virBufferAddLit(buf, "/>\n");
     }
 
     return 0;
@@ -384,6 +432,17 @@ static int qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, void *data)
         }
         VIR_FREE(tmp);
         priv->job.asyncJob = async;
+
+        if ((tmp = virXPathString("string(./job[1]/@phase)", ctxt))) {
+            priv->job.phase = qemuDomainAsyncJobPhaseFromString(async, tmp);
+            if (priv->job.phase < 0) {
+                qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                                _("Unknown job phase %s"), tmp);
+                VIR_FREE(tmp);
+                goto error;
+            }
+            VIR_FREE(tmp);
+        }
     }
 
     return 0;
@@ -595,6 +654,20 @@ qemuDomainObjSaveJob(struct qemud_driver *driver, virDomainObjPtr obj)
 }
 
 void
+qemuDomainObjSetJobPhase(struct qemud_driver *driver,
+                         virDomainObjPtr obj,
+                         int phase)
+{
+    qemuDomainObjPrivatePtr priv = obj->privateData;
+
+    if (!priv->job.asyncJob)
+        return;
+
+    priv->job.phase = phase;
+    qemuDomainObjSaveJob(driver, obj);
+}
+
+void
 qemuDomainObjSetAsyncJobMask(virDomainObjPtr obj,
                              unsigned long long allowedJobs)
 {
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 49be3d2..7245e67 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -91,6 +91,7 @@ struct qemuDomainJobObj {
 
     virCond asyncCond;                  /* Use to coordinate with async jobs */
     enum qemuDomainAsyncJob asyncJob;   /* Currently active async job */
+    int phase;                          /* Job phase (mainly for migrations) */
     unsigned long long mask;            /* Jobs allowed during async job */
     unsigned long long start;           /* When the async job started */
     virDomainJobInfo info;              /* Async job progress data */
@@ -133,6 +134,11 @@ struct qemuDomainWatchdogEvent
     int action;
 };
 
+const char *qemuDomainAsyncJobPhaseToString(enum qemuDomainAsyncJob job,
+                                            int phase);
+int qemuDomainAsyncJobPhaseFromString(enum qemuDomainAsyncJob job,
+                                      const char *phase);
+
 void qemuDomainEventFlush(int timer ATTRIBUTE_UNUSED, void *opaque);
 
 /* driver must be locked before calling */
@@ -175,6 +181,9 @@ void qemuDomainObjEndNestedJob(struct qemud_driver *driver,
                                virDomainObjPtr obj);
 
 void qemuDomainObjSaveJob(struct qemud_driver *driver, virDomainObjPtr obj);
+void qemuDomainObjSetJobPhase(struct qemud_driver *driver,
+                              virDomainObjPtr obj,
+                              int phase);
 void qemuDomainObjSetAsyncJobMask(virDomainObjPtr obj,
                                   unsigned long long allowedJobs);
 void qemuDomainObjRestoreJob(virDomainObjPtr obj,
-- 
1.7.6




More information about the libvir-list mailing list