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

Reply via email to