diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 2bcc9839d1a137a15b068152e0b680fe3bbb9186..f621cf7afc4f5541c28b9b29e9717bbc29dc9616 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, "\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 f92841ceb9394858c355bcb9885e4c8ab96e0197..c34cd37fc4c3354678398625cf85754e1ec4009e 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 7d7a5f1e4b0a9982da66d8a2228f8e4e8eb5ef46..14f5b58fe913361db856b992f6a0f89525aae34b 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, "\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))) {