[libvirt] [PATCH v2 3/3] qemuMigrationPrecreateDisk: Preserve sparse files

Michal Privoznik mprivozn at redhat.com
Fri Apr 10 15:25:41 UTC 2015


https://bugzilla.redhat.com/show_bug.cgi?id=817700

When pre-creating a disk on the destination, a volume XML is
constructed. The XML is then passed to virStorageVolCreateXML() which
does the work. But, since there's no <allocation/> in the XML, the
disk are fully allocated. This possibly breaks sparse allocation user
has on the migration source.

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 src/qemu/qemu_migration.c | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index d4757e4..7a40548 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -144,6 +144,7 @@ typedef qemuMigrationCookieNBDDisk *qemuMigrationCookieNBDDiskPtr;
 struct _qemuMigrationCookieNBDDisk {
     char *target;                   /* Disk target */
     unsigned long long capacity;    /* And its capacity */
+    unsigned long long allocation;  /* And its allocation */
 };
 
 typedef struct _qemuMigrationCookieNBD qemuMigrationCookieNBD;
@@ -593,6 +594,7 @@ qemuMigrationCookieAddNBD(qemuMigrationCookiePtr mig,
                        disk->dst) < 0)
             goto cleanup;
         mig->nbd->disks[mig->nbd->ndisks].capacity = entry->capacity;
+        mig->nbd->disks[mig->nbd->ndisks].allocation = entry->wr_highest_offset;
         mig->nbd->ndisks++;
     }
 
@@ -833,8 +835,12 @@ qemuMigrationCookieXMLFormat(virQEMUDriverPtr driver,
             for (i = 0; i < mig->nbd->ndisks; i++) {
                 virBufferEscapeString(buf, "<disk target='%s'",
                                       mig->nbd->disks[i].target);
-                virBufferAsprintf(buf, " capacity='%llu'/>\n",
+                virBufferAsprintf(buf, " capacity='%llu'",
                                   mig->nbd->disks[i].capacity);
+                if (mig->nbd->disks[i].capacity != mig->nbd->disks[i].allocation)
+                    virBufferAsprintf(buf, " allocation='%llu'",
+                                      mig->nbd->disks[i].allocation);
+                virBufferAddLit(buf, "/>\n");
             }
             virBufferAdjustIndent(buf, -2);
             virBufferAddLit(buf, "</nbd>\n");
@@ -972,7 +978,7 @@ static qemuMigrationCookieNBDPtr
 qemuMigrationCookieNBDXMLParse(xmlXPathContextPtr ctxt)
 {
     qemuMigrationCookieNBDPtr ret = NULL;
-    char *port = NULL, *capacity = NULL;
+    char *port = NULL, *capacity = NULL, *allocation = NULL;
     size_t i;
     int n;
     xmlNodePtr *disks = NULL;
@@ -1000,6 +1006,7 @@ qemuMigrationCookieNBDXMLParse(xmlXPathContextPtr ctxt)
         for (i = 0; i < n; i++) {
             ctxt->node = disks[i];
             VIR_FREE(capacity);
+            VIR_FREE(allocation);
 
             if (!(ret->disks[i].target = virXPathString("string(./@target)", ctxt))) {
                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -1016,12 +1023,24 @@ qemuMigrationCookieNBDXMLParse(xmlXPathContextPtr ctxt)
                                NULLSTR(capacity));
                 goto error;
             }
+
+            allocation = virXPathString("string(./@allocation)", ctxt);
+            if (allocation) {
+                if (virStrToLong_ull(allocation, NULL, 10,
+                                     &ret->disks[i].allocation) < 0) {
+                    virReportError(VIR_ERR_INTERNAL_ERROR,
+                                   _("Malformed disk allocation: '%s'"),
+                                   allocation);
+                    goto error;
+                }
+            }
         }
     }
 
  cleanup:
     VIR_FREE(port);
     VIR_FREE(capacity);
+    VIR_FREE(allocation);
     VIR_FREE(disks);
     ctxt->node = save_ctxt;
     return ret;
@@ -1541,6 +1560,8 @@ qemuMigrationPrecreateDisk(virConnectPtr conn,
     virBufferAdjustIndent(&buf, 2);
     virBufferEscapeString(&buf, "<name>%s</name>\n", volName);
     virBufferAsprintf(&buf, "<capacity>%llu</capacity>\n", nbd->capacity);
+    if (nbd->allocation)
+        virBufferAsprintf(&buf, "<allocation>%llu</allocation>\n", nbd->allocation);
     virBufferAddLit(&buf, "<target>\n");
     virBufferAdjustIndent(&buf, 2);
     virBufferAsprintf(&buf, "<format type='%s'/>\n", format);
@@ -1585,8 +1606,9 @@ qemuMigrationPrecreateStorage(virConnectPtr conn,
         int indx;
         const char *diskSrcPath;
 
-        VIR_DEBUG("Looking up disk target '%s' (capacity=%llu)",
-                  nbd->disks[i].target, nbd->disks[i].capacity);
+        VIR_DEBUG("Looking up disk target '%s' (capacity=%llu allocation=%llu)",
+                  nbd->disks[i].target, nbd->disks[i].capacity,
+                  nbd->disks[i].allocation);
 
         if ((indx = virDomainDiskIndexByName(vm->def,
                                              nbd->disks[i].target, false)) < 0) {
-- 
2.0.5




More information about the libvir-list mailing list