[PATCH v2 1/2] qemu: Allow saving QEMU libvirt state to a pipe

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Chen Hanxiao <chenhanxiao@xxxxxxxxx>

Base upon patches from Roy Keene <rkeene@xxxxxxxxxxxxxxx>

Currently qemuDomainSaveMemory can save vm's config
and memory to fd.
It write a magic QEMU_SAVE_PARTIAL firstly,
then re-open it to change QEMU_SAVE_PARTIAL as QEMU_SAVE_MAGIC.

For pipes this is not possible, attempting to re-open the pipe
will not connect you to the same consumer.
Seeking is also not possible on a pipe.

This patch introduce VIR_DOMAIN_SAVE_DIRECT
If set, write QEMU_SAVE_MAGIC directly.

This is useful to me for saving a VM state directly to
Ceph RBD images without having an intermediate file.

Signed-off-by: Roy Keene <rkeene@xxxxxxxxxxxxxxx>
Signed-off-by: Chen Hanxiao <chenhanxiao@xxxxxxxxx>
---
v2:
  rename VIR_DOMAIN_SAVE_PIPE to VIR_DOMAIN_SAVE_DIRECT
  remove S_ISFIFO check for dst path

 include/libvirt/libvirt-domain.h |  1 +
 src/qemu/qemu_driver.c           | 54 ++++++++++++++++++++++++++--------------
 2 files changed, 37 insertions(+), 18 deletions(-)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 3290b10..48865a8 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -1169,6 +1169,7 @@ typedef enum {
     VIR_DOMAIN_SAVE_BYPASS_CACHE = 1 << 0, /* Avoid file system cache pollution */
     VIR_DOMAIN_SAVE_RUNNING      = 1 << 1, /* Favor running over paused */
     VIR_DOMAIN_SAVE_PAUSED       = 1 << 2, /* Favor paused over running */
+    VIR_DOMAIN_SAVE_DIRECT       = 1 << 3, /* Write QEMU_SAVE_MAGIC directly */
 } virDomainSaveRestoreFlags;
 
 int                     virDomainSave           (virDomainPtr domain,
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 88778d4..76b25ad 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3051,6 +3051,7 @@ qemuDomainSaveMemory(virQEMUDriverPtr driver,
     virQEMUSaveHeader header;
     bool bypassSecurityDriver = false;
     bool needUnlink = false;
+    bool canReopen = true;
     int ret = -1;
     int fd = -1;
     int directFlag = 0;
@@ -3058,7 +3059,6 @@ qemuDomainSaveMemory(virQEMUDriverPtr driver,
     unsigned int wrapperFlags = VIR_FILE_WRAPPER_NON_BLOCKING;
 
     memset(&header, 0, sizeof(header));
-    memcpy(header.magic, QEMU_SAVE_PARTIAL, sizeof(header.magic));
     header.version = QEMU_SAVE_VERSION;
     header.was_running = was_running ? 1 : 0;
     header.compressed = compressed;
@@ -3074,6 +3074,7 @@ qemuDomainSaveMemory(virQEMUDriverPtr driver,
             goto cleanup;
         }
     }
+
     fd = qemuOpenFile(driver, vm, path,
                       O_WRONLY | O_TRUNC | O_CREAT | directFlag,
                       &needUnlink, &bypassSecurityDriver);
@@ -3086,6 +3087,20 @@ qemuDomainSaveMemory(virQEMUDriverPtr driver,
     if (!(wrapperFd = virFileWrapperFdNew(&fd, path, wrapperFlags)))
         goto cleanup;
 
+    /* Set the header magic.
+     * Setting flags VIR_DOMAIN_SAVE_DIRECT will write
+     * magic QEMU_SAVE_MAGIC directly.
+     * For PIPE, we should do this because it can't be reopen.
+     * Otherwise we'll update the magic after
+     * the saving completes successfully.
+     */
+    if (flags & VIR_DOMAIN_SAVE_DIRECT) {
+        canReopen = false;
+        memcpy(header.magic, QEMU_SAVE_MAGIC, sizeof(header.magic));
+    } else {
+        memcpy(header.magic, QEMU_SAVE_PARTIAL, sizeof(header.magic));
+    }
+
     /* Write header to file, followed by XML */
     if (qemuDomainSaveHeader(fd, path, domXML, &header) < 0)
         goto cleanup;
@@ -3094,28 +3109,30 @@ qemuDomainSaveMemory(virQEMUDriverPtr driver,
     if (qemuMigrationToFile(driver, vm, fd, compressedpath, asyncJob) < 0)
         goto cleanup;
 
-    /* Touch up file header to mark image complete. */
+    if (canReopen) {
+        /* Touch up file header to mark image complete. */
 
-    /* Reopen the file to touch up the header, since we aren't set
-     * up to seek backwards on wrapperFd.  The reopened fd will
-     * trigger a single page of file system cache pollution, but
-     * that's acceptable.  */
-    if (VIR_CLOSE(fd) < 0) {
-        virReportSystemError(errno, _("unable to close %s"), path);
-        goto cleanup;
-    }
+        /* Reopen the file to touch up the header, since we aren't set
+        * up to seek backwards on wrapperFd.  The reopened fd will
+        * trigger a single page of file system cache pollution, but
+        * that's acceptable.  */
+        if (VIR_CLOSE(fd) < 0) {
+                virReportSystemError(errno, _("unable to close %s"), path);
+                goto cleanup;
+        }
 
-    if (virFileWrapperFdClose(wrapperFd) < 0)
-        goto cleanup;
+        if (virFileWrapperFdClose(wrapperFd) < 0)
+                goto cleanup;
 
-    if ((fd = qemuOpenFile(driver, vm, path, O_WRONLY, NULL, NULL)) < 0)
-        goto cleanup;
+        if ((fd = qemuOpenFile(driver, vm, path, O_WRONLY, NULL, NULL)) < 0)
+                goto cleanup;
 
-    memcpy(header.magic, QEMU_SAVE_MAGIC, sizeof(header.magic));
+        memcpy(header.magic, QEMU_SAVE_MAGIC, sizeof(header.magic));
 
-    if (safewrite(fd, &header, sizeof(header)) != sizeof(header)) {
-        virReportSystemError(errno, _("unable to write %s"), path);
-        goto cleanup;
+        if (safewrite(fd, &header, sizeof(header)) != sizeof(header)) {
+                virReportSystemError(errno, _("unable to write %s"), path);
+                goto cleanup;
+        }
     }
 
     if (VIR_CLOSE(fd) < 0) {
@@ -3345,6 +3362,7 @@ qemuDomainSaveFlags(virDomainPtr dom, const char *path, const char *dxml,
 
     virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
                   VIR_DOMAIN_SAVE_RUNNING |
+                  VIR_DOMAIN_SAVE_DIRECT |
                   VIR_DOMAIN_SAVE_PAUSED, -1);
 
     cfg = virQEMUDriverGetConfig(driver);
-- 
2.7.4


--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list



[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]
  Powered by Linux