[libvirt] [PATCH 1/8] lxc: Add job support to lxc driver

Katerina Koukiou k.koukiou at googlemail.com
Mon May 16 21:36:47 UTC 2016


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

Signed-off-by: Katerina Koukiou <k.koukiou at gmail.com>
---
 src/lxc/lxc_domain.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++----
 src/lxc/lxc_domain.h |  37 +++++++++++++
 2 files changed, 180 insertions(+), 11 deletions(-)

diff --git a/src/lxc/lxc_domain.c b/src/lxc/lxc_domain.c
index 3177a62..bca2bb2 100644
--- a/src/lxc/lxc_domain.c
+++ b/src/lxc/lxc_domain.c
@@ -30,22 +30,164 @@
 #include "virstring.h"
 #include "virutil.h"
 #include "virfile.h"
+#include "virtime.h"
 
 #define VIR_FROM_THIS VIR_FROM_LXC
 #define LXC_NAMESPACE_HREF "http://libvirt.org/schemas/domain/lxc/1.0"
 
+VIR_ENUM_IMPL(virLXCDomainJob, LXC_JOB_LAST,
+              "none",
+              "query",
+              "destroy",
+              "modify",
+);
+
 VIR_LOG_INIT("lxc.lxc_domain");
 
-static void *virLXCDomainObjPrivateAlloc(void)
+static int
+virLXCDomainObjInitJob(virLXCDomainObjPrivatePtr priv)
+{
+    memset(&priv->job, 0, sizeof(priv->job));
+
+    if (virCondInit(&priv->job.cond) < 0)
+        return -1;
+
+    return 0;
+}
+
+static void
+virLXCDomainObjResetJob(virLXCDomainObjPrivatePtr priv)
+{
+    struct virLXCDomainJobObj *job = &priv->job;
+
+    job->active = LXC_JOB_NONE;
+    job->owner = 0;
+}
+
+static void
+virLXCDomainObjFreeJob(virLXCDomainObjPrivatePtr priv)
+{
+    ignore_value(virCondDestroy(&priv->job.cond));
+}
+
+/* Give up waiting for mutex after 30 seconds */
+#define LXC_JOB_WAIT_TIME (1000ull * 30)
+
+/*
+ * obj must be locked before calling, virLXCDriverPtr 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
+virLXCDomainObjBeginJob(virLXCDriverPtr driver ATTRIBUTE_UNUSED,
+                       virDomainObjPtr obj,
+                       enum virLXCDomainJob job)
+{
+    virLXCDomainObjPrivatePtr priv = obj->privateData;
+    unsigned long long now;
+    unsigned long long then;
+
+    if (virTimeMillisNow(&now) < 0)
+        return -1;
+    then = now + LXC_JOB_WAIT_TIME;
+
+    virObjectRef(obj);
+
+    while (priv->job.active) {
+        VIR_DEBUG("Wait normal job condition for starting job: %s",
+                  virLXCDomainJobTypeToString(job));
+        if (virCondWaitUntil(&priv->job.cond, &obj->parent.lock, then) < 0)
+            goto error;
+    }
+
+    virLXCDomainObjResetJob(priv);
+
+    VIR_DEBUG("Starting job: %s", virLXCDomainJobTypeToString(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)",
+             virLXCDomainJobTypeToString(job),
+             obj->def->name,
+             virLXCDomainJobTypeToString(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 virLXCDomainBeginJob() 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
+virLXCDomainObjEndJob(virLXCDriverPtr driver ATTRIBUTE_UNUSED,
+                     virDomainObjPtr obj)
+{
+    virLXCDomainObjPrivatePtr priv = obj->privateData;
+    enum virLXCDomainJob job = priv->job.active;
+
+    VIR_DEBUG("Stopping job: %s",
+              virLXCDomainJobTypeToString(job));
+
+    virLXCDomainObjResetJob(priv);
+    virCondSignal(&priv->job.cond);
+
+    return virObjectUnref(obj);
+}
+
+
+static void *
+virLXCDomainObjPrivateAlloc(void)
 {
     virLXCDomainObjPrivatePtr priv;
 
     if (VIR_ALLOC(priv) < 0)
         return NULL;
 
+    if (virLXCDomainObjInitJob(priv) < 0) {
+        VIR_FREE(priv);
+        return NULL;
+    }
+
     return priv;
 }
 
+
+static void
+virLXCDomainObjPrivateFree(void *data)
+{
+    virLXCDomainObjPrivatePtr priv = data;
+
+    virCgroupFree(&priv->cgroup);
+    virLXCDomainObjFreeJob(priv);
+    VIR_FREE(priv);
+}
+
+
+
 VIR_ENUM_IMPL(virLXCDomainNamespace,
               VIR_LXC_DOMAIN_NAMESPACE_LAST,
               "sharenet",
@@ -190,16 +332,6 @@ virDomainXMLNamespace virLXCDriverDomainXMLNamespace = {
 };
 
 
-static void virLXCDomainObjPrivateFree(void *data)
-{
-    virLXCDomainObjPrivatePtr priv = data;
-
-    virCgroupFree(&priv->cgroup);
-
-    VIR_FREE(priv);
-}
-
-
 static int
 virLXCDomainObjPrivateXMLFormat(virBufferPtr buf,
                                 virDomainObjPtr vm)
diff --git a/src/lxc/lxc_domain.h b/src/lxc/lxc_domain.h
index 39c6e7d..e82c719 100644
--- a/src/lxc/lxc_domain.h
+++ b/src/lxc/lxc_domain.h
@@ -27,6 +27,7 @@
 # include "lxc_conf.h"
 # include "lxc_monitor.h"
 
+
 typedef enum {
     VIR_LXC_DOMAIN_NAMESPACE_SHARENET = 0,
     VIR_LXC_DOMAIN_NAMESPACE_SHAREIPC,
@@ -53,6 +54,28 @@ struct _lxcDomainDef {
     char *ns_val[VIR_LXC_DOMAIN_NAMESPACE_LAST];
 };
 
+
+/* Only 1 job is allowed at any time
+ * A job includes *all* lxc.so api, even those just querying
+ * information, not merely actions */
+
+enum virLXCDomainJob {
+    LXC_JOB_NONE = 0,      /* Always set to 0 for easy if (jobActive) conditions */
+    LXC_JOB_QUERY,         /* Doesn't change any state */
+    LXC_JOB_DESTROY,       /* Destroys the domain (cannot be masked out) */
+    LXC_JOB_MODIFY,        /* May change state */
+    LXC_JOB_LAST
+};
+VIR_ENUM_DECL(virLXCDomainJob)
+
+
+struct virLXCDomainJobObj {
+    virCond cond;                       /* Use to coordinate jobs */
+    enum virLXCDomainJob active;        /* Currently running job */
+    int owner;                          /* Thread which set current job */
+};
+
+
 typedef struct _virLXCDomainObjPrivate virLXCDomainObjPrivate;
 typedef virLXCDomainObjPrivate *virLXCDomainObjPrivatePtr;
 struct _virLXCDomainObjPrivate {
@@ -65,10 +88,24 @@ struct _virLXCDomainObjPrivate {
 
     virCgroupPtr cgroup;
     char *machineName;
+
+    struct virLXCDomainJobObj job;
 };
 
 extern virDomainXMLNamespace virLXCDriverDomainXMLNamespace;
 extern virDomainXMLPrivateDataCallbacks virLXCDriverPrivateDataCallbacks;
 extern virDomainDefParserConfig virLXCDriverDomainDefParserConfig;
 
+int
+virLXCDomainObjBeginJob(virLXCDriverPtr driver,
+                       virDomainObjPtr obj,
+                       enum virLXCDomainJob job)
+    ATTRIBUTE_RETURN_CHECK;
+
+bool
+virLXCDomainObjEndJob(virLXCDriverPtr driver,
+                     virDomainObjPtr obj)
+    ATTRIBUTE_RETURN_CHECK;
+
+
 #endif /* __LXC_DOMAIN_H__ */
-- 
2.7.4




More information about the libvir-list mailing list