From 679d628c430b8729041f6d19c0e544388a3c3b96 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Thu, 16 Dec 2010 16:12:02 +0000 Subject: [PATCH] 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 --- src/qemu/qemu_domain.c | 230 +++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_domain.h | 16 +++ src/qemu/qemu_driver.c | 226 ---------------------------------------- 3 files changed, 246 insertions(+), 226 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 14364ffe78..27f353fe26 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -30,12 +30,17 @@ #include "virterror_internal.h" #include "c-ctype.h" +#include + #include #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); +} diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 0d1e2224c3..870a900c9d 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -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__ */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 9f2e536750..1c4ccedb8d 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -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;