[PATCH RFC 8/9] qemu: Support O_DIRECT with mapped-ram on save

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

 



Signed-off-by: Jim Fehlig <jfehlig@xxxxxxxx>
---

I'm not happy with this and the subsequent patch, which pass another FD
around for QEMU to use for reading/writing unaligned state when
BYPASS_CACHE has been specified. One idea is to pass the qemuFdPass object
around the various functions, but qemu_fd.h already includes qemu_monitor.h.
E.g. passing a qemuFdPass to qemuMonitorMigrateToMappedFile requires
including qemu_fd.h in qemu_monitor.h, so a cyclical dependency. I could
move qemuFDPass*TransferMonitor* functions to qemu_monitor.[ch] to avoid
the include in qemu_fd.h, but would likely require moving the _qemuFDPass
struct in qemu_fd.c to qemu_fd.h.

Another idea is to move qemuProcessIncomingDefNew in qemu_process.c to
qemuMigrationConnectionDefNew() in qemu_migration.c. Also move
qemuProcessIncomingDef object in qemu_process.h to qemuMigrationConnectDef
(or something like that) in qemu_migration.h. The qemuMigrationConnectDef
can encapsulate all the connection info related to the migration. E.g.
traditional fd, path associated with fd, uri, listen address, qemuFDPass
object containing fds for mapped_ram, etc. This can be used by both save
and restore paths.

Other suggestions kindly welcomed :-).

 src/qemu/qemu_migration.c |  3 ++-
 src/qemu/qemu_migration.h |  1 +
 src/qemu/qemu_monitor.c   | 14 +++++++++++---
 src/qemu/qemu_monitor.h   |  3 ++-
 src/qemu/qemu_saveimage.c | 25 +++++++++++++++++--------
 5 files changed, 33 insertions(+), 13 deletions(-)

diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index b1d27e07e1..a0435a0572 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -7084,6 +7084,7 @@ qemuMigrationSrcToFile(virQEMUDriver *driver, virDomainObj *vm,
 int
 qemuMigrationSrcToMappedFile(virQEMUDriver *driver, virDomainObj *vm,
                              int fd,
+                             int nondirectFD,
                              virDomainAsyncJob asyncJob)
 {
     qemuDomainObjPrivate *priv = vm->privateData;
@@ -7121,7 +7122,7 @@ qemuMigrationSrcToMappedFile(virQEMUDriver *driver, virDomainObj *vm,
     if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0)
         goto cleanup;
 
-    rc = qemuMonitorMigrateToFdSet(vm, 0, fd);
+    rc = qemuMonitorMigrateToFdSet(vm, 0, fd, nondirectFD);
     qemuDomainObjExitMonitor(vm);
     if (rc < 0)
         goto cleanup;
diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h
index 864f3280e5..939205ef13 100644
--- a/src/qemu/qemu_migration.h
+++ b/src/qemu/qemu_migration.h
@@ -245,6 +245,7 @@ int
 qemuMigrationSrcToMappedFile(virQEMUDriver *driver,
                              virDomainObj *vm,
                              int fd,
+                             int nondirectFD,
                              virDomainAsyncJob asyncJob)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;
 
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 4c92bd740a..c0936bee6b 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -2240,7 +2240,8 @@ qemuMonitorMigrateToFd(qemuMonitor *mon,
 int
 qemuMonitorMigrateToFdSet(virDomainObj *vm,
                           unsigned int flags,
-                          int fd)
+                          int fd,
+                          int nondirectFD)
 {
     qemuDomainObjPrivate *priv = vm->privateData;
     qemuMonitor *mon = priv->mon;
@@ -2249,15 +2250,22 @@ qemuMonitorMigrateToFdSet(virDomainObj *vm,
     unsigned int setId;
     g_autofree char *uri = NULL;
 
-    VIR_DEBUG("fd=%d flags=0x%x", fd, flags);
+    VIR_DEBUG("fd=%d nondirectFD=%d flags=0x%x", fd, nondirectFD, flags);
 
     QEMU_CHECK_MONITOR(mon);
 
-    if ((offset = lseek(fd, 0, SEEK_CUR)) == -1)
+    if (nondirectFD != -1)
+        offset = lseek(nondirectFD, 0, SEEK_CUR);
+    else
+        offset = lseek(fd, 0, SEEK_CUR);
+
+    if (offset == -1)
         return -1;
 
     fdPassMigrate = qemuFDPassNew("migrate", priv);
     qemuFDPassAddFD(fdPassMigrate, &fd, "-fd");
+    if (nondirectFD != -1)
+        qemuFDPassAddFD(fdPassMigrate, &nondirectFD, "-nondirect-fd");
     qemuFDPassTransferMonitor(fdPassMigrate, mon);
 
     if (qemuFDPassGetId(fdPassMigrate, &setId) < 0)
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index c477def138..0fbb2dadc1 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -845,7 +845,8 @@ int qemuMonitorMigrateToFd(qemuMonitor *mon,
 
 int qemuMonitorMigrateToFdSet(virDomainObj *vm,
                               unsigned int flags,
-                              int fd);
+                              int fd,
+                              int nondirectFD);
 
 int qemuMonitorMigrateToHost(qemuMonitor *mon,
                              unsigned int flags,
diff --git a/src/qemu/qemu_saveimage.c b/src/qemu/qemu_saveimage.c
index 1545c00472..2b0281895a 100644
--- a/src/qemu/qemu_saveimage.c
+++ b/src/qemu/qemu_saveimage.c
@@ -431,19 +431,28 @@ qemuSaveImageCreateMapped(virQEMUDriver *driver,
                           virDomainAsyncJob asyncJob)
 {
     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
+    VIR_AUTOCLOSE nondirectFD = -1;
 
-    /* mapped-ram does not support directIO */
+    /* If BYPASS_CACHE has been specified, fd has been opened with O_DIRECT.
+     * In this case, QEMU requires a second FD without O_DIRECT for writing
+     * unaligned state. We'll use this FD as well to write the header.
+     * Relative to VM RAM size, this data is a drop in the bucket and fine
+     * to write without O_DIRECT.
+    */
     if ((flags & VIR_DOMAIN_SAVE_BYPASS_CACHE)) {
-        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
-                       _("bypass cache unsupported by this system"));
-        return -1;
+        if ((nondirectFD = qemuDomainOpenFile(cfg, vm->def, path, O_WRONLY, NULL)) < 0)
+            return -1;
+        if (qemuSecuritySetImageFDLabel(driver->securityManager, vm->def, nondirectFD) < 0)
+            return -1;
+        if (virQEMUSaveDataWrite(data, nondirectFD, path) < 0)
+            return -1;
+    } else {
+        if (virQEMUSaveDataWrite(data, fd, path) < 0)
+            return -1;
     }
 
-    if (virQEMUSaveDataWrite(data, fd, path) < 0)
-        return -1;
-
     /* Perform the migration */
-    return qemuMigrationSrcToMappedFile(driver, vm, fd, asyncJob);
+    return qemuMigrationSrcToMappedFile(driver, vm, fd, nondirectFD, asyncJob);
 }
 
 
-- 
2.44.0



[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