]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: blockjob: Unplug inherited storage chains when concluding blockjob
authorPeter Krempa <pkrempa@redhat.com>
Fri, 29 Mar 2019 07:47:38 +0000 (08:47 +0100)
committerPeter Krempa <pkrempa@redhat.com>
Thu, 18 Jul 2019 15:59:34 +0000 (17:59 +0200)
In cases when the disk frontend was unplugged while a blockjob was
running the blockjob inherits the backing chain. When the blockjob is
then terminated we need to unplug the chain as it will not be used any
more.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
src/qemu/qemu_blockjob.c

index d55eb4860573b144cd370b6d0f7a8ab2b7d3d0ac..292610d089c6bd12598da2cfbb2db2e10d24cadf 100644 (file)
@@ -536,6 +536,28 @@ qemuBlockJobEventProcessLegacy(virQEMUDriverPtr driver,
 }
 
 
+static void
+qemuBlockJobEventProcessConcludedRemoveChain(virQEMUDriverPtr driver,
+                                             virDomainObjPtr vm,
+                                             qemuDomainAsyncJob asyncJob,
+                                             virStorageSourcePtr chain)
+{
+    VIR_AUTOPTR(qemuBlockStorageSourceChainData) data = NULL;
+
+    if (!(data = qemuBlockStorageSourceChainDetachPrepareBlockdev(chain)))
+        return;
+
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+        return;
+
+    qemuBlockStorageSourceChainDetach(qemuDomainGetMonitor(vm), data);
+    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        return;
+
+    qemuDomainStorageSourceChainAccessRevoke(driver, vm, chain);
+}
+
+
 static void
 qemuBlockJobEventProcessConcludedTransition(qemuBlockJobDataPtr job,
                                             virQEMUDriverPtr driver,
@@ -652,6 +674,16 @@ qemuBlockJobEventProcessConcluded(qemuBlockJobDataPtr job,
 
     qemuBlockJobEventProcessConcludedTransition(job, driver, vm, asyncJob);
 
+    /* unplug the backing chains in case the job inherited them */
+    if (!job->disk) {
+        if (job->chain)
+            qemuBlockJobEventProcessConcludedRemoveChain(driver, vm, asyncJob,
+                                                         job->chain);
+        if (job->mirrorChain)
+            qemuBlockJobEventProcessConcludedRemoveChain(driver, vm, asyncJob,
+                                                         job->mirrorChain);
+    }
+
  cleanup:
     if (dismissed) {
         qemuBlockJobUnregister(job, vm);