Move QEMU domain lock / job helper code to separate file

To allow the APIs to be used from separate files, move the domain
lock / job helper code into qemu_domain.c

* src/qemu/qemu_domain.c, src/qemu/qemu_domain.h: Add domain lock
  / job code
* src/qemu/qemu_driver.c: Remove domain lock / job code
This commit is contained in:
Daniel P. Berrange 2010-12-16 16:12:02 +00:00
parent 22f4cb855c
commit 679d628c43
3 changed files with 246 additions and 226 deletions

View File

@ -30,12 +30,17 @@
#include "virterror_internal.h"
#include "c-ctype.h"
#include <sys/time.h>
#include <libxml/xpathInternals.h>
#define VIR_FROM_THIS VIR_FROM_QEMU
#define QEMU_NAMESPACE_HREF "http://libvirt.org/schemas/domain/qemu/1.0"
#define timeval_to_ms(tv) (((tv).tv_sec * 1000ull) + ((tv).tv_usec / 1000))
static void *qemuDomainObjPrivateAlloc(void)
{
qemuDomainObjPrivatePtr priv;
@ -372,3 +377,228 @@ void qemuDomainSetNamespaceHooks(virCapsPtr caps)
caps->ns.format = qemuDomainDefNamespaceFormatXML;
caps->ns.href = qemuDomainDefNamespaceHref;
}
/*
* obj must be locked before calling, qemud_driver must NOT be locked
*
* This must be called by anything that will change the VM state
* in any way, or anything that will use the QEMU monitor.
*
* Upon successful return, the object will have its ref count increased,
* successful calls must be followed by EndJob eventually
*/
/* Give up waiting for mutex after 30 seconds */
#define QEMU_JOB_WAIT_TIME (1000ull * 30)
int qemuDomainObjBeginJob(virDomainObjPtr obj)
{
qemuDomainObjPrivatePtr priv = obj->privateData;
struct timeval now;
unsigned long long then;
if (gettimeofday(&now, NULL) < 0) {
virReportSystemError(errno, "%s",
_("cannot get time of day"));
return -1;
}
then = timeval_to_ms(now) + QEMU_JOB_WAIT_TIME;
virDomainObjRef(obj);
while (priv->jobActive) {
if (virCondWaitUntil(&priv->jobCond, &obj->lock, then) < 0) {
virDomainObjUnref(obj);
if (errno == ETIMEDOUT)
qemuReportError(VIR_ERR_OPERATION_TIMEOUT,
"%s", _("cannot acquire state change lock"));
else
virReportSystemError(errno,
"%s", _("cannot acquire job mutex"));
return -1;
}
}
priv->jobActive = QEMU_JOB_UNSPECIFIED;
priv->jobSignals = 0;
memset(&priv->jobSignalsData, 0, sizeof(priv->jobSignalsData));
priv->jobStart = timeval_to_ms(now);
memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
return 0;
}
/*
* obj must be locked before calling, qemud_driver must be locked
*
* This must be called by anything that will change the VM state
* in any way, or anything that will use the QEMU monitor.
*/
int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver,
virDomainObjPtr obj)
{
qemuDomainObjPrivatePtr priv = obj->privateData;
struct timeval now;
unsigned long long then;
if (gettimeofday(&now, NULL) < 0) {
virReportSystemError(errno, "%s",
_("cannot get time of day"));
return -1;
}
then = timeval_to_ms(now) + QEMU_JOB_WAIT_TIME;
virDomainObjRef(obj);
qemuDriverUnlock(driver);
while (priv->jobActive) {
if (virCondWaitUntil(&priv->jobCond, &obj->lock, then) < 0) {
virDomainObjUnref(obj);
if (errno == ETIMEDOUT)
qemuReportError(VIR_ERR_OPERATION_TIMEOUT,
"%s", _("cannot acquire state change lock"));
else
virReportSystemError(errno,
"%s", _("cannot acquire job mutex"));
qemuDriverLock(driver);
return -1;
}
}
priv->jobActive = QEMU_JOB_UNSPECIFIED;
priv->jobSignals = 0;
memset(&priv->jobSignalsData, 0, sizeof(priv->jobSignalsData));
priv->jobStart = timeval_to_ms(now);
memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
virDomainObjUnlock(obj);
qemuDriverLock(driver);
virDomainObjLock(obj);
return 0;
}
/*
* obj must be locked before calling, qemud_driver does not matter
*
* To be called after completing the work associated with the
* earlier qemuDomainBeginJob() call
*
* Returns remaining refcount on 'obj', maybe 0 to indicated it
* was deleted
*/
int qemuDomainObjEndJob(virDomainObjPtr obj)
{
qemuDomainObjPrivatePtr priv = obj->privateData;
priv->jobActive = QEMU_JOB_NONE;
priv->jobSignals = 0;
memset(&priv->jobSignalsData, 0, sizeof(priv->jobSignalsData));
priv->jobStart = 0;
memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
virCondSignal(&priv->jobCond);
return virDomainObjUnref(obj);
}
/*
* obj must be locked before calling, qemud_driver must be unlocked
*
* To be called immediately before any QEMU monitor API call
* Must have already called qemuDomainObjBeginJob(), and checked
* that the VM is still active.
*
* To be followed with qemuDomainObjExitMonitor() once complete
*/
void qemuDomainObjEnterMonitor(virDomainObjPtr obj)
{
qemuDomainObjPrivatePtr priv = obj->privateData;
qemuMonitorLock(priv->mon);
qemuMonitorRef(priv->mon);
virDomainObjUnlock(obj);
}
/* obj must NOT be locked before calling, qemud_driver must be unlocked
*
* Should be paired with an earlier qemuDomainObjEnterMonitor() call
*/
void qemuDomainObjExitMonitor(virDomainObjPtr obj)
{
qemuDomainObjPrivatePtr priv = obj->privateData;
int refs;
refs = qemuMonitorUnref(priv->mon);
if (refs > 0)
qemuMonitorUnlock(priv->mon);
virDomainObjLock(obj);
if (refs == 0) {
virDomainObjUnref(obj);
priv->mon = NULL;
}
}
/*
* obj must be locked before calling, qemud_driver must be locked
*
* To be called immediately before any QEMU monitor API call
* Must have already called qemuDomainObjBeginJob().
*
* To be followed with qemuDomainObjExitMonitorWithDriver() once complete
*/
void qemuDomainObjEnterMonitorWithDriver(struct qemud_driver *driver,
virDomainObjPtr obj)
{
qemuDomainObjPrivatePtr priv = obj->privateData;
qemuMonitorLock(priv->mon);
qemuMonitorRef(priv->mon);
virDomainObjUnlock(obj);
qemuDriverUnlock(driver);
}
/* obj must NOT be locked before calling, qemud_driver must be unlocked,
* and will be locked after returning
*
* Should be paired with an earlier qemuDomainObjEnterMonitorWithDriver() call
*/
void qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver,
virDomainObjPtr obj)
{
qemuDomainObjPrivatePtr priv = obj->privateData;
int refs;
refs = qemuMonitorUnref(priv->mon);
if (refs > 0)
qemuMonitorUnlock(priv->mon);
qemuDriverLock(driver);
virDomainObjLock(obj);
if (refs == 0) {
virDomainObjUnref(obj);
priv->mon = NULL;
}
}
void qemuDomainObjEnterRemoteWithDriver(struct qemud_driver *driver,
virDomainObjPtr obj)
{
virDomainObjRef(obj);
virDomainObjUnlock(obj);
qemuDriverUnlock(driver);
}
void qemuDomainObjExitRemoteWithDriver(struct qemud_driver *driver,
virDomainObjPtr obj)
{
qemuDriverLock(driver);
virDomainObjLock(obj);
virDomainObjUnref(obj);
}

View File

@ -27,6 +27,7 @@
# include "threads.h"
# include "domain_conf.h"
# include "qemu_monitor.h"
# include "qemu_conf.h"
/* Only 1 job is allowed at any time
* A job includes *all* monitor commands, even those just querying
@ -80,4 +81,19 @@ struct _qemuDomainObjPrivate {
void qemuDomainSetPrivateDataHooks(virCapsPtr caps);
void qemuDomainSetNamespaceHooks(virCapsPtr caps);
int qemuDomainObjBeginJob(virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK;
int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver,
virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK;
int qemuDomainObjEndJob(virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK;
void qemuDomainObjEnterMonitor(virDomainObjPtr obj);
void qemuDomainObjExitMonitor(virDomainObjPtr obj);
void qemuDomainObjEnterMonitorWithDriver(struct qemud_driver *driver,
virDomainObjPtr obj);
void qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver,
virDomainObjPtr obj);
void qemuDomainObjEnterRemoteWithDriver(struct qemud_driver *driver,
virDomainObjPtr obj);
void qemuDomainObjExitRemoteWithDriver(struct qemud_driver *driver,
virDomainObjPtr obj);
#endif /* __QEMU_DOMAIN_H__ */

View File

@ -142,232 +142,6 @@ static int qemudVMFiltersInstantiate(virConnectPtr conn,
static struct qemud_driver *qemu_driver = NULL;
/*
* obj must be locked before calling, qemud_driver must NOT be locked
*
* This must be called by anything that will change the VM state
* in any way, or anything that will use the QEMU monitor.
*
* Upon successful return, the object will have its ref count increased,
* successful calls must be followed by EndJob eventually
*/
/* Give up waiting for mutex after 30 seconds */
#define QEMU_JOB_WAIT_TIME (1000ull * 30)
static int qemuDomainObjBeginJob(virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK;
static int qemuDomainObjBeginJob(virDomainObjPtr obj)
{
qemuDomainObjPrivatePtr priv = obj->privateData;
struct timeval now;
unsigned long long then;
if (gettimeofday(&now, NULL) < 0) {
virReportSystemError(errno, "%s",
_("cannot get time of day"));
return -1;
}
then = timeval_to_ms(now) + QEMU_JOB_WAIT_TIME;
virDomainObjRef(obj);
while (priv->jobActive) {
if (virCondWaitUntil(&priv->jobCond, &obj->lock, then) < 0) {
virDomainObjUnref(obj);
if (errno == ETIMEDOUT)
qemuReportError(VIR_ERR_OPERATION_TIMEOUT,
"%s", _("cannot acquire state change lock"));
else
virReportSystemError(errno,
"%s", _("cannot acquire job mutex"));
return -1;
}
}
priv->jobActive = QEMU_JOB_UNSPECIFIED;
priv->jobSignals = 0;
memset(&priv->jobSignalsData, 0, sizeof(priv->jobSignalsData));
priv->jobStart = timeval_to_ms(now);
memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
return 0;
}
/*
* obj must be locked before calling, qemud_driver must be locked
*
* This must be called by anything that will change the VM state
* in any way, or anything that will use the QEMU monitor.
*/
static int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver,
virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK;
static int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver,
virDomainObjPtr obj)
{
qemuDomainObjPrivatePtr priv = obj->privateData;
struct timeval now;
unsigned long long then;
if (gettimeofday(&now, NULL) < 0) {
virReportSystemError(errno, "%s",
_("cannot get time of day"));
return -1;
}
then = timeval_to_ms(now) + QEMU_JOB_WAIT_TIME;
virDomainObjRef(obj);
qemuDriverUnlock(driver);
while (priv->jobActive) {
if (virCondWaitUntil(&priv->jobCond, &obj->lock, then) < 0) {
virDomainObjUnref(obj);
if (errno == ETIMEDOUT)
qemuReportError(VIR_ERR_OPERATION_TIMEOUT,
"%s", _("cannot acquire state change lock"));
else
virReportSystemError(errno,
"%s", _("cannot acquire job mutex"));
qemuDriverLock(driver);
return -1;
}
}
priv->jobActive = QEMU_JOB_UNSPECIFIED;
priv->jobSignals = 0;
memset(&priv->jobSignalsData, 0, sizeof(priv->jobSignalsData));
priv->jobStart = timeval_to_ms(now);
memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
virDomainObjUnlock(obj);
qemuDriverLock(driver);
virDomainObjLock(obj);
return 0;
}
/*
* obj must be locked before calling, qemud_driver does not matter
*
* To be called after completing the work associated with the
* earlier qemuDomainBeginJob() call
*
* Returns remaining refcount on 'obj', maybe 0 to indicated it
* was deleted
*/
static int ATTRIBUTE_RETURN_CHECK qemuDomainObjEndJob(virDomainObjPtr obj)
{
qemuDomainObjPrivatePtr priv = obj->privateData;
priv->jobActive = QEMU_JOB_NONE;
priv->jobSignals = 0;
memset(&priv->jobSignalsData, 0, sizeof(priv->jobSignalsData));
priv->jobStart = 0;
memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
virCondSignal(&priv->jobCond);
return virDomainObjUnref(obj);
}
/*
* obj must be locked before calling, qemud_driver must be unlocked
*
* To be called immediately before any QEMU monitor API call
* Must have already called qemuDomainObjBeginJob(), and checked
* that the VM is still active.
*
* To be followed with qemuDomainObjExitMonitor() once complete
*/
static void qemuDomainObjEnterMonitor(virDomainObjPtr obj)
{
qemuDomainObjPrivatePtr priv = obj->privateData;
qemuMonitorLock(priv->mon);
qemuMonitorRef(priv->mon);
virDomainObjUnlock(obj);
}
/* obj must NOT be locked before calling, qemud_driver must be unlocked
*
* Should be paired with an earlier qemuDomainObjEnterMonitor() call
*/
static void qemuDomainObjExitMonitor(virDomainObjPtr obj)
{
qemuDomainObjPrivatePtr priv = obj->privateData;
int refs;
refs = qemuMonitorUnref(priv->mon);
if (refs > 0)
qemuMonitorUnlock(priv->mon);
virDomainObjLock(obj);
if (refs == 0) {
virDomainObjUnref(obj);
priv->mon = NULL;
}
}
/*
* obj must be locked before calling, qemud_driver must be locked
*
* To be called immediately before any QEMU monitor API call
* Must have already called qemuDomainObjBeginJob().
*
* To be followed with qemuDomainObjExitMonitorWithDriver() once complete
*/
static void qemuDomainObjEnterMonitorWithDriver(struct qemud_driver *driver, virDomainObjPtr obj)
{
qemuDomainObjPrivatePtr priv = obj->privateData;
qemuMonitorLock(priv->mon);
qemuMonitorRef(priv->mon);
virDomainObjUnlock(obj);
qemuDriverUnlock(driver);
}
/* obj must NOT be locked before calling, qemud_driver must be unlocked,
* and will be locked after returning
*
* Should be paired with an earlier qemuDomainObjEnterMonitorWithDriver() call
*/
static void qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver, virDomainObjPtr obj)
{
qemuDomainObjPrivatePtr priv = obj->privateData;
int refs;
refs = qemuMonitorUnref(priv->mon);
if (refs > 0)
qemuMonitorUnlock(priv->mon);
qemuDriverLock(driver);
virDomainObjLock(obj);
if (refs == 0) {
virDomainObjUnref(obj);
priv->mon = NULL;
}
}
static void qemuDomainObjEnterRemoteWithDriver(struct qemud_driver *driver,
virDomainObjPtr obj)
{
virDomainObjRef(obj);
virDomainObjUnlock(obj);
qemuDriverUnlock(driver);
}
static void qemuDomainObjExitRemoteWithDriver(struct qemud_driver *driver,
virDomainObjPtr obj)
{
qemuDriverLock(driver);
virDomainObjLock(obj);
virDomainObjUnref(obj);
}
static int doStartCPUs(struct qemud_driver *driver, virDomainObjPtr vm, virConnectPtr conn)
{
int ret;