[libvirt] [PATCH 4/9] qemu: blockjob: Register disk->mirror with a job only when required

Peter Krempa pkrempa at redhat.com
Wed Jul 24 21:07:31 UTC 2019


Commit job for example references existing storage in the <mirror>
subelement thus tracking it separately could lead into problems.

This patch introduces qemuBlockJobDiskRegisterMirror which registers the
mirror chain separately only for job which require it. This also comes
with remembering that in the status XML.

Signed-off-by: Peter Krempa <pkrempa at redhat.com>
---
 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..a3109d3934 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
+ * qemuBlockJobDiskRegisterMirror should be used.
  */
 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, "<errmsg>%s</errmsg>", job->errmsg);

     if (job->disk) {
-        virBufferEscapeString(&childBuf, "<disk dst='%s'/>\n", job->disk->dst);
+        virBufferEscapeString(&childBuf, "<disk dst='%s'", job->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 @@
   <nodename index='0'/>
   <blockjobs active='yes'>
     <blockjob name='drive-virtio-disk0' type='copy' state='ready'>
-      <disk dst='vda'/>
+      <disk dst='vda' mirror='yes'/>
     </blockjob>
     <blockjob name='test-orphan-job0' type='copy' state='ready'>
       <chains>
-- 
2.21.0




More information about the libvir-list mailing list