In order for a future patch to actually implement the new
VIR_DOMAIN_XML_BLOCK_INFO flag, we'll need to make a qemu
monitor command call for each disk backed by block storage.
Not only does a monitor command require a job, but even
iterating over disks to determine if the monitor command is
needed requires a job (so no other command is hot-plugging
disks in the meantime). Previously, we needed a job if
we were talking to old qemu that lacked balloon events,
and just silently ignored that efforts if a long-running
job was already in effect; but since the new API is an
explicit flag, we aren't grabbing the job unless a user
requests it, and the user request gives us reason to wait
for the earlier job to finish.
Ideally, this rewrite should have no semantic changes for
callers that do not pass the new flag.
* src/qemu/qemu_driver.c (qemuDomainGetXMLDesc): Rearrange job
control, in order to make future patch for grabbing block info
easier to manage.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
src/qemu/qemu_driver.c | 73 ++++++++++++++++++++++++++++++--------------------
1 file changed, 44 insertions(+), 29 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index a84fd47..9b77b00 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6188,6 +6188,8 @@ static char *qemuDomainGetXMLDesc(virDomainPtr dom,
unsigned long long balloon;
int err = 0;
qemuDomainObjPrivatePtr priv;
+ bool need_job = false;
+ bool need_balloon = false;
/* Flags checked by virDomainDefFormat */
@@ -6199,38 +6201,47 @@ static char *qemuDomainGetXMLDesc(virDomainPtr dom,
if (virDomainGetXMLDescEnsureACL(dom->conn, vm->def, flags) < 0)
goto cleanup;
+ /* Need a job if we will talk to the monitor */
+ if (virDomainObjIsActive(vm)) {
+ if (flags & VIR_DOMAIN_XML_BLOCK_INFO)
+ need_job = true;
+ if (vm->def->memballoon &&
+ vm->def->memballoon->model != VIR_DOMAIN_MEMBALLOON_MODEL_NONE
&&
+ !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BALLOON_EVENT)) {
+ /* If we already need a job, then grab balloon. But if
+ * balloon is the only reason to query, don't delay if
+ * someone's using the monitor; existing most recent data
+ * is good enough. */
+ need_job |= qemuDomainJobAllowed(priv, QEMU_JOB_QUERY);
+ need_balloon = need_job;
+ }
+ }
+ if (need_job) {
+ if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
+ goto cleanup;
+
+ if (!virDomainObjIsActive(vm)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("domain is not running"));
+ goto endjob;
+ }
+ }
+
/* Refresh current memory based on balloon info if supported */
- if ((vm->def->memballoon != NULL) &&
- (vm->def->memballoon->model != VIR_DOMAIN_MEMBALLOON_MODEL_NONE)
&&
- !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BALLOON_EVENT) &&
- (virDomainObjIsActive(vm))) {
- /* Don't delay if someone's using the monitor, just use
- * existing most recent data instead */
- if (qemuDomainJobAllowed(priv, QEMU_JOB_QUERY)) {
- if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
- goto cleanup;
+ if (need_balloon) {
+ qemuDomainObjEnterMonitor(driver, vm);
+ err = qemuMonitorGetBalloonInfo(priv->mon, &balloon);
+ qemuDomainObjExitMonitor(driver, vm);
- if (!virDomainObjIsActive(vm)) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- "%s", _("domain is not running"));
- goto endjob;
- }
+ if (err < 0)
+ goto endjob;
+ if (err > 0)
+ vm->def->mem.cur_balloon = balloon;
+ /* err == 0 indicates no balloon support, so ignore it */
+ }
- qemuDomainObjEnterMonitor(driver, vm);
- err = qemuMonitorGetBalloonInfo(priv->mon, &balloon);
- qemuDomainObjExitMonitor(driver, vm);
-
- endjob:
- if (!qemuDomainObjEndJob(driver, vm)) {
- vm = NULL;
- goto cleanup;
- }
- if (err < 0)
- goto cleanup;
- if (err > 0)
- vm->def->mem.cur_balloon = balloon;
- /* err == 0 indicates no balloon support, so ignore it */
- }
+ if (flags & VIR_DOMAIN_XML_BLOCK_INFO) {
+ /* FIXME run monitor commands to refresh block info */
}
if ((flags & VIR_DOMAIN_XML_MIGRATABLE))
@@ -6238,6 +6249,10 @@ static char *qemuDomainGetXMLDesc(virDomainPtr dom,
ret = qemuDomainFormatXML(driver, vm, flags);
+ endjob:
+ if (need_job && !qemuDomainObjEndJob(driver, vm))
+ vm = NULL;
+
cleanup:
if (vm)
virObjectUnlock(vm);
--
1.9.3