]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
qemu: block: Properly track disk source while pivoting to new image
authorPeter Krempa <pkrempa@redhat.com>
Fri, 27 Jun 2014 14:12:20 +0000 (16:12 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Wed, 9 Jul 2014 09:45:56 +0000 (11:45 +0200)
When pivoting to a new disk source after a block commit (and possibly
after a soon-to-be-added active block commit) we changed just a few
fields to the new target. In case we'd copy a network disk to a local
file we'd not change the type properly.

To avoid such problems, switch to tracking of the source via changing of
the complete source struct to the one tracking the mirroring info.

src/qemu/qemu_driver.c

index 4d6f3952af223b97f73e469c49f14193079b6b14..2abbbd337bd6661edef1dd2ecf44e386c789c393 100644 (file)
@@ -14863,9 +14863,7 @@ qemuDomainBlockPivot(virConnectPtr conn,
     virDomainBlockJobInfo info;
     const char *format = NULL;
     bool resume = false;
-    char *oldsrc = NULL;
-    int oldformat;
-    virStorageSourcePtr oldchain = NULL;
+    virStorageSourcePtr oldsrc = NULL;
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
 
     if (!disk->mirror) {
@@ -14931,29 +14929,17 @@ qemuDomainBlockPivot(virConnectPtr conn,
      * label the entire chain.  This action is safe even if the
      * backing chain has already been labeled; but only necessary when
      * we know for sure that there is a backing chain.  */
-    oldsrc = disk->src->path;
-    oldformat = disk->src->format;
-    oldchain = disk->src->backingStore;
-    disk->src->path = disk->mirror->path;
-    disk->src->format = disk->mirror->format;
-    disk->src->backingStore = NULL;
-    if (qemuDomainDetermineDiskChain(driver, vm, disk, false) < 0) {
-        disk->src->path = oldsrc;
-        disk->src->format = oldformat;
-        disk->src->backingStore = oldchain;
+    oldsrc = disk->src;
+    disk->src = disk->mirror;
+
+    if (qemuDomainDetermineDiskChain(driver, vm, disk, false) < 0)
         goto cleanup;
-    }
+
     if (disk->mirror->format && disk->mirror->format != VIR_STORAGE_FILE_RAW &&
-        (virDomainLockDiskAttach(driver->lockManager, cfg->uri,
-                                 vm, disk) < 0 ||
+        (virDomainLockDiskAttach(driver->lockManager, cfg->uri, vm, disk) < 0 ||
          qemuSetupDiskCgroup(vm, disk) < 0 ||
-         virSecurityManagerSetDiskLabel(driver->securityManager, vm->def,
-                                        disk) < 0)) {
-        disk->src->path = oldsrc;
-        disk->src->format = oldformat;
-        disk->src->backingStore = oldchain;
+         virSecurityManagerSetDiskLabel(driver->securityManager, vm->def, disk) < 0))
         goto cleanup;
-    }
 
     /* Attempt the pivot.  */
     qemuDomainObjEnterMonitor(driver, vm);
@@ -14968,9 +14954,8 @@ qemuDomainBlockPivot(virConnectPtr conn,
          * portion of the chain, and is made more difficult by the
          * fact that we aren't tracking the full chain ourselves; so
          * for now, we leak the access to the original.  */
-        VIR_FREE(oldsrc);
-        virStorageSourceFree(oldchain);
-        disk->mirror->path = NULL;
+        virStorageSourceFree(oldsrc);
+        oldsrc = NULL;
     } else {
         /* On failure, qemu abandons the mirror, and reverts back to
          * the source disk (RHEL 6.3 has a bug where the revert could
@@ -14980,16 +14965,17 @@ qemuDomainBlockPivot(virConnectPtr conn,
          * 'query-block', to see what state we really got left in
          * before killing the mirroring job?  And just as on the
          * success case, there's security labeling to worry about.  */
-        disk->src->path = oldsrc;
-        disk->src->format = oldformat;
-        virStorageSourceFree(disk->src->backingStore);
-        disk->src->backingStore = oldchain;
+        virStorageSourceFree(disk->mirror);
     }
-    virStorageSourceFree(disk->mirror);
+
     disk->mirror = NULL;
     disk->mirroring = false;
 
  cleanup:
+    /* revert to original disk def on failure */
+    if (oldsrc)
+        disk->src = oldsrc;
+
     if (resume && virDomainObjIsActive(vm) &&
         qemuProcessStartCPUs(driver, vm, conn,
                              VIR_DOMAIN_RUNNING_UNPAUSED,
@@ -15410,6 +15396,9 @@ qemuDomainBlockCopy(virDomainObjPtr vm,
     if (VIR_STRDUP(mirror->path, dest) < 0)
         goto endjob;
 
+    if (virStorageSourceInitChainElement(disk->mirror, disk->src, false) < 0)
+        goto endjob;
+
     if (qemuDomainPrepareDiskChainElement(driver, vm, disk, mirror,
                                           VIR_DISK_CHAIN_READ_WRITE) < 0) {
         qemuDomainPrepareDiskChainElement(driver, vm, disk, mirror,