Blob Blame History Raw
From 4a304d9114e1b2e2f69fdb0857501ad8db03d17b Mon Sep 17 00:00:00 2001
Message-Id: <4a304d9114e1b2e2f69fdb0857501ad8db03d17b@dist-git>
From: Jiri Denemark <jdenemar@redhat.com>
Date: Tue, 6 Jun 2017 23:41:57 +0200
Subject: [PATCH] qemu: Refactor qemuDomainSaveHeader

The function is now called virQEMUSaveDataWrite and it is now doing
everything it needs to save both the save image header and domain XML to
a file. Be it a new file or an existing file in which a user wants to
change the domain XML.

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
(cherry picked from commit 33ae270bee012fc89d7b8bb23986ce837ee21b0e)

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

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
 src/qemu/qemu_driver.c | 98 ++++++++++++++++++++++++++++++--------------------
 1 file changed, 60 insertions(+), 38 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index a0b607b419..1629f27470 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2837,7 +2837,7 @@ virQEMUSaveDataFree(virQEMUSaveHeaderPtr header)
 
 
 static virQEMUSaveHeaderPtr
-virQEMUSaveDataNew(char *domXML,
+virQEMUSaveDataNew(char *domXML ATTRIBUTE_UNUSED,
                    bool running,
                    int compressed)
 {
@@ -2850,34 +2850,66 @@ virQEMUSaveDataNew(char *domXML,
     header->version = QEMU_SAVE_VERSION;
     header->was_running = running ? 1 : 0;
     header->compressed = compressed;
-    header->data_len = strlen(domXML) + 1;
 
     return header;
 }
 
 
-/* return -errno on failure, or 0 on success */
+/* virQEMUSaveDataWrite:
+ *
+ * Writes libvirt's header (including domain XML) into a saved image of a
+ * running domain. If @header has data_len filled in (because it was previously
+ * read from the file), the function will make sure the new data will fit
+ * within data_len.
+ *
+ * Returns -1 on failure, or 0 on success.
+ */
 static int
-qemuDomainSaveHeader(int fd, const char *path, const char *xml,
-                     virQEMUSaveHeaderPtr header)
+virQEMUSaveDataWrite(virQEMUSaveHeaderPtr header,
+                     const char *xml,
+                     int fd,
+                     const char *path)
 {
-    int ret = 0;
+    size_t len;
+    int ret = -1;
+    size_t zerosLen = 0;
+    char *zeros = NULL;
+
+    len = strlen(xml) + 1;
+
+    if (header->data_len > 0) {
+        if (len > header->data_len) {
+            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+                           _("new xml too large to fit in file"));
+            goto cleanup;
+        }
+
+        zerosLen = header->data_len - len;
+        if (VIR_ALLOC_N(zeros, zerosLen) < 0)
+            goto cleanup;
+    } else {
+        header->data_len = len;
+    }
 
     if (safewrite(fd, header, sizeof(*header)) != sizeof(*header)) {
-        ret = -errno;
-        virReportError(VIR_ERR_OPERATION_FAILED,
-                       _("failed to write header to domain save file '%s'"),
-                       path);
-        goto endjob;
+        virReportSystemError(errno,
+                             _("failed to write header to domain save file '%s'"),
+                             path);
+        goto cleanup;
     }
 
-    if (safewrite(fd, xml, header->data_len) != header->data_len) {
-        ret = -errno;
-        virReportError(VIR_ERR_OPERATION_FAILED,
-                       _("failed to write xml to '%s'"), path);
-        goto endjob;
+    if (safewrite(fd, xml, header->data_len) != header->data_len ||
+        safewrite(fd, zeros, zerosLen) != zerosLen) {
+        virReportSystemError(errno,
+                             _("failed to write domain xml to '%s'"),
+                             path);
+        goto cleanup;
     }
- endjob:
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(zeros);
     return ret;
 }
 
@@ -3132,8 +3164,7 @@ qemuDomainSaveMemory(virQEMUDriverPtr driver,
     if (!(wrapperFd = virFileWrapperFdNew(&fd, path, wrapperFlags)))
         goto cleanup;
 
-    /* Write header to file, followed by XML */
-    if (qemuDomainSaveHeader(fd, path, domXML, header) < 0)
+    if (virQEMUSaveDataWrite(header, domXML, fd, path) < 0)
         goto cleanup;
 
     /* Perform the migration */
@@ -6620,7 +6651,6 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path,
     virDomainDefPtr newdef = NULL;
     int fd = -1;
     char *xml = NULL;
-    size_t len;
     virQEMUSaveHeaderPtr header = NULL;
     int state = -1;
 
@@ -6656,30 +6686,22 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path,
 
     VIR_FREE(xml);
 
-    xml = qemuDomainDefFormatXML(driver, newdef,
-                                 VIR_DOMAIN_XML_INACTIVE |
-                                 VIR_DOMAIN_XML_SECURE |
-                                 VIR_DOMAIN_XML_MIGRATABLE);
-    if (!xml)
-        goto cleanup;
-    len = strlen(xml) + 1;
-
-    if (len > header->data_len) {
-        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
-                       _("new xml too large to fit in file"));
-        goto cleanup;
-    }
-    if (VIR_EXPAND_N(xml, len, header->data_len - len) < 0)
+    if (!(xml = qemuDomainDefFormatXML(driver, newdef,
+                                       VIR_DOMAIN_XML_INACTIVE |
+                                       VIR_DOMAIN_XML_SECURE |
+                                       VIR_DOMAIN_XML_MIGRATABLE)))
         goto cleanup;
 
     if (lseek(fd, 0, SEEK_SET) != 0) {
         virReportSystemError(errno, _("cannot seek in '%s'"), path);
         goto cleanup;
     }
-    if (safewrite(fd, &header, sizeof(header)) != sizeof(header) ||
-        safewrite(fd, xml, len) != len ||
-        VIR_CLOSE(fd) < 0) {
-        virReportSystemError(errno, _("failed to write xml to '%s'"), path);
+
+    if (virQEMUSaveDataWrite(header, xml, fd, path) < 0)
+        goto cleanup;
+
+    if (VIR_CLOSE(fd) < 0) {
+        virReportSystemError(errno, _("failed to write header data to '%s'"), path);
         goto cleanup;
     }
 
-- 
2.13.1