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

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

 



Signed-off-by: Jim Fehlig <jfehlig@xxxxxxxx>
---
 src/qemu/qemu_driver.c    | 22 +++++++++++++---------
 src/qemu/qemu_migration.c |  2 +-
 src/qemu/qemu_process.c   | 20 ++++++++++++++++----
 src/qemu/qemu_process.h   |  3 +++
 src/qemu/qemu_saveimage.c | 29 +++++++++++++++++++++++++----
 src/qemu/qemu_saveimage.h |  4 +++-
 src/qemu/qemu_snapshot.c  |  8 ++++----
 7 files changed, 65 insertions(+), 23 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 34f37210d9..53674458bf 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1624,7 +1624,7 @@ static virDomainPtr qemuDomainCreateXML(virConnectPtr conn,
     }
 
     if (qemuProcessStart(conn, driver, vm, NULL, VIR_ASYNC_JOB_START,
-                         NULL, -1, NULL, NULL,
+                         NULL, -1, -1, NULL, NULL,
                          VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
                          start_flags) < 0) {
         virDomainAuditStart(vm, "booted", false);
@@ -5742,6 +5742,7 @@ qemuDomainRestoreInternal(virConnectPtr conn,
     g_autofree char *xmlout = NULL;
     const char *newxml = dxml;
     int fd = -1;
+    int nondirectFd = -1;
     int ret = -1;
     virQEMUSaveData *data = NULL;
     virFileWrapperFd *wrapperFd = NULL;
@@ -5758,7 +5759,7 @@ qemuDomainRestoreInternal(virConnectPtr conn,
 
     fd = qemuSaveImageOpen(driver, NULL, path, &def, &data,
                            (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0,
-                           &wrapperFd, false, false);
+                           &wrapperFd, &nondirectFd, false, false);
     if (fd < 0)
         goto cleanup;
 
@@ -5812,13 +5813,14 @@ qemuDomainRestoreInternal(virConnectPtr conn,
     if (qemuProcessBeginJob(vm, VIR_DOMAIN_JOB_OPERATION_RESTORE, flags) < 0)
         goto cleanup;
 
-    ret = qemuSaveImageStartVM(conn, driver, vm, &fd, data, path,
+    ret = qemuSaveImageStartVM(conn, driver, vm, &fd, nondirectFd, data, path,
                                false, reset_nvram, VIR_ASYNC_JOB_START);
 
     qemuProcessEndJob(vm);
 
  cleanup:
     VIR_FORCE_CLOSE(fd);
+    VIR_FORCE_CLOSE(nondirectFd);
     if (virFileWrapperFdClose(wrapperFd) < 0)
         ret = -1;
     virFileWrapperFdFree(wrapperFd);
@@ -5893,7 +5895,7 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path,
     virCheckFlags(VIR_DOMAIN_SAVE_IMAGE_XML_SECURE, NULL);
 
     fd = qemuSaveImageOpen(driver, NULL, path, &def, &data,
-                           false, NULL, false, false);
+                           false, NULL, NULL, false, false);
 
     if (fd < 0)
         goto cleanup;
@@ -5930,7 +5932,7 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path,
         state = 0;
 
     fd = qemuSaveImageOpen(driver, NULL, path, &def, &data,
-                           false, NULL, true, false);
+                           false, NULL, NULL, true, false);
 
     if (fd < 0)
         goto cleanup;
@@ -6011,7 +6013,7 @@ qemuDomainManagedSaveGetXMLDesc(virDomainPtr dom, unsigned int flags)
     }
 
     if ((fd = qemuSaveImageOpen(driver, priv->qemuCaps, path, &def, &data,
-                                false, NULL, false, false)) < 0)
+                                false, NULL, NULL, false, false)) < 0)
         goto cleanup;
 
     ret = qemuDomainDefFormatXML(driver, priv->qemuCaps, def, flags);
@@ -6069,13 +6071,14 @@ qemuDomainObjRestore(virConnectPtr conn,
     g_autoptr(virDomainDef) def = NULL;
     qemuDomainObjPrivate *priv = vm->privateData;
     int fd = -1;
+    int nondirectFd = -1;
     int ret = -1;
     g_autofree char *xmlout = NULL;
     virQEMUSaveData *data = NULL;
     virFileWrapperFd *wrapperFd = NULL;
 
     fd = qemuSaveImageOpen(driver, NULL, path, &def, &data,
-                           bypass_cache, &wrapperFd, false, true);
+                           bypass_cache, &wrapperFd, &nondirectFd, false, true);
     if (fd < 0) {
         if (fd == -3)
             ret = 1;
@@ -6120,12 +6123,13 @@ qemuDomainObjRestore(virConnectPtr conn,
 
     virDomainObjAssignDef(vm, &def, true, NULL);
 
-    ret = qemuSaveImageStartVM(conn, driver, vm, &fd, data, path,
+    ret = qemuSaveImageStartVM(conn, driver, vm, &fd, nondirectFd, data, path,
                                start_paused, reset_nvram, asyncJob);
 
  cleanup:
     virQEMUSaveDataFree(data);
     VIR_FORCE_CLOSE(fd);
+    VIR_FORCE_CLOSE(nondirectFd);
     if (virFileWrapperFdClose(wrapperFd) < 0)
         ret = -1;
     virFileWrapperFdFree(wrapperFd);
@@ -6321,7 +6325,7 @@ qemuDomainObjStart(virConnectPtr conn,
     }
 
     ret = qemuProcessStart(conn, driver, vm, NULL, asyncJob,
-                           NULL, -1, NULL, NULL,
+                           NULL, -1, -1, NULL, NULL,
                            VIR_NETDEV_VPORT_PROFILE_OP_CREATE, start_flags);
     virDomainAuditStart(vm, "booted", ret >= 0);
     if (ret >= 0) {
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index a0435a0572..0b1e03394e 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -3009,7 +3009,7 @@ qemuMigrationDstPrepare(virDomainObj *vm,
     }
 
     return qemuProcessIncomingDefNew(vm, listenAddress,
-                                     migrateFrom, fd, NULL, 0);
+                                     migrateFrom, fd, -1, NULL, 0);
 }
 
 
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index f700390a8c..f5b2f9ea2b 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4688,6 +4688,7 @@ qemuProcessIncomingDefNew(virDomainObj *vm,
                           const char *listenAddress,
                           const char *migrateFrom,
                           int fd,
+                          int nondirectFd,
                           const char *path,
                           unsigned int flags)
 {
@@ -4707,11 +4708,18 @@ qemuProcessIncomingDefNew(virDomainObj *vm,
         unsigned int fdsetId;
         off_t offset;
 
-        if ((offset = lseek(fd, 0, SEEK_CUR)) == -1)
-            offset = 0;
+        if (nondirectFd == -1)
+            offset = lseek(fd, 0, SEEK_CUR);
+        else
+            offset = lseek(nondirectFd, 0, SEEK_CUR);
+
+        if (offset < 0)
+            goto error;
 
         inc->fdPassMigrate = qemuFDPassNew("migrate", priv);
         qemuFDPassAddFD(inc->fdPassMigrate, &fd, "-fd");
+        if (nondirectFd != -1)
+            qemuFDPassAddFD(inc->fdPassMigrate, &nondirectFd, "-nondirect-fd");
         qemuFDPassGetId(inc->fdPassMigrate, &fdsetId);
         inc->uri = g_strdup_printf("file:/dev/fdset/%u,offset=%#lx", fdsetId, offset);
     } else {
@@ -8148,6 +8156,7 @@ qemuProcessStart(virConnectPtr conn,
                  virDomainAsyncJob asyncJob,
                  const char *migrateFrom,
                  int migrateFd,
+                 int migrateNondirectFd,
                  const char *migratePath,
                  virDomainMomentObj *snapshot,
                  virNetDevVPortProfileOp vmop,
@@ -8185,7 +8194,8 @@ qemuProcessStart(virConnectPtr conn,
 
     if (migrateFrom) {
         incoming = qemuProcessIncomingDefNew(vm, NULL, migrateFrom,
-                                             migrateFd, migratePath, flags);
+                                             migrateFd, migrateNondirectFd,
+                                             migratePath, flags);
         if (!incoming)
             goto stop;
     }
@@ -8264,6 +8274,7 @@ qemuProcessStart(virConnectPtr conn,
  * @driver: qemu driver object
  * @vm: domain object
  * @fd: FD pointer of memory state file
+ * @nondirectFd: FD for memory state file, opened without O_DIRECT
  * @path: path to memory state file
  * @snapshot: internal snapshot to load when starting QEMU process or NULL
  * @data: data from memory state file or NULL
@@ -8290,6 +8301,7 @@ qemuProcessStartWithMemoryState(virConnectPtr conn,
                                 virQEMUDriver *driver,
                                 virDomainObj *vm,
                                 int *fd,
+                                int nondirectFd,
                                 const char *path,
                                 virDomainMomentObj *snapshot,
                                 virQEMUSaveData *data,
@@ -8329,7 +8341,7 @@ qemuProcessStartWithMemoryState(virConnectPtr conn,
         priv->disableSlirp = true;
 
     if (qemuProcessStart(conn, driver, vm, cookie ? cookie->cpu : NULL,
-                         asyncJob, migrateFrom, *fd, path, snapshot,
+                         asyncJob, migrateFrom, *fd, nondirectFd, path, snapshot,
                          VIR_NETDEV_VPORT_PROFILE_OP_RESTORE,
                          start_flags) == 0)
         *started = true;
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index a5212ee56e..6e37dac2ca 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -62,6 +62,7 @@ qemuProcessIncomingDef *qemuProcessIncomingDefNew(virDomainObj *vm,
                                                   const char *listenAddress,
                                                   const char *migrateFrom,
                                                   int fd,
+                                                  int nondirectFd,
                                                   const char *path,
                                                   unsigned int flags);
 void qemuProcessIncomingDefFree(qemuProcessIncomingDef *inc);
@@ -89,6 +90,7 @@ int qemuProcessStart(virConnectPtr conn,
                      virDomainAsyncJob asyncJob,
                      const char *migrateFrom,
                      int stdin_fd,
+                     int nondirectFd,
                      const char *stdin_path,
                      virDomainMomentObj *snapshot,
                      virNetDevVPortProfileOp vmop,
@@ -98,6 +100,7 @@ int qemuProcessStartWithMemoryState(virConnectPtr conn,
                                     virQEMUDriver *driver,
                                     virDomainObj *vm,
                                     int *fd,
+                                    int nondirectFd,
                                     const char *path,
                                     virDomainMomentObj *snapshot,
                                     virQEMUSaveData *data,
diff --git a/src/qemu/qemu_saveimage.c b/src/qemu/qemu_saveimage.c
index 2b0281895a..8e634862a6 100644
--- a/src/qemu/qemu_saveimage.c
+++ b/src/qemu/qemu_saveimage.c
@@ -610,6 +610,7 @@ qemuSaveImageGetCompressionProgram(const char *imageFormat,
  * @ret_data: returns structure filled with data from the image header
  * @bypass_cache: bypass cache when opening the file
  * @wrapperFd: returns the file wrapper structure
+ * @nondirectFd: returns file descriptor without O_DIRECT set
  * @open_write: open the file for writing (for updates)
  * @unlink_corrupt: remove the image file if it is corrupted
  *
@@ -625,11 +626,14 @@ qemuSaveImageOpen(virQEMUDriver *driver,
                   virQEMUSaveData **ret_data,
                   bool bypass_cache,
                   virFileWrapperFd **wrapperFd,
+                  int *nondirectFd,
                   bool open_write,
                   bool unlink_corrupt)
 {
     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
     VIR_AUTOCLOSE fd = -1;
+    VIR_AUTOCLOSE nondirect_fd = -1;
+    int read_fd;
     int ret = -1;
     g_autoptr(virQEMUSaveData) data = NULL;
     virQEMUSaveHeader *header;
@@ -646,6 +650,13 @@ qemuSaveImageOpen(virQEMUDriver *driver,
                            _("bypass cache unsupported by this system"));
             return -1;
         }
+
+        /* Also open the file without O_DIRECT for reading header and for
+         * qemu to use when reading unaligned state
+         */
+        if ((nondirect_fd = qemuDomainOpenFile(cfg, NULL, path, oflags, NULL)) < 0)
+            return -1;
+
         oflags |= directFlag;
     }
 
@@ -655,7 +666,12 @@ qemuSaveImageOpen(virQEMUDriver *driver,
     data = g_new0(virQEMUSaveData, 1);
 
     header = &data->header;
-    if (saferead(fd, header, sizeof(*header)) != sizeof(*header)) {
+    if (nondirect_fd != -1)
+        read_fd = nondirect_fd;
+    else
+        read_fd = fd;
+
+    if (saferead(read_fd, header, sizeof(*header)) != sizeof(*header)) {
         if (unlink_corrupt) {
             if (unlink(path) < 0) {
                 virReportSystemError(errno,
@@ -732,7 +748,7 @@ qemuSaveImageOpen(virQEMUDriver *driver,
 
     data->xml = g_new0(char, xml_len);
 
-    if (saferead(fd, data->xml, xml_len) != xml_len) {
+    if (saferead(read_fd, data->xml, xml_len) != xml_len) {
         virReportError(VIR_ERR_OPERATION_FAILED,
                        "%s", _("failed to read domain XML"));
         return -1;
@@ -741,7 +757,7 @@ qemuSaveImageOpen(virQEMUDriver *driver,
     if (cookie_len > 0) {
         data->cookie = g_new0(char, cookie_len);
 
-        if (saferead(fd, data->cookie, cookie_len) != cookie_len) {
+        if (saferead(read_fd, data->cookie, cookie_len) != cookie_len) {
             virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                            _("failed to read cookie"));
             return -1;
@@ -761,6 +777,10 @@ qemuSaveImageOpen(virQEMUDriver *driver,
 
     *ret_def = g_steal_pointer(&def);
     *ret_data = g_steal_pointer(&data);
+    if (nondirectFd) {
+        *nondirectFd = nondirect_fd;
+        nondirect_fd = -1;
+    }
 
     ret = fd;
     fd = -1;
@@ -774,6 +794,7 @@ qemuSaveImageStartVM(virConnectPtr conn,
                      virQEMUDriver *driver,
                      virDomainObj *vm,
                      int *fd,
+                     int nondirectFd,
                      virQEMUSaveData *data,
                      const char *path,
                      bool start_paused,
@@ -794,7 +815,7 @@ qemuSaveImageStartVM(virConnectPtr conn,
     if (header->features & QEMU_SAVE_FEATURE_MAPPED_RAM)
         start_flags |= VIR_QEMU_PROCESS_START_MAPPED_RAM;
 
-    if (qemuProcessStartWithMemoryState(conn, driver, vm, fd, path, NULL, data,
+    if (qemuProcessStartWithMemoryState(conn, driver, vm, fd, nondirectFd, path, NULL, data,
                                         asyncJob, start_flags, "restored",
                                         &started) < 0) {
         goto cleanup;
diff --git a/src/qemu/qemu_saveimage.h b/src/qemu/qemu_saveimage.h
index 81d93bf33c..0a8b35158a 100644
--- a/src/qemu/qemu_saveimage.h
+++ b/src/qemu/qemu_saveimage.h
@@ -67,12 +67,13 @@ qemuSaveImageStartVM(virConnectPtr conn,
                      virQEMUDriver *driver,
                      virDomainObj *vm,
                      int *fd,
+                     int nondirectFd,
                      virQEMUSaveData *data,
                      const char *path,
                      bool start_paused,
                      bool reset_nvram,
                      virDomainAsyncJob asyncJob)
-    ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5) ATTRIBUTE_NONNULL(6);
+    ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(6) ATTRIBUTE_NONNULL(7);
 
 int
 qemuSaveImageOpen(virQEMUDriver *driver,
@@ -82,6 +83,7 @@ qemuSaveImageOpen(virQEMUDriver *driver,
                   virQEMUSaveData **ret_data,
                   bool bypass_cache,
                   virFileWrapperFd **wrapperFd,
+                  int *nondirectFd,
                   bool open_write,
                   bool unlink_corrupt)
     ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4);
diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c
index 1e9e0e31d7..f137a79a8d 100644
--- a/src/qemu/qemu_snapshot.c
+++ b/src/qemu/qemu_snapshot.c
@@ -2115,7 +2115,7 @@ qemuSnapshotRevertExternalPrepare(virDomainObj *vm,
         memdata->path = snapdef->memorysnapshotfile;
         memdata->fd = qemuSaveImageOpen(driver, NULL, memdata->path,
                                         &savedef, &memdata->data,
-                                        false, NULL,
+                                        false, NULL, NULL,
                                         false, false);
 
         if (memdata->fd < 0)
@@ -2359,7 +2359,7 @@ qemuSnapshotRevertActive(virDomainObj *vm,
     virDomainObjAssignDef(vm, config, true, NULL);
 
     if (qemuProcessStartWithMemoryState(snapshot->domain->conn, driver, vm,
-                                        &memdata.fd, memdata.path, loadSnap,
+                                        &memdata.fd, -1, memdata.path, loadSnap,
                                         memdata.data, VIR_ASYNC_JOB_SNAPSHOT,
                                         start_flags, "from-snapshot",
                                         &started) < 0) {
@@ -2513,7 +2513,7 @@ qemuSnapshotRevertInactive(virDomainObj *vm,
         start_flags |= paused ? VIR_QEMU_PROCESS_START_PAUSED : 0;
 
         rc = qemuProcessStart(snapshot->domain->conn, driver, vm, NULL,
-                              VIR_ASYNC_JOB_SNAPSHOT, NULL, -1, NULL, NULL,
+                              VIR_ASYNC_JOB_SNAPSHOT, NULL, -1, -1, NULL, NULL,
                               VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
                               start_flags);
         virDomainAuditStart(vm, "from-snapshot", rc >= 0);
@@ -2991,7 +2991,7 @@ qemuSnapshotDeleteExternalPrepare(virDomainObj *vm,
 
         if (!virDomainObjIsActive(vm)) {
             if (qemuProcessStart(NULL, driver, vm, NULL, VIR_ASYNC_JOB_SNAPSHOT,
-                                 NULL, -1, NULL, NULL,
+                                 NULL, -1, -1, NULL, NULL,
                                  VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
                                  VIR_QEMU_PROCESS_START_PAUSED) < 0) {
                 return -1;
-- 
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