From dae7d01322c3621bd2464dc992dc007ca20605f5 Mon Sep 17 00:00:00 2001 From: Peter Krempa Date: Wed, 24 Jul 2019 14:50:33 +0200 Subject: [PATCH] qemu: blockjob: Register disk->mirror with a job only when required The subelement is used in two ways: in a commit job to point to existing storage, and in a block-copy job to point to additional storage. We need a way to track only the distinct storage. This patch introduces qemuBlockJobDiskRegisterMirror which registers the mirror chain separately only for jobs which require it. This also comes with remembering that in the status XML. Signed-off-by: Peter Krempa ACKed-by: Eric Blake --- src/qemu/qemu_blockjob.c | 22 ++++++++++++++++++- src/qemu/qemu_blockjob.h | 4 ++++ src/qemu/qemu_domain.c | 14 +++++++++++- .../blockjob-blockdev-in.xml | 2 +- 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c index ac7b3a0aef..52065f07ca 100644 --- a/src/qemu/qemu_blockjob.c +++ b/src/qemu/qemu_blockjob.c @@ -126,6 +126,9 @@ qemuBlockJobDataNew(qemuBlockJobType type, * * This function registers @job with @disk and @vm and records it into the status * xml (if @savestatus is true). + * + * Note that if @job also references a separate chain e.g. for disk mirroring, + * then qemuBlockJobDiskRegisterMirror should be used separately. */ int qemuBlockJobRegister(qemuBlockJobDataPtr job, @@ -143,7 +146,6 @@ qemuBlockJobRegister(qemuBlockJobDataPtr job, if (disk) { job->disk = disk; job->chain = virObjectRef(disk->src); - job->mirrorChain = virObjectRef(disk->mirror); QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob = virObjectRef(job); } @@ -205,6 +207,24 @@ qemuBlockJobDiskNew(virDomainObjPtr vm, } +/** + * qemuBlockJobDiskRegisterMirror: + * @job: block job to register 'mirror' chain on + * + * In cases when the disk->mirror attribute references a separate storage chain + * such as for block-copy, this function registers it with the job. Note + * that this function does not save the status XML and thus must be used before + * qemuBlockJobRegister or qemuBlockJobStarted to properly track the chain + * in the status XML. + */ +void +qemuBlockJobDiskRegisterMirror(qemuBlockJobDataPtr job) +{ + if (job->disk) + job->mirrorChain = virObjectRef(job->disk->mirror); +} + + /** * qemuBlockJobDiskGetJob: * @disk: disk definition diff --git a/src/qemu/qemu_blockjob.h b/src/qemu/qemu_blockjob.h index 47bdc54b2b..3299207610 100644 --- a/src/qemu/qemu_blockjob.h +++ b/src/qemu/qemu_blockjob.h @@ -110,6 +110,10 @@ qemuBlockJobDiskNew(virDomainObjPtr vm, const char *jobname) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4); +void +qemuBlockJobDiskRegisterMirror(qemuBlockJobDataPtr job) + ATTRIBUTE_NONNULL(1); + qemuBlockJobDataPtr qemuBlockJobDiskGetJob(virDomainDiskDefPtr disk) ATTRIBUTE_NONNULL(1); diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index e7f28aa2b8..c508f55287 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -2367,7 +2367,10 @@ qemuDomainObjPrivateXMLFormatBlockjobIterator(void *payload, virBufferEscapeString(&childBuf, "%s", job->errmsg); if (job->disk) { - virBufferEscapeString(&childBuf, "\n", job->disk->dst); + virBufferEscapeString(&childBuf, "disk->dst); + if (job->mirrorChain) + virBufferAddLit(&childBuf, " mirror='yes'"); + virBufferAddLit(&childBuf, "/>\n"); } else { if (job->chain && qemuDomainObjPrivateXMLFormatBlockjobFormatChain(&chainsBuf, @@ -2806,6 +2809,7 @@ qemuDomainObjPrivateXMLParseBlockjobData(virDomainObjPtr vm, int state = QEMU_BLOCKJOB_STATE_FAILED; VIR_AUTOFREE(char *) diskdst = NULL; VIR_AUTOFREE(char *) newstatestr = NULL; + VIR_AUTOFREE(char *) mirror = NULL; int newstate = -1; bool invalidData = false; xmlNodePtr tmp; @@ -2840,6 +2844,10 @@ qemuDomainObjPrivateXMLParseBlockjobData(virDomainObjPtr vm, !(disk = virDomainDiskByName(vm->def, diskdst, false))) invalidData = true; + if ((mirror = virXPathString("string(./disk/@mirror)", ctxt)) && + STRNEQ(mirror, "yes")) + invalidData = true; + if (!disk && !invalidData) { if ((tmp = virXPathNode("./chains/disk", ctxt)) && !(job->chain = qemuDomainObjPrivateXMLParseBlockjobChain(tmp, ctxt, xmlopt))) @@ -2854,6 +2862,10 @@ qemuDomainObjPrivateXMLParseBlockjobData(virDomainObjPtr vm, job->newstate = newstate; job->errmsg = virXPathString("string(./errmsg)", ctxt); job->invalidData = invalidData; + job->disk = disk; + + if (mirror) + qemuBlockJobDiskRegisterMirror(job); if (qemuBlockJobRegister(job, vm, disk, false) < 0) return -1; diff --git a/tests/qemustatusxml2xmldata/blockjob-blockdev-in.xml b/tests/qemustatusxml2xmldata/blockjob-blockdev-in.xml index 5b9777ca71..7b9282d059 100644 --- a/tests/qemustatusxml2xmldata/blockjob-blockdev-in.xml +++ b/tests/qemustatusxml2xmldata/blockjob-blockdev-in.xml @@ -235,7 +235,7 @@ - +