Follows the pattern used in the libxl driver for managing multiple, simultaneous jobs within the driver. Signed-off-by: Katerina Koukiou <k.koukiou@xxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list