[libvirt PATCH v3 02/10] qemu_saveimage: introduce helpers to decompress memory state file

Pavel Hrdina posted 10 patches 5 months, 1 week ago
[libvirt PATCH v3 02/10] qemu_saveimage: introduce helpers to decompress memory state file
Posted by Pavel Hrdina 5 months, 1 week ago
These new helpers separates the code from the logic used to start new
QEMU process with memory state and will make it easier to move
qemuSaveImageStartProcess() into qemu_process.c file.

Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
 src/qemu/qemu_saveimage.c | 155 +++++++++++++++++++++++++++-----------
 src/qemu/qemu_saveimage.h |  15 ++++
 2 files changed, 128 insertions(+), 42 deletions(-)

diff --git a/src/qemu/qemu_saveimage.c b/src/qemu/qemu_saveimage.c
index 27b95b03ae..95fabee907 100644
--- a/src/qemu/qemu_saveimage.c
+++ b/src/qemu/qemu_saveimage.c
@@ -247,6 +247,116 @@ qemuSaveImageGetCompressionCommand(virQEMUSaveFormat compression)
 }
 
 
+/**
+ * qemuSaveImageDecompressionStart:
+ * @data: data from memory state file
+ * @fd: pointer to FD of memory state file
+ * @intermediatefd: pointer to FD to store original @fd
+ * @errbuf: error buffer for @retcmd
+ * @retcmd: new virCommand pointer
+ *
+ * Start process to decompress VM memory state from @fd. If decompression
+ * is needed the original FD is stored to @intermediatefd and new FD after
+ * decompression is stored to @fd so caller can use the same variable
+ * in both cases.
+ *
+ * Function qemuSaveImageDecompressionStop() needs to be used to correctly
+ * stop the process and swap FD to the original state.
+ *
+ * Caller is responsible for freeing @retcmd.
+ *
+ * Returns -1 on error, 0 on success.
+ */
+int
+qemuSaveImageDecompressionStart(virQEMUSaveData *data,
+                                int *fd,
+                                int *intermediatefd,
+                                char **errbuf,
+                                virCommand **retcmd)
+{
+    virQEMUSaveHeader *header = &data->header;
+    g_autoptr(virCommand) cmd = NULL;
+
+    if (header->version != 2)
+        return 0;
+
+    if (header->compressed == QEMU_SAVE_FORMAT_RAW)
+        return 0;
+
+    if (!(cmd = qemuSaveImageGetCompressionCommand(header->compressed)))
+        return -1;
+
+    *intermediatefd = *fd;
+    *fd = -1;
+
+    virCommandSetInputFD(cmd, *intermediatefd);
+    virCommandSetOutputFD(cmd, fd);
+    virCommandSetErrorBuffer(cmd, errbuf);
+    virCommandDoAsyncIO(cmd);
+
+    if (virCommandRunAsync(cmd, NULL) < 0) {
+        *fd = *intermediatefd;
+        *intermediatefd = -1;
+        return -1;
+    }
+
+    *retcmd = g_steal_pointer(&cmd);
+    return 0;
+}
+
+
+/**
+ * qemuSaveImageDecompressionStop:
+ * @cmd: virCommand pointer
+ * @fd: pointer to FD of memory state file
+ * @intermediatefd: pointer to FD to store original @fd
+ * @errbuf: error buffer for @cmd
+ * @started: boolean to indicate if QEMU process was started
+ * @path: path to the memory state file
+ *
+ * Stop decompression process and close both @fd and @intermediatefd if
+ * necessary.
+ *
+ * Returns -1 on errro, 0 on success.
+ */
+int
+qemuSaveImageDecompressionStop(virCommand *cmd,
+                               int *fd,
+                               int *intermediatefd,
+                               char *errbuf,
+                               bool started,
+                               const char *path)
+{
+    int rc = 0;
+    virErrorPtr orig_err = NULL;
+
+    if (*intermediatefd == -1)
+        return rc;
+
+    if (!started) {
+        /* if there was an error setting up qemu, the intermediate
+         * process will wait forever to write to stdout, so we
+         * must manually kill it and ignore any error related to
+         * the process
+         */
+        virErrorPreserveLast(&orig_err);
+        VIR_FORCE_CLOSE(*intermediatefd);
+        VIR_FORCE_CLOSE(*fd);
+    }
+
+    rc = virCommandWait(cmd, NULL);
+    VIR_DEBUG("Decompression binary stderr: %s", NULLSTR(errbuf));
+    virErrorRestore(&orig_err);
+
+    if (VIR_CLOSE(*fd) < 0) {
+        virReportSystemError(errno, _("cannot close file: %1$s"), path);
+        rc = -1;
+    }
+
+    return rc;
+}
+
+
 /* Helper function to execute a migration to file with a correct save header
  * the caller needs to make sure that the processors are stopped and do all other
  * actions besides saving memory */
@@ -595,7 +705,6 @@ qemuSaveImageStartProcess(virConnectPtr conn,
 {
     qemuDomainObjPrivate *priv = vm->privateData;
     g_autoptr(qemuDomainSaveCookie) cookie = NULL;
-    virQEMUSaveHeader *header = &data->header;
     VIR_AUTOCLOSE intermediatefd = -1;
     g_autoptr(virCommand) cmd = NULL;
     g_autofree char *errbuf = NULL;
@@ -605,25 +714,8 @@ qemuSaveImageStartProcess(virConnectPtr conn,
                                  virDomainXMLOptionGetSaveCookie(driver->xmlopt)) < 0)
         return -1;
 
-    if ((header->version == 2) &&
-        (header->compressed != QEMU_SAVE_FORMAT_RAW)) {
-        if (!(cmd = qemuSaveImageGetCompressionCommand(header->compressed)))
-            return -1;
-
-        intermediatefd = *fd;
-        *fd = -1;
-
-        virCommandSetInputFD(cmd, intermediatefd);
-        virCommandSetOutputFD(cmd, fd);
-        virCommandSetErrorBuffer(cmd, &errbuf);
-        virCommandDoAsyncIO(cmd);
-
-        if (virCommandRunAsync(cmd, NULL) < 0) {
-            *fd = intermediatefd;
-            intermediatefd = -1;
-            return -1;
-        }
-    }
+    if (qemuSaveImageDecompressionStart(data, fd, &intermediatefd, &errbuf, &cmd) < 0)
+        return -1;
 
     /* No cookie means libvirt which saved the domain was too old to mess up
      * the CPU definitions.
@@ -641,28 +733,7 @@ qemuSaveImageStartProcess(virConnectPtr conn,
                          start_flags) == 0)
         *started = true;
 
-    if (intermediatefd != -1) {
-        virErrorPtr orig_err = NULL;
-
-        if (!*started) {
-            /* if there was an error setting up qemu, the intermediate
-             * process will wait forever to write to stdout, so we
-             * must manually kill it and ignore any error related to
-             * the process
-             */
-            virErrorPreserveLast(&orig_err);
-            VIR_FORCE_CLOSE(intermediatefd);
-            VIR_FORCE_CLOSE(*fd);
-        }
-
-        rc = virCommandWait(cmd, NULL);
-        VIR_DEBUG("Decompression binary stderr: %s", NULLSTR(errbuf));
-        virErrorRestore(&orig_err);
-    }
-    if (VIR_CLOSE(*fd) < 0) {
-        virReportSystemError(errno, _("cannot close file: %1$s"), path);
-        rc = -1;
-    }
+    rc = qemuSaveImageDecompressionStop(cmd, fd, &intermediatefd, errbuf, *started, path);
 
     virDomainAuditStart(vm, "restored", *started);
     if (!*started || rc < 0)
diff --git a/src/qemu/qemu_saveimage.h b/src/qemu/qemu_saveimage.h
index 24249ddf4c..dcee482066 100644
--- a/src/qemu/qemu_saveimage.h
+++ b/src/qemu/qemu_saveimage.h
@@ -99,6 +99,21 @@ qemuSaveImageGetCompressionProgram(const char *imageFormat,
                                    bool use_raw_on_fail)
     ATTRIBUTE_NONNULL(2);
 
+int
+qemuSaveImageDecompressionStart(virQEMUSaveData *data,
+                                int *fd,
+                                int *intermediatefd,
+                                char **errbuf,
+                                virCommand **retcmd);
+
+int
+qemuSaveImageDecompressionStop(virCommand *cmd,
+                               int *fd,
+                               int *intermediatefd,
+                               char *errbuf,
+                               bool started,
+                               const char *path);
+
 int
 qemuSaveImageCreate(virQEMUDriver *driver,
                     virDomainObj *vm,
-- 
2.41.0