From: Peter Krempa <[email protected]> Similarly to how we enter monitor context, so that the VM object is unlocked while waiting for qemu, there are non-monitor operations where we might want to yield the domain object (while holding a JOB on the domain object) so that other threads are not blocked e.g. on looking upi a list of active domains.
This basically copies the helpers to enter monitor minus locking of the monitor object. Signed-off-by: Peter Krempa <[email protected]> --- src/qemu/qemu_domain.c | 65 ++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_domain.h | 8 ++++++ 2 files changed, 73 insertions(+) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 9368ab916d..ea591e4c95 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -5287,6 +5287,71 @@ qemuDomainObjExitRemote(virDomainObj *obj, } +/** + * qemuDomainObjEnterOperation: + * @obj: domain object + * + * @obj must be locked when this function is called. + * + * Enter a potentially long running operation on @vm. Unlocks @vm and allows + * other threads to e.g. look up the object. + * + * This requires that virDomainObjBeginJob() was already called on @vm and + * checked that the VM is still active. + * + * To be followed with qemuDomainObjExitOperation() once complete + */ +int +qemuDomainObjEnterOperation(virDomainObj *obj, + virDomainAsyncJob asyncJob) +{ + if (asyncJob != VIR_ASYNC_JOB_NONE) { + int ret; + if ((ret = virDomainObjBeginNestedJob(obj, asyncJob)) < 0) + return ret; + if (!virDomainObjIsActive(obj)) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("domain is no longer running")); + virDomainObjEndJob(obj); + return -1; + } + } else if (obj->job->asyncOwner == virThreadSelfID()) { + VIR_WARN("This thread seems to be the async job owner; entering operation without asking for a nested job is dangerous"); + } else if (obj->job->owner != virThreadSelfID()) { + VIR_WARN("Entering an operation without owning a job. Job %s owner %s (%llu)", + virDomainJobTypeToString(obj->job->active), + obj->job->ownerAPI, obj->job->owner); + } + + VIR_DEBUG("Entering operation (vm=%p name=%s)", + obj, obj->def->name); + virObjectUnlock(obj); + + return 0; +} + + +/** + * qemuDomainObjExitOperation: + * @obj: domain object + * + * @obj must be *UNLOCKED* when this is called. + * + * Enter normal context on return from the long running operation started by + * qemuDomainObjEnterOperation(). + */ +void +qemuDomainObjExitOperation(virDomainObj *obj) +{ + virObjectLock(obj); + VIR_DEBUG("Exited operation (vm=%p name=%s)", + obj, obj->def->name); + + if (obj->job->active == VIR_JOB_ASYNC_NESTED) + virDomainObjEndJob(obj); +} + + static virDomainDef * qemuDomainDefFromXML(virQEMUDriver *driver, virQEMUCaps *qemuCaps, diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index ec1c2a4779..ad44e0cc2a 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -624,6 +624,14 @@ int qemuDomainObjExitRemote(virDomainObj *obj, bool checkActive) ATTRIBUTE_NONNULL(1) G_GNUC_WARN_UNUSED_RESULT; + +int qemuDomainObjEnterOperation(virDomainObj *obj, + virDomainAsyncJob asyncJob) + ATTRIBUTE_NONNULL(1) G_GNUC_WARN_UNUSED_RESULT; + +void qemuDomainObjExitOperation(virDomainObj *obj) + ATTRIBUTE_NONNULL(1); + virDomainDef *qemuDomainDefCopy(virQEMUDriver *driver, virQEMUCaps *qemuCaps, virDomainDef *src, -- 2.54.0
