mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-01 17:35:17 +00:00
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:
parent
22f4cb855c
commit
679d628c43
@ -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);
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user