libxl: Add job support to libxl driver

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

Signed-off-by: Jim Fehlig <jfehlig@suse.com>
This commit is contained in:
Jim Fehlig 2013-12-19 13:54:39 +08:00
parent 343119a44b
commit 4b4b61c329
2 changed files with 166 additions and 0 deletions

View File

@ -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)

View File

@ -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 */