[libvirt] [PATCH V2 03/13] libxl: Add job support to libxl driver

Jim Fehlig jfehlig at suse.com
Thu Feb 13 01:56:17 UTC 2014


Follows the pattern used in the QEMU driver for managing multiple,
simultaneous jobs within the driver.

Signed-off-by: Jim Fehlig <jfehlig at suse.com>
---

V2:
  Add ATTRIBUTE_RETURN_CHECK to libxlDomainObjEndJob

 src/libxl/libxl_domain.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++
 src/libxl/libxl_domain.h |  38 ++++++++++++++
 2 files changed, 166 insertions(+)

diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index eb2e50e..fdc4661 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -30,10 +30,18 @@
 #include "virerror.h"
 #include "virlog.h"
 #include "virstring.h"
+#include "virtime.h"
 
 #define VIR_FROM_THIS VIR_FROM_LIBXL
 
 
+VIR_ENUM_IMPL(libxlDomainJob, LIBXL_JOB_LAST,
+              "none",
+              "query",
+              "destroy",
+              "modify",
+);
+
 /* Object used to store info related to libxl event registrations */
 typedef struct _libxlEventHookInfo libxlEventHookInfo;
 typedef libxlEventHookInfo *libxlEventHookInfoPtr;
@@ -284,6 +292,119 @@ static const libxl_osevent_hooks libxl_event_callbacks = {
     .timeout_deregister = libxlDomainObjTimeoutDeregisterEventHook,
 };
 
+static int
+libxlDomainObjInitJob(libxlDomainObjPrivatePtr priv)
+{
+    memset(&priv->job, 0, sizeof(priv->job));
+
+    if (virCondInit(&priv->job.cond) < 0)
+        return -1;
+
+    return 0;
+}
+
+static void
+libxlDomainObjResetJob(libxlDomainObjPrivatePtr priv)
+{
+    struct libxlDomainJobObj *job = &priv->job;
+
+    job->active = LIBXL_JOB_NONE;
+    job->owner = 0;
+}
+
+static void
+libxlDomainObjFreeJob(libxlDomainObjPrivatePtr priv)
+{
+    ignore_value(virCondDestroy(&priv->job.cond));
+}
+
+/* Give up waiting for mutex after 30 seconds */
+#define LIBXL_JOB_WAIT_TIME (1000ull * 30)
+
+/*
+ * obj must be locked before calling, libxlDriverPrivatePtr must NOT be locked
+ *
+ * This must be called by anything that will change the VM state
+ * in any way
+ *
+ * Upon successful return, the object will have its ref count increased,
+ * successful calls must be followed by EndJob eventually
+ */
+int
+libxlDomainObjBeginJob(libxlDriverPrivatePtr driver ATTRIBUTE_UNUSED,
+                       virDomainObjPtr obj,
+                       enum libxlDomainJob job)
+{
+    libxlDomainObjPrivatePtr priv = obj->privateData;
+    unsigned long long now;
+    unsigned long long then;
+
+    if (virTimeMillisNow(&now) < 0)
+        return -1;
+    then = now + LIBXL_JOB_WAIT_TIME;
+
+    virObjectRef(obj);
+
+    while (priv->job.active) {
+        VIR_DEBUG("Wait normal job condition for starting job: %s",
+                  libxlDomainJobTypeToString(job));
+        if (virCondWaitUntil(&priv->job.cond, &obj->parent.lock, then) < 0)
+            goto error;
+    }
+
+    libxlDomainObjResetJob(priv);
+
+    VIR_DEBUG("Starting job: %s", libxlDomainJobTypeToString(job));
+    priv->job.active = job;
+    priv->job.owner = virThreadSelfID();
+
+    return 0;
+
+error:
+    VIR_WARN("Cannot start job (%s) for domain %s;"
+             " current job is (%s) owned by (%d)",
+             libxlDomainJobTypeToString(job),
+             obj->def->name,
+             libxlDomainJobTypeToString(priv->job.active),
+             priv->job.owner);
+
+    if (errno == ETIMEDOUT)
+        virReportError(VIR_ERR_OPERATION_TIMEOUT,
+                       "%s", _("cannot acquire state change lock"));
+    else
+        virReportSystemError(errno,
+                             "%s", _("cannot acquire job mutex"));
+
+    virObjectUnref(obj);
+    return -1;
+}
+
+/*
+ * obj must be locked before calling
+ *
+ * To be called after completing the work associated with the
+ * earlier libxlDomainBeginJob() call
+ *
+ * Returns true if the remaining reference count on obj is
+ * non-zero, false if the reference count has dropped to zero
+ * and obj is disposed.
+ */
+bool
+libxlDomainObjEndJob(libxlDriverPrivatePtr driver ATTRIBUTE_UNUSED,
+                     virDomainObjPtr obj)
+{
+    libxlDomainObjPrivatePtr priv = obj->privateData;
+    enum libxlDomainJob job = priv->job.active;
+
+    VIR_DEBUG("Stopping job: %s",
+              libxlDomainJobTypeToString(job));
+
+    libxlDomainObjResetJob(priv);
+    virCondSignal(&priv->job.cond);
+
+    return virObjectUnref(obj);
+}
+
 static void *
 libxlDomainObjPrivateAlloc(void)
 {
@@ -300,6 +421,12 @@ libxlDomainObjPrivateAlloc(void)
         return NULL;
     }
 
+    if (libxlDomainObjInitJob(priv) < 0) {
+        virChrdevFree(priv->devs);
+        virObjectUnref(priv);
+        return NULL;
+    }
+
     return priv;
 }
 
@@ -311,6 +438,7 @@ libxlDomainObjPrivateDispose(void *obj)
     if (priv->deathW)
         libxl_evdisable_domain_death(priv->ctx, priv->deathW);
 
+    libxlDomainObjFreeJob(priv);
     virChrdevFree(priv->devs);
     libxl_ctx_free(priv->ctx);
     if (priv->logger_file)
diff --git a/src/libxl/libxl_domain.h b/src/libxl/libxl_domain.h
index 8565820..0a29d38 100644
--- a/src/libxl/libxl_domain.h
+++ b/src/libxl/libxl_domain.h
@@ -30,6 +30,31 @@
 # include "libxl_conf.h"
 # include "virchrdev.h"
 
+# define JOB_MASK(job)                  (1 << (job - 1))
+# define DEFAULT_JOB_MASK               \
+    (JOB_MASK(LIBXL_JOB_DESTROY) |      \
+     JOB_MASK(LIBXL_JOB_ABORT))
+
+/* Only 1 job is allowed at any time
+ * A job includes *all* libxl.so api, even those just querying
+ * information, not merely actions */
+enum libxlDomainJob {
+    LIBXL_JOB_NONE = 0,      /* Always set to 0 for easy if (jobActive) conditions */
+    LIBXL_JOB_QUERY,         /* Doesn't change any state */
+    LIBXL_JOB_DESTROY,       /* Destroys the domain (cannot be masked out) */
+    LIBXL_JOB_MODIFY,        /* May change state */
+
+    LIBXL_JOB_LAST
+};
+VIR_ENUM_DECL(libxlDomainJob)
+
+
+struct libxlDomainJobObj {
+    virCond cond;                       /* Use to coordinate jobs */
+    enum libxlDomainJob active;         /* Currently running job */
+    int owner;                          /* Thread which set current job */
+};
+
 typedef struct _libxlDomainObjPrivate libxlDomainObjPrivate;
 typedef libxlDomainObjPrivate *libxlDomainObjPrivatePtr;
 struct _libxlDomainObjPrivate {
@@ -43,6 +68,8 @@ struct _libxlDomainObjPrivate {
     /* console */
     virChrdevsPtr devs;
     libxl_evgen_domain_death *deathW;
+
+    struct libxlDomainJobObj job;
 };
 
 
@@ -53,4 +80,15 @@ extern virDomainDefParserConfig libxlDomainDefParserConfig;
 int
 libxlDomainObjPrivateInitCtx(virDomainObjPtr vm);
 
+int
+libxlDomainObjBeginJob(libxlDriverPrivatePtr driver,
+                       virDomainObjPtr obj,
+                       enum libxlDomainJob job)
+    ATTRIBUTE_RETURN_CHECK;
+
+bool
+libxlDomainObjEndJob(libxlDriverPrivatePtr driver,
+                     virDomainObjPtr obj)
+    ATTRIBUTE_RETURN_CHECK;
+
 #endif /* LIBXL_DOMAIN_H */
-- 
1.8.1.4




More information about the libvir-list mailing list