]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: blockjob: Register disk->mirror with a job only when required
authorPeter Krempa <pkrempa@redhat.com>
Wed, 24 Jul 2019 12:50:33 +0000 (14:50 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Thu, 25 Jul 2019 11:21:33 +0000 (13:21 +0200)
The <mirror> 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 <pkrempa@redhat.com>
ACKed-by: Eric Blake <eblake@redhat.com>
src/qemu/qemu_blockjob.c
src/qemu/qemu_blockjob.h
src/qemu/qemu_domain.c
tests/qemustatusxml2xmldata/blockjob-blockdev-in.xml

index ac7b3a0aef520a07c669511449550b7062d41f3c..52065f07caa953873a22925041cce40ebf8d25d9 100644 (file)
@@ -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
index 47bdc54b2b81f43904f2fa459964c81865fe353b..3299207610c419d628e5ad8852dccece1c9cae14 100644 (file)
@@ -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);
index e7f28aa2b87881718e7504a2b2ca8bece5f2fe93..c508f5528748923324826bc9f6ab3e358be770fd 100644 (file)
@@ -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;
index 5b9777ca7181477b3a19ac3d9b7a795bbd84f03d..7b9282d059504186b9ed70f4508bcfb831b7c811 100644 (file)
   <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>