Note when no blockjobs are running in the status XML so that we know
that the backing chain will not change until we reconnect.
---
src/qemu/qemu_domain.c | 38 ++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_domain.h | 3 +++
tests/qemuxml2xmltest.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 85 insertions(+)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index a8c718f62..6958ed736 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1759,6 +1759,8 @@ qemuDomainObjPrivateDataClear(qemuDomainObjPrivatePtr priv)
/* clear previously used namespaces */
virBitmapFree(priv->namespaces);
priv->namespaces = NULL;
+
+ priv->reconnectBlockjobs = VIR_TRISTATE_BOOL_ABSENT;
}
@@ -1854,6 +1856,20 @@ qemuDomainObjPrivateXMLFormatAutomaticPlacement(virBufferPtr buf,
}
+static int
+qemuDomainObjPrivateXMLFormatBlockjobs(virBufferPtr buf,
+ virDomainObjPtr vm)
+{
+ virBuffer attrBuf = VIR_BUFFER_INITIALIZER;
+ bool bj = qemuDomainHasBlockjob(vm, false);
+
+ virBufferAsprintf(&attrBuf, " active='%s'",
+ virTristateBoolTypeToString(virTristateBoolFromBool(bj)));
+
+ return virXMLFormatElement(buf, "blockjobs", &attrBuf, NULL);
+}
+
+
static int
qemuDomainObjPrivateXMLFormat(virBufferPtr buf,
virDomainObjPtr vm)
@@ -1976,6 +1992,9 @@ qemuDomainObjPrivateXMLFormat(virBufferPtr buf,
if (priv->chardevStdioLogd)
virBufferAddLit(buf, "<chardevStdioLogd/>\n");
+ if (qemuDomainObjPrivateXMLFormatBlockjobs(buf, vm) < 0)
+ return -1;
+
return 0;
}
@@ -2067,6 +2086,22 @@ qemuDomainObjPrivateXMLParseAutomaticPlacement(xmlXPathContextPtr
ctxt,
}
+static int
+qemuDomainObjPrivateXMLParseBlockjobs(qemuDomainObjPrivatePtr priv,
+ xmlXPathContextPtr ctxt)
+{
+ char *active;
+ int tmp;
+
+ if ((active = virXPathString("string(./blockjobs/@active)", ctxt))
&&
+ (tmp = virTristateBoolTypeFromString(active)) > 0)
+ priv->reconnectBlockjobs = tmp;
+
+ VIR_FREE(active);
+ return 0;
+}
+
+
static int
qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt,
virDomainObjPtr vm,
@@ -2282,6 +2317,9 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt,
priv->chardevStdioLogd = virXPathBoolean("boolean(./chardevStdioLogd)",
ctxt) == 1;
+ if (qemuDomainObjPrivateXMLParseBlockjobs(priv, ctxt) < 0)
+ goto error;
+
return 0;
error:
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index f92841ceb..c34cd37fc 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -320,6 +320,9 @@ struct _qemuDomainObjPrivate {
/* If true virtlogd is used as stdio handler for character devices. */
bool chardevStdioLogd;
+
+ /* Tracks blockjob state for vm. Valid only while reconnecting to qemu. */
+ virTristateBool reconnectBlockjobs;
};
# define QEMU_DOMAIN_PRIVATE(vm) \
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 7d7a5f1e4..14f5b58fe 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -34,6 +34,7 @@ struct testInfo {
char *outInactiveName;
virBitmapPtr activeVcpus;
+ bool blockjobs;
virQEMUCapsPtr qemuCaps;
};
@@ -43,11 +44,22 @@ qemuXML2XMLActivePreFormatCallback(virDomainDefPtr def,
const void *opaque)
{
struct testInfo *info = (struct testInfo *) opaque;
+ size_t i;
/* store vCPU bitmap so that the status XML can be created faithfully */
if (!info->activeVcpus)
info->activeVcpus = virDomainDefGetOnlineVcpumap(def);
+ info->blockjobs = false;
+
+ /* remember whether we have mirror jobs */
+ for (i = 0; i < def->ndisks; i++) {
+ if (def->disks[i]->mirror) {
+ info->blockjobs = true;
+ break;
+ }
+ }
+
return 0;
}
@@ -124,6 +136,15 @@ testGetStatuXMLPrefixVcpus(virBufferPtr buf,
}
+static void
+testGetStatusXMLAddBlockjobs(virBufferPtr buf,
+ const struct testInfo *data)
+{
+ virBufferAsprintf(buf, "<blockjobs active='%s'/>\n",
+
virTristateBoolTypeToString(virTristateBoolFromBool(data->blockjobs)));
+}
+
+
static char *
testGetStatusXMLPrefix(const struct testInfo *data)
{
@@ -136,12 +157,31 @@ testGetStatusXMLPrefix(const struct testInfo *data)
virBufferAddStr(&buf, testStatusXMLPrefixBodyStatic);
+ testGetStatusXMLAddBlockjobs(&buf, data);
+
virBufferAdjustIndent(&buf, -2);
return virBufferContentAndReset(&buf);
}
+static int
+testProcessStatusXML(virDomainObjPtr vm)
+{
+ size_t i;
+
+ /* fix the private 'blockjob' flag for disks */
+ for (i = 0; i < vm->def->ndisks; i++) {
+ virDomainDiskDefPtr disk = vm->def->disks[i];
+ qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
+
+ diskPriv->blockjob = !!disk->mirror;
+ }
+
+ return 0;
+}
+
+
static int
testCompareStatusXMLToXMLFiles(const void *opaque)
{
@@ -200,6 +240,10 @@ testCompareStatusXMLToXMLFiles(const void *opaque)
goto cleanup;
}
+ /* process the definition if necessary */
+ if (testProcessStatusXML(obj) < 0)
+ goto cleanup;
+
/* format it back */
if (!(actual = virDomainObjFormat(driver.xmlopt, obj, NULL,
VIR_DOMAIN_DEF_FORMAT_SECURE))) {
--
2.14.1