[PATCH V3 13/19] qemu: Add support for mapped-ram on restore

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

 



Add support for the mapped-ram migration capability on restore.

Signed-off-by: Jim Fehlig <jfehlig@xxxxxxxx>
---
 src/qemu/qemu_driver.c    | 27 +++++++++++++++++++-------
 src/qemu/qemu_migration.c | 12 ++++++------
 src/qemu/qemu_process.c   | 41 ++++++++++++++++++++++++++++-----------
 src/qemu/qemu_process.h   | 15 +++++++++-----
 src/qemu/qemu_saveimage.c | 29 ++++++++++++++++-----------
 src/qemu/qemu_saveimage.h |  2 ++
 src/qemu/qemu_snapshot.c  |  8 ++++----
 7 files changed, 90 insertions(+), 44 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index f77516a4f4..0f363849ba 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1614,7 +1614,7 @@ static virDomainPtr qemuDomainCreateXML(virConnectPtr conn,
     }
 
     if (qemuProcessStart(conn, driver, vm, NULL, VIR_ASYNC_JOB_START,
-                         NULL, -1, NULL, NULL,
+                         NULL, -1, NULL, NULL, NULL,
                          VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
                          start_flags) < 0) {
         virDomainAuditStart(vm, "booted", false);
@@ -5783,6 +5783,8 @@ qemuDomainRestoreInternal(virConnectPtr conn,
     virFileWrapperFd *wrapperFd = NULL;
     bool hook_taint = false;
     bool reset_nvram = false;
+    bool sparse = false;
+    g_autoptr(qemuMigrationParams) restoreParams = NULL;
 
     virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
                   VIR_DOMAIN_SAVE_RUNNING |
@@ -5795,9 +5797,13 @@ qemuDomainRestoreInternal(virConnectPtr conn,
     if (qemuSaveImageGetMetadata(driver, NULL, path, &def, &data) < 0)
         goto cleanup;
 
+    sparse = data->header.format == QEMU_SAVE_FORMAT_SPARSE;
+    if (!(restoreParams = qemuMigrationParamsForSave(sparse)))
+        goto cleanup;
+
     fd = qemuSaveImageOpen(driver, path,
                            (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0,
-                           &wrapperFd, false);
+                           sparse, &wrapperFd, false);
     if (fd < 0)
         goto cleanup;
 
@@ -5851,7 +5857,7 @@ 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, data, path, restoreParams,
                                false, reset_nvram, VIR_ASYNC_JOB_START);
 
     qemuProcessEndJob(vm);
@@ -5966,7 +5972,8 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path,
     if (qemuSaveImageGetMetadata(driver, NULL, path, &def, &data) < 0)
         goto cleanup;
 
-    fd = qemuSaveImageOpen(driver, path, 0, NULL, false);
+    fd = qemuSaveImageOpen(driver, path, 0, false, NULL, false);
+
     if (fd < 0)
         goto cleanup;
 
@@ -6105,6 +6112,8 @@ qemuDomainObjRestore(virConnectPtr conn,
     g_autofree char *xmlout = NULL;
     virQEMUSaveData *data = NULL;
     virFileWrapperFd *wrapperFd = NULL;
+    bool sparse = false;
+    g_autoptr(qemuMigrationParams) restoreParams = NULL;
 
     ret = qemuSaveImageGetMetadata(driver, NULL, path, &def, &data);
     if (ret < 0) {
@@ -6122,7 +6131,11 @@ qemuDomainObjRestore(virConnectPtr conn,
         goto cleanup;
     }
 
-    fd = qemuSaveImageOpen(driver, path, bypass_cache, &wrapperFd, false);
+    sparse = data->header.format == QEMU_SAVE_FORMAT_SPARSE;
+    if (!(restoreParams = qemuMigrationParamsForSave(sparse)))
+        return -1;
+
+    fd = qemuSaveImageOpen(driver, path, bypass_cache, sparse, &wrapperFd, false);
     if (fd < 0)
         goto cleanup;
 
@@ -6164,7 +6177,7 @@ qemuDomainObjRestore(virConnectPtr conn,
 
     virDomainObjAssignDef(vm, &def, true, NULL);
 
-    ret = qemuSaveImageStartVM(conn, driver, vm, &fd, data, path,
+    ret = qemuSaveImageStartVM(conn, driver, vm, &fd, data, path, restoreParams,
                                start_paused, reset_nvram, asyncJob);
 
  cleanup:
@@ -6370,7 +6383,7 @@ qemuDomainObjStart(virConnectPtr conn,
     }
 
     ret = qemuProcessStart(conn, driver, vm, NULL, asyncJob,
-                           NULL, -1, NULL, NULL,
+                           NULL, -1, NULL, 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 bd46143717..9665b523af 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -3068,9 +3068,8 @@ qemuMigrationDstPrepare(virDomainObj *vm,
                         const char *protocol,
                         const char *listenAddress,
                         unsigned short port,
-                        int fd)
+                        int *fd)
 {
-    qemuDomainObjPrivate *priv = vm->privateData;
     g_autofree char *migrateFrom = NULL;
 
     if (tunnel) {
@@ -3124,8 +3123,9 @@ qemuMigrationDstPrepare(virDomainObj *vm,
         migrateFrom = g_strdup_printf(incFormat, protocol, listenAddress, port);
     }
 
-    return qemuProcessIncomingDefNew(priv->qemuCaps, listenAddress,
-                                     migrateFrom, fd, NULL);
+    return qemuProcessIncomingDefNew(vm, listenAddress,
+                                     migrateFrom, fd,
+                                     NULL, NULL);
 }
 
 
@@ -3267,7 +3267,7 @@ qemuMigrationDstPrepareActive(virQEMUDriver *driver,
 
     if (!(incoming = qemuMigrationDstPrepare(vm, tunnel, protocol,
                                              listenAddress, port,
-                                             dataFD[0])))
+                                             &dataFD[0])))
         goto error;
 
     qemuMigrationDstPrepareDiskSeclabels(vm, migrate_disks, flags);
@@ -3638,7 +3638,7 @@ qemuMigrationDstPrepareResume(virQEMUDriver *driver,
     priv->origname = g_strdup(origname);
 
     if (!(incoming = qemuMigrationDstPrepare(vm, false, protocol,
-                                             listenAddress, port, -1)))
+                                             listenAddress, port, NULL)))
         goto cleanup;
 
     if (qemuDomainObjEnterMonitorAsync(vm, VIR_ASYNC_JOB_MIGRATION_IN) < 0)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 063033cb95..94e7e90d28 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4823,6 +4823,7 @@ qemuProcessIncomingDefFree(qemuProcessIncomingDef *inc)
 
     g_free(inc->address);
     g_free(inc->uri);
+    qemuFDPassFree(inc->fdPassMigrate);
     g_free(inc);
 }
 
@@ -4836,26 +4837,38 @@ qemuProcessIncomingDefFree(qemuProcessIncomingDef *inc)
  * qemuProcessIncomingDefFree will NOT close it.
  */
 qemuProcessIncomingDef *
-qemuProcessIncomingDefNew(virQEMUCaps *qemuCaps,
+qemuProcessIncomingDefNew(virDomainObj *vm,
                           const char *listenAddress,
                           const char *migrateFrom,
-                          int fd,
-                          const char *path)
+                          int *fd,
+                          const char *path,
+                          virQEMUSaveData *data)
 {
+    qemuDomainObjPrivate *priv = vm->privateData;
     qemuProcessIncomingDef *inc = NULL;
 
-    if (qemuMigrationDstCheckProtocol(qemuCaps, migrateFrom) < 0)
+    if (qemuMigrationDstCheckProtocol(priv->qemuCaps, migrateFrom) < 0)
         return NULL;
 
     inc = g_new0(qemuProcessIncomingDef, 1);
 
     inc->address = g_strdup(listenAddress);
 
-    inc->uri = qemuMigrationDstGetURI(migrateFrom, fd);
+    if (data && data->header.format == QEMU_SAVE_FORMAT_SPARSE) {
+        size_t offset = sizeof(virQEMUSaveHeader) + data->header.data_len;
+
+        inc->fdPassMigrate = qemuFDPassNew("libvirt-incoming-migrate", priv);
+        qemuFDPassAddFD(inc->fdPassMigrate, fd, "-fd");
+        inc->uri = g_strdup_printf("file:%s,offset=%#lx",
+                                   qemuFDPassGetPath(inc->fdPassMigrate), offset);
+    } else {
+        inc->uri = qemuMigrationDstGetURI(migrateFrom, *fd);
+    }
+
     if (!inc->uri)
         goto error;
 
-    inc->fd = fd;
+    inc->fd = *fd;
     inc->path = path;
 
     return inc;
@@ -7899,8 +7912,11 @@ qemuProcessLaunch(virConnectPtr conn,
                                      &nnicindexes, &nicindexes)))
         goto cleanup;
 
-    if (incoming && incoming->fd != -1)
-        virCommandPassFD(cmd, incoming->fd, 0);
+    if (incoming) {
+        if (incoming->fd != -1)
+            virCommandPassFD(cmd, incoming->fd, 0);
+        qemuFDPassTransferCommand(incoming->fdPassMigrate, cmd);
+    }
 
     /* now that we know it is about to start call the hook if present */
     if (qemuProcessStartHook(driver, vm,
@@ -8319,6 +8335,7 @@ qemuProcessStart(virConnectPtr conn,
                  int migrateFd,
                  const char *migratePath,
                  virDomainMomentObj *snapshot,
+                 qemuMigrationParams *migParams,
                  virNetDevVPortProfileOp vmop,
                  unsigned int flags)
 {
@@ -8372,7 +8389,7 @@ qemuProcessStart(virConnectPtr conn,
     relabel = true;
 
     if (incoming) {
-        if (qemuMigrationDstRun(vm, incoming->uri, asyncJob, NULL, 0) < 0)
+        if (qemuMigrationDstRun(vm, incoming->uri, asyncJob, migParams, 0) < 0)
             goto stop;
     } else {
         /* Refresh state of devices from QEMU. During migration this happens
@@ -8426,6 +8443,7 @@ qemuProcessStart(virConnectPtr conn,
  * @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
+ * @migParams: Migration params to use on restore or NULL
  * @asyncJob: type of asynchronous job
  * @start_flags: flags to start QEMU process with
  * @reason: audit log reason
@@ -8452,6 +8470,7 @@ qemuProcessStartWithMemoryState(virConnectPtr conn,
                                 const char *path,
                                 virDomainMomentObj *snapshot,
                                 virQEMUSaveData *data,
+                                qemuMigrationParams *migParams,
                                 virDomainAsyncJob asyncJob,
                                 unsigned int start_flags,
                                 const char *reason,
@@ -8480,7 +8499,7 @@ qemuProcessStartWithMemoryState(virConnectPtr conn,
     /* The fd passed to qemuProcessIncomingDefNew is used to create the migration
      * URI, so it must be called after starting the decompression program.
      */
-    incoming = qemuProcessIncomingDefNew(priv->qemuCaps, NULL, "stdio", *fd, path);
+    incoming = qemuProcessIncomingDefNew(vm, NULL, "stdio", fd, path, data);
     if (!incoming)
         return -1;
 
@@ -8495,7 +8514,7 @@ qemuProcessStartWithMemoryState(virConnectPtr conn,
 
     if (qemuProcessStart(conn, driver, vm, cookie ? cookie->cpu : NULL,
                          asyncJob, incoming, *fd, path, snapshot,
-                         VIR_NETDEV_VPORT_PROFILE_OP_RESTORE,
+                         migParams, 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 a9e0a03a21..c51335ad7a 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -53,14 +53,17 @@ struct _qemuProcessIncomingDef {
     char *address; /* address where QEMU is supposed to listen */
     char *uri; /* used when calling migrate-incoming QMP command */
     int fd; /* for fd:N URI */
+    qemuFDPass *fdPassMigrate; /* for file:/dev/fdset/n,offset=x URI */
     const char *path; /* path associated with fd */
 };
 
-qemuProcessIncomingDef *qemuProcessIncomingDefNew(virQEMUCaps *qemuCaps,
-                                                    const char *listenAddress,
-                                                    const char *migrateFrom,
-                                                    int fd,
-                                                    const char *path);
+qemuProcessIncomingDef *qemuProcessIncomingDefNew(virDomainObj *vm,
+                                                  const char *listenAddress,
+                                                  const char *migrateFrom,
+                                                  int *fd,
+                                                  const char *path,
+                                                  virQEMUSaveData *data);
+
 void qemuProcessIncomingDefFree(qemuProcessIncomingDef *inc);
 
 int qemuProcessBeginJob(virDomainObj *vm,
@@ -87,6 +90,7 @@ int qemuProcessStart(virConnectPtr conn,
                      int stdin_fd,
                      const char *stdin_path,
                      virDomainMomentObj *snapshot,
+                     qemuMigrationParams *migParams,
                      virNetDevVPortProfileOp vmop,
                      unsigned int flags);
 
@@ -97,6 +101,7 @@ int qemuProcessStartWithMemoryState(virConnectPtr conn,
                                     const char *path,
                                     virDomainMomentObj *snapshot,
                                     virQEMUSaveData *data,
+                                    qemuMigrationParams *migParams,
                                     virDomainAsyncJob asyncJob,
                                     unsigned int start_flags,
                                     const char *reason,
diff --git a/src/qemu/qemu_saveimage.c b/src/qemu/qemu_saveimage.c
index 0ffbe03f24..3f20ffd58c 100644
--- a/src/qemu/qemu_saveimage.c
+++ b/src/qemu/qemu_saveimage.c
@@ -348,7 +348,8 @@ qemuSaveImageDecompressionStart(virQEMUSaveData *data,
     if (header->version != 2)
         return 0;
 
-    if (header->format == QEMU_SAVE_FORMAT_RAW)
+    if (header->format == QEMU_SAVE_FORMAT_RAW ||
+        header->format == QEMU_SAVE_FORMAT_SPARSE)
         return 0;
 
     if (!(cmd = qemuSaveImageGetCompressionCommand(header->format)))
@@ -697,6 +698,7 @@ qemuSaveImageGetMetadata(virQEMUDriver *driver,
  * @driver: qemu driver data
  * @path: path of the save image
  * @bypass_cache: bypass cache when opening the file
+ * @sparse: Image contains mapped-ram save format
  * @wrapperFd: returns the file wrapper structure
  * @open_write: open the file for writing (for updates)
  *
@@ -706,6 +708,7 @@ int
 qemuSaveImageOpen(virQEMUDriver *driver,
                   const char *path,
                   bool bypass_cache,
+                  bool sparse,
                   virFileWrapperFd **wrapperFd,
                   bool open_write)
 {
@@ -727,15 +730,18 @@ qemuSaveImageOpen(virQEMUDriver *driver,
     if ((fd = qemuDomainOpenFile(cfg, NULL, path, oflags, NULL)) < 0)
         return -1;
 
-    if (bypass_cache &&
-        !(*wrapperFd = virFileWrapperFdNew(&fd, path,
-                                           VIR_FILE_WRAPPER_BYPASS_CACHE)))
-        return -1;
+    /* If sparse, no need for the iohelper or positioning the file pointer. */
+    if (!sparse) {
+        if (bypass_cache &&
+            !(*wrapperFd = virFileWrapperFdNew(&fd, path,
+                                               VIR_FILE_WRAPPER_BYPASS_CACHE)))
+            return -1;
 
-    /* Read the header to position the file pointer for QEMU. Unfortunately we
-     * can't use lseek with virFileWrapperFD. */
-    if (qemuSaveImageReadHeader(fd, NULL) < 0)
-        return -1;
+        /* Read the header to position the file pointer for QEMU. Unfortunately we
+         * can't use lseek with virFileWrapperFD. */
+        if (qemuSaveImageReadHeader(fd, NULL) < 0)
+            return -1;
+    }
 
     ret = fd;
     fd = -1;
@@ -751,6 +757,7 @@ qemuSaveImageStartVM(virConnectPtr conn,
                      int *fd,
                      virQEMUSaveData *data,
                      const char *path,
+                     qemuMigrationParams *restoreParams,
                      bool start_paused,
                      bool reset_nvram,
                      virDomainAsyncJob asyncJob)
@@ -767,8 +774,8 @@ qemuSaveImageStartVM(virConnectPtr conn,
         start_flags |= VIR_QEMU_PROCESS_START_RESET_NVRAM;
 
     if (qemuProcessStartWithMemoryState(conn, driver, vm, fd, path, NULL, data,
-                                        asyncJob, start_flags, "restored",
-                                        &started) < 0) {
+                                        restoreParams, asyncJob, start_flags,
+                                        "restored", &started) < 0) {
         goto cleanup;
     }
 
diff --git a/src/qemu/qemu_saveimage.h b/src/qemu/qemu_saveimage.h
index 2b3d839e5b..b3992de126 100644
--- a/src/qemu/qemu_saveimage.h
+++ b/src/qemu/qemu_saveimage.h
@@ -84,6 +84,7 @@ qemuSaveImageStartVM(virConnectPtr conn,
                      int *fd,
                      virQEMUSaveData *data,
                      const char *path,
+                     qemuMigrationParams *restoreParams,
                      bool start_paused,
                      bool reset_nvram,
                      virDomainAsyncJob asyncJob)
@@ -106,6 +107,7 @@ int
 qemuSaveImageOpen(virQEMUDriver *driver,
                   const char *path,
                   bool bypass_cache,
+                  bool sparse,
                   virFileWrapperFd **wrapperFd,
                   bool open_write)
     ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4);
diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c
index 3088b28716..6f8ba5697b 100644
--- a/src/qemu/qemu_snapshot.c
+++ b/src/qemu/qemu_snapshot.c
@@ -2407,7 +2407,7 @@ qemuSnapshotRevertExternalPrepare(virDomainObj *vm,
             return -1;
 
         memdata->fd = qemuSaveImageOpen(driver, memdata->path,
-                                        false, NULL, false);
+                                        false, false, NULL, false);
         if (memdata->fd < 0)
             return -1;
 
@@ -2647,7 +2647,7 @@ qemuSnapshotRevertActive(virDomainObj *vm,
 
     if (qemuProcessStartWithMemoryState(snapshot->domain->conn, driver, vm,
                                         &memdata.fd, memdata.path, loadSnap,
-                                        memdata.data, VIR_ASYNC_JOB_SNAPSHOT,
+                                        memdata.data, NULL, VIR_ASYNC_JOB_SNAPSHOT,
                                         start_flags, "from-snapshot",
                                         &started) < 0) {
         if (started) {
@@ -2801,7 +2801,7 @@ qemuSnapshotRevertInactive(virDomainObj *vm,
 
         rc = qemuProcessStart(snapshot->domain->conn, driver, vm, NULL,
                               VIR_ASYNC_JOB_SNAPSHOT, NULL, -1, NULL, NULL,
-                              VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
+                              NULL, VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
                               start_flags);
         virDomainAuditStart(vm, "from-snapshot", rc >= 0);
         if (rc < 0) {
@@ -3277,7 +3277,7 @@ qemuSnapshotDeleteExternalPrepare(virDomainObj *vm,
 
         if (!virDomainObjIsActive(vm)) {
             if (qemuProcessStart(NULL, driver, vm, NULL, VIR_ASYNC_JOB_SNAPSHOT,
-                                 NULL, -1, NULL, NULL,
+                                 NULL, -1, NULL, NULL, NULL,
                                  VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
                                  VIR_QEMU_PROCESS_START_PAUSED) < 0) {
                 return -1;
-- 
2.43.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