[libvirt] [PATCH v2 04/10] conf: store mirroring information in virStorageSource

Eric Blake eblake at redhat.com
Thu Jun 5 22:52:31 UTC 2014


The current implementation of 'virsh blockcopy' (virDomainBlockRebase)
is limited to copying to a local file name.  But future patches want
to extend it to also copy to network disks.  This patch converts over
to a virStorageSourcePtr, although it should have no semantic change
visible to the user, in anticipation of those future patches being
able to use more fields for non-file destinations.

* src/conf/domain_conf.h (_virDomainDiskDef): Change type of
mirror information.
* src/conf/domain_conf.c (virDomainDiskDefParseXML): Localize
mirror parsing into new object.
(virDomainDiskDefFormat): Adjust clients.
* src/qemu/qemu_domain.c (qemuDomainDeviceDefPostParse):
Likewise.
* src/qemu/qemu_driver.c (qemuDomainBlockPivot)
(qemuDomainBlockJobImpl, qemuDomainBlockCopy): Likewise.

Signed-off-by: Eric Blake <eblake at redhat.com>
---
 src/conf/domain_conf.c  | 50 ++++++++++++++++++++---------------------
 src/conf/domain_conf.h  |  3 +--
 src/qemu/qemu_domain.c  |  8 +++----
 src/qemu/qemu_driver.c  | 60 +++++++++++++++++++++++++++++++------------------
 src/qemu/qemu_process.c | 15 ++++++++-----
 5 files changed, 77 insertions(+), 59 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 361d087..b8e7c50 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -5223,9 +5223,6 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
     char *ioeventfd = NULL;
     char *event_idx = NULL;
     char *copy_on_read = NULL;
-    char *mirror = NULL;
-    char *mirrorFormat = NULL;
-    bool mirroring = false;
     char *devaddr = NULL;
     virStorageEncryptionPtr encryption = NULL;
     char *serial = NULL;
@@ -5374,19 +5371,37 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
                 event_idx = virXMLPropString(cur, "event_idx");
                 copy_on_read = virXMLPropString(cur, "copy_on_read");
                 discard = virXMLPropString(cur, "discard");
-            } else if (!mirror && xmlStrEqual(cur->name, BAD_CAST "mirror") &&
+            } else if (!def->mirror &&
+                       xmlStrEqual(cur->name, BAD_CAST "mirror") &&
                        !(flags & VIR_DOMAIN_XML_INACTIVE)) {
                 char *ready;
-                mirror = virXMLPropString(cur, "file");
-                if (!mirror) {
+                char *mirrorFormat;
+
+                if (VIR_ALLOC(def->mirror) < 0)
+                    goto error;
+                def->mirror->type = VIR_STORAGE_TYPE_FILE;
+                def->mirror->path = virXMLPropString(cur, "file");
+                if (!def->mirror->path) {
                     virReportError(VIR_ERR_XML_ERROR, "%s",
                                    _("mirror requires file name"));
                     goto error;
                 }
                 mirrorFormat = virXMLPropString(cur, "format");
+                if (mirrorFormat) {
+                    def->mirror->format =
+                        virStorageFileFormatTypeFromString(mirrorFormat);
+                    if (def->mirror->format <= 0) {
+                        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                                       _("unknown mirror format value '%s'"),
+                                       mirrorFormat);
+                        VIR_FREE(mirrorFormat);
+                        goto error;
+                    }
+                    VIR_FREE(mirrorFormat);
+                }
                 ready = virXMLPropString(cur, "ready");
                 if (ready) {
-                    mirroring = true;
+                    def->mirroring = true;
                     VIR_FREE(ready);
                 }
             } else if (xmlStrEqual(cur->name, BAD_CAST "auth")) {
@@ -5906,9 +5921,6 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
     authUsername = NULL;
     def->src->driverName = driverName;
     driverName = NULL;
-    def->mirror = mirror;
-    mirror = NULL;
-    def->mirroring = mirroring;
     def->src->encryption = encryption;
     encryption = NULL;
     def->serial = serial;
@@ -5930,16 +5942,6 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
         }
     }

-    if (mirrorFormat) {
-        def->mirrorFormat = virStorageFileFormatTypeFromString(mirrorFormat);
-        if (def->mirrorFormat <= 0) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("unknown mirror format value '%s'"),
-                           driverType);
-            goto error;
-        }
-    }
-
     if (def->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE
         && virDomainDiskDefAssignAddress(xmlopt, def) < 0)
         goto error;
@@ -5964,8 +5966,6 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
     VIR_FREE(authUsage);
     VIR_FREE(driverType);
     VIR_FREE(driverName);
-    VIR_FREE(mirror);
-    VIR_FREE(mirrorFormat);
     VIR_FREE(cachetag);
     VIR_FREE(error_policy);
     VIR_FREE(rerror_policy);
@@ -15160,10 +15160,10 @@ virDomainDiskDefFormat(virBufferPtr buf,
      * for live domains, therefore we ignore it on input except for
      * the internal parse on libvirtd restart.  */
     if (def->mirror && !(flags & VIR_DOMAIN_XML_INACTIVE)) {
-        virBufferEscapeString(buf, "<mirror file='%s'", def->mirror);
-        if (def->mirrorFormat)
+        virBufferEscapeString(buf, "<mirror file='%s'", def->mirror->path);
+        if (def->mirror->format)
             virBufferAsprintf(buf, " format='%s'",
-                              virStorageFileFormatTypeToString(def->mirrorFormat));
+                              virStorageFileFormatTypeToString(def->mirror->format));
         if (def->mirroring)
             virBufferAddLit(buf, " ready='yes'");
         virBufferAddLit(buf, "/>\n");
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 3585537..11d5c68 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -606,8 +606,7 @@ struct _virDomainDiskDef {
     int tray_status; /* enum virDomainDiskTray */
     int removable; /* enum virDomainFeatureState */

-    char *mirror;
-    int mirrorFormat; /* virStorageFileFormat */
+    virStorageSourcePtr mirror;
     bool mirroring;

     struct {
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index ccdface..962698b 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -887,8 +887,8 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,

                  /* default disk format for mirrored drive */
                 if (disk->mirror &&
-                    disk->mirrorFormat == VIR_STORAGE_FILE_NONE)
-                    disk->mirrorFormat = VIR_STORAGE_FILE_AUTO;
+                    disk->mirror->format == VIR_STORAGE_FILE_NONE)
+                    disk->mirror->format = VIR_STORAGE_FILE_AUTO;
             } else {
                 /* default driver if probing is forbidden */
                 if (!virDomainDiskGetDriver(disk) &&
@@ -903,8 +903,8 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,

                  /* default disk format for mirrored drive */
                 if (disk->mirror &&
-                    disk->mirrorFormat == VIR_STORAGE_FILE_NONE)
-                    disk->mirrorFormat = VIR_STORAGE_FILE_RAW;
+                    disk->mirror->format == VIR_STORAGE_FILE_NONE)
+                    disk->mirror->format = VIR_STORAGE_FILE_RAW;
             }
         }
     }
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 32c5a09..b0f80a5 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -14870,13 +14870,22 @@ qemuDomainBlockPivot(virConnectPtr conn,
     int ret = -1, rc;
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virDomainBlockJobInfo info;
-    const char *format = virStorageFileFormatTypeToString(disk->mirrorFormat);
+    const char *format = NULL;
     bool resume = false;
     char *oldsrc = NULL;
     int oldformat;
     virStorageSourcePtr oldchain = NULL;
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);

+    if (!disk->mirror) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       _("pivot of disk '%s' requires an active copy job"),
+                       disk->dst);
+        goto cleanup;
+    }
+
+    format = virStorageFileFormatTypeToString(disk->mirror->format);
+
     /* Probe the status, if needed.  */
     if (!disk->mirroring) {
         qemuDomainObjEnterMonitor(driver, vm);
@@ -14934,8 +14943,8 @@ qemuDomainBlockPivot(virConnectPtr conn,
     oldsrc = disk->src->path;
     oldformat = disk->src->format;
     oldchain = disk->src->backingStore;
-    disk->src->path = disk->mirror;
-    disk->src->format = disk->mirrorFormat;
+    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;
@@ -14943,7 +14952,7 @@ qemuDomainBlockPivot(virConnectPtr conn,
         disk->src->backingStore = oldchain;
         goto cleanup;
     }
-    if (disk->mirrorFormat && disk->mirrorFormat != VIR_STORAGE_FILE_RAW &&
+    if (disk->mirror->format && disk->mirror->format != VIR_STORAGE_FILE_RAW &&
         (virDomainLockDiskAttach(driver->lockManager, cfg->uri,
                                  vm, disk) < 0 ||
          qemuSetupDiskCgroup(vm, disk) < 0 ||
@@ -14957,7 +14966,7 @@ qemuDomainBlockPivot(virConnectPtr conn,

     /* Attempt the pivot.  */
     qemuDomainObjEnterMonitor(driver, vm);
-    ret = qemuMonitorDrivePivot(priv->mon, device, disk->mirror, format);
+    ret = qemuMonitorDrivePivot(priv->mon, device, disk->mirror->path, format);
     qemuDomainObjExitMonitor(driver, vm);

     if (ret == 0) {
@@ -14970,7 +14979,7 @@ qemuDomainBlockPivot(virConnectPtr conn,
          * for now, we leak the access to the original.  */
         VIR_FREE(oldsrc);
         virStorageSourceFree(oldchain);
-        disk->mirror = NULL;
+        disk->mirror->path = 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
@@ -14984,9 +14993,9 @@ qemuDomainBlockPivot(virConnectPtr conn,
         disk->src->format = oldformat;
         virStorageSourceFree(disk->src->backingStore);
         disk->src->backingStore = oldchain;
-        VIR_FREE(disk->mirror);
     }
-    disk->mirrorFormat = VIR_STORAGE_FILE_NONE;
+    virStorageSourceFree(disk->mirror);
+    disk->mirror = NULL;
     disk->mirroring = false;

  cleanup:
@@ -15112,8 +15121,8 @@ qemuDomainBlockJobImpl(virDomainObjPtr vm,
     if (mode == BLOCK_JOB_ABORT && disk->mirror) {
         /* XXX We should also revoke security labels and disk lease on
          * the mirror, and audit that fact, before dropping things.  */
-        VIR_FREE(disk->mirror);
-        disk->mirrorFormat = VIR_STORAGE_FILE_NONE;
+        virStorageSourceFree(disk->mirror);
+        disk->mirror = NULL;
         disk->mirroring = false;
     }

@@ -15248,7 +15257,7 @@ qemuDomainBlockCopy(virDomainObjPtr vm,
     int idx;
     struct stat st;
     bool need_unlink = false;
-    char *mirror = NULL;
+    virStorageSourcePtr mirror = NULL;
     virQEMUDriverConfigPtr cfg = NULL;

     /* Preliminaries: find the disk we are editing, sanity checks */
@@ -15329,6 +15338,11 @@ qemuDomainBlockCopy(virDomainObjPtr vm,
         goto endjob;
     }

+    if (VIR_ALLOC(mirror) < 0)
+        goto endjob;
+    /* XXX Allow non-file mirror destinations */
+    mirror->type = VIR_STORAGE_TYPE_FILE;
+
     if (!(flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT)) {
         int fd = qemuOpenFile(driver, vm, dest, O_WRONLY | O_TRUNC | O_CREAT,
                               &need_unlink, NULL);
@@ -15336,10 +15350,10 @@ qemuDomainBlockCopy(virDomainObjPtr vm,
             goto endjob;
         VIR_FORCE_CLOSE(fd);
         if (!format)
-            disk->mirrorFormat = disk->src->format;
+            mirror->format = disk->src->format;
     } else if (format) {
-        disk->mirrorFormat = virStorageFileFormatTypeFromString(format);
-        if (disk->mirrorFormat <= 0) {
+        mirror->format = virStorageFileFormatTypeFromString(format);
+        if (mirror->format <= 0) {
             virReportError(VIR_ERR_INVALID_ARG, _("unrecognized format '%s'"),
                            format);
             goto endjob;
@@ -15349,12 +15363,12 @@ qemuDomainBlockCopy(virDomainObjPtr vm,
          * also passed the RAW flag (and format is non-NULL), or it is
          * safe for us to probe the format from the file that we will
          * be using.  */
-        disk->mirrorFormat = virStorageFileProbeFormat(dest, cfg->user,
-                                                       cfg->group);
+        mirror->format = virStorageFileProbeFormat(dest, cfg->user,
+                                                   cfg->group);
     }
-    if (!format && disk->mirrorFormat > 0)
-        format = virStorageFileFormatTypeToString(disk->mirrorFormat);
-    if (VIR_STRDUP(mirror, dest) < 0)
+    if (!format && mirror->format > 0)
+        format = virStorageFileFormatTypeToString(mirror->format);
+    if (VIR_STRDUP(mirror->path, dest) < 0)
         goto endjob;

     if (qemuDomainPrepareDiskChainElementPath(driver, vm, disk, dest,
@@ -15384,9 +15398,11 @@ qemuDomainBlockCopy(virDomainObjPtr vm,
  endjob:
     if (need_unlink && unlink(dest))
         VIR_WARN("unable to unlink just-created %s", dest);
-    if (ret < 0 && disk)
-        disk->mirrorFormat = VIR_STORAGE_FILE_NONE;
-    VIR_FREE(mirror);
+    if (ret < 0 && disk) {
+        virStorageSourceFree(disk->mirror);
+        disk->mirror = NULL;
+    }
+    virStorageSourceFree(mirror);
     if (!qemuDomainObjEndJob(driver, vm))
         vm = NULL;

diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index d906494..e4845ba 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -1033,12 +1033,15 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
              type == VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT) &&
             status == VIR_DOMAIN_BLOCK_JOB_COMPLETED)
             qemuDomainDetermineDiskChain(driver, vm, disk, true);
-        if (disk->mirror && type == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY &&
-            status == VIR_DOMAIN_BLOCK_JOB_READY)
-            disk->mirroring = true;
-        if (disk->mirror && type == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY &&
-            status == VIR_DOMAIN_BLOCK_JOB_FAILED)
-            VIR_FREE(disk->mirror);
+        if (disk->mirror && type == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY) {
+            if (status == VIR_DOMAIN_BLOCK_JOB_READY) {
+                disk->mirroring = true;
+            } else if (status == VIR_DOMAIN_BLOCK_JOB_FAILED) {
+                virStorageSourceFree(disk->mirror);
+                disk->mirror = NULL;
+                disk->mirroring = false;
+            }
+        }
     }

     virObjectUnlock(vm);
-- 
1.9.3




More information about the libvir-list mailing list