Re: [PATCH RFC 6/9] qemu: Add support for mapped-ram on save

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

 



On Thu, Jun 13, 2024 at 04:43:20PM -0600, Jim Fehlig via Devel wrote:
Signed-off-by: Jim Fehlig <jfehlig@xxxxxxxx>
---
src/qemu/qemu_driver.c    |   2 +-
src/qemu/qemu_migration.c |  79 ++++++++++++++++++++++++++++
src/qemu/qemu_migration.h |   7 +++
src/qemu/qemu_monitor.c   |  32 ++++++++++++
src/qemu/qemu_monitor.h   |   4 ++
src/qemu/qemu_saveimage.c | 105 ++++++++++++++++++++++++++++++--------
src/qemu/qemu_saveimage.h |   1 +
src/qemu/qemu_snapshot.c  |   2 +-
8 files changed, 208 insertions(+), 24 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index f9761242d2..34f37210d9 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2696,7 +2696,7 @@ qemuDomainSaveInternal(virQEMUDriver *driver,
    if (!(cookie = qemuDomainSaveCookieNew(vm)))
        goto endjob;

-    if (!(data = virQEMUSaveDataNew(driver, xml, cookie, was_running, compressed)))
+    if (!(data = virQEMUSaveDataNew(driver, vm, xml, cookie, was_running, compressed)))
        goto endjob;
    xml = NULL;

diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 1faab5dd23..3110ef2621 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -7072,6 +7072,85 @@ qemuMigrationSrcToFile(virQEMUDriver *driver, virDomainObj *vm,
}


+int
+qemuMigrationSrcToMappedFile(virQEMUDriver *driver, virDomainObj *vm,
+                             int fd,
+                             virDomainAsyncJob asyncJob)
+{
+    qemuDomainObjPrivate *priv = vm->privateData;
+    g_autoptr(qemuMigrationParams) saveParams = NULL;
+    unsigned long saveMigBandwidth = priv->migMaxBandwidth;
+    int rc;
+    int ret = -1;
+    virErrorPtr orig_err = NULL;
+
+    if (qemuMigrationSetDBusVMState(driver, vm) < 0)
+        return -1;
+
+    if (!(saveParams = qemuMigrationParamsForMappedSave()))
+        return -1;
+
+    /* Increase migration bandwidth to unlimited since target is a file.
+     * Failure to change migration speed is not fatal. */
+    if (qemuMigrationParamsSetULL(saveParams,
+                                  QEMU_MIGRATION_PARAM_MAX_BANDWIDTH,
+                                  QEMU_DOMAIN_MIG_BANDWIDTH_MAX * 1024 * 1024) < 0)
+        return -1;
+
+    if (qemuMigrationParamsApply(vm, asyncJob, saveParams, 0) < 0)
+        return -1;
+
+    priv->migMaxBandwidth = QEMU_DOMAIN_MIG_BANDWIDTH_MAX;
+
+    if (!virDomainObjIsActive(vm)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("guest unexpectedly quit"));
+        /* nothing to tear down */
+        return -1;
+    }
+
+    if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0)
+        goto cleanup;
+
+    rc = qemuMonitorMigrateToFdSet(vm, 0, fd);
+    qemuDomainObjExitMonitor(vm);
+    if (rc < 0)
+        goto cleanup;
+
+    rc = qemuMigrationSrcWaitForCompletion(vm, asyncJob, NULL, 0);
+
+    if (rc < 0) {
+        if (rc == -2) {
+            virErrorPreserveLast(&orig_err);
+            if (virDomainObjIsActive(vm))
+                qemuMigrationSrcCancel(vm, asyncJob, true);
+        }
+        goto cleanup;
+    }
+
+    qemuDomainEventEmitJobCompleted(driver, vm);
+    ret = 0;
+
+ cleanup:
+    if (ret < 0 && !orig_err)
+        virErrorPreserveLast(&orig_err);
+
+    /* Restore max migration bandwidth */
+    if (virDomainObjIsActive(vm)) {
+        if (qemuMigrationParamsSetULL(saveParams,
+                                      QEMU_MIGRATION_PARAM_MAX_BANDWIDTH,
+                                      saveMigBandwidth * 1024 * 1024) == 0)
+            ignore_value(qemuMigrationParamsApply(vm, asyncJob,
+                                                  saveParams, 0));
+        priv->migMaxBandwidth = saveMigBandwidth;
+    }
+
+    virErrorRestore(&orig_err);
+
+    return ret;
+}
+
+
/**
 * This function is supposed to be used only to while reconnecting to a domain
 * with an active migration job.
diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h
index ed62fd4a91..f845a0198b 100644
--- a/src/qemu/qemu_migration.h
+++ b/src/qemu/qemu_migration.h
@@ -241,6 +241,13 @@ qemuMigrationSrcToFile(virQEMUDriver *driver,
                       virDomainAsyncJob asyncJob)
    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;

+int
+qemuMigrationSrcToMappedFile(virQEMUDriver *driver,
+                             virDomainObj *vm,
+                             int fd,
+                             virDomainAsyncJob asyncJob)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;
+
int
qemuMigrationSrcCancelUnattended(virDomainObj *vm,
                                 virDomainJobObj *oldJob);
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 34e2ccab97..4c92bd740a 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -2237,6 +2237,38 @@ qemuMonitorMigrateToFd(qemuMonitor *mon,
}


+int
+qemuMonitorMigrateToFdSet(virDomainObj *vm,
+                          unsigned int flags,
+                          int fd)
+{
+    qemuDomainObjPrivate *priv = vm->privateData;
+    qemuMonitor *mon = priv->mon;
+    off_t offset;
+    g_autoptr(qemuFDPass) fdPassMigrate = NULL;
+    unsigned int setId;
+    g_autofree char *uri = NULL;
+
+    VIR_DEBUG("fd=%d flags=0x%x", fd, flags);
+
+    QEMU_CHECK_MONITOR(mon);
+
+    if ((offset = lseek(fd, 0, SEEK_CUR)) == -1)
+        return -1;

virReportSystemError() should probably be here or this could be
checked/gathered before entering the monitor

+
+    fdPassMigrate = qemuFDPassNew("migrate", priv);
+    qemuFDPassAddFD(fdPassMigrate, &fd, "-fd");
+    qemuFDPassTransferMonitor(fdPassMigrate, mon);

This function can fail (and set an error)

+
+    if (qemuFDPassGetId(fdPassMigrate, &setId) < 0)
+        return -1;

No error set here, but I see no way for it failing in this case.

+
+    uri = g_strdup_printf("file:/dev/fdset/%u,offset=%#lx", setId, offset);
+
+    return qemuMonitorJSONMigrate(mon, flags, uri);
+}
+
+
int
qemuMonitorMigrateToHost(qemuMonitor *mon,
                         unsigned int flags,
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 6e81945201..c477def138 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -843,6 +843,10 @@ int qemuMonitorMigrateToFd(qemuMonitor *mon,
                           unsigned int flags,
                           int fd);

+int qemuMonitorMigrateToFdSet(virDomainObj *vm,
+                              unsigned int flags,
+                              int fd);
+
int qemuMonitorMigrateToHost(qemuMonitor *mon,
                             unsigned int flags,
                             const char *protocol,
diff --git a/src/qemu/qemu_saveimage.c b/src/qemu/qemu_saveimage.c
index 30085dc7bc..8f28770086 100644
--- a/src/qemu/qemu_saveimage.c
+++ b/src/qemu/qemu_saveimage.c
@@ -96,6 +96,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(virQEMUSaveData, virQEMUSaveDataFree);
 */
virQEMUSaveData *
virQEMUSaveDataNew(virQEMUDriver *driver,
+                   virDomainObj *vm,
                   char *domXML,
                   qemuDomainSaveCookie *cookieObj,
                   bool running,
@@ -122,6 +123,10 @@ virQEMUSaveDataNew(virQEMUDriver *driver,
        goto error;
    }
    header->version = cfg->saveImageVersion;
+    /* Enable mapped-ram feature if available and save version >= 3 */
+    if (header->version >= QEMU_SAVE_VERSION &&

This should really be "3" and not the save version in case we increase
it, but to be readable without magic numbers and also more error proof,
there should be a mapping of feature->minVersion maybe?

+        qemuMigrationCapsGet(vm, QEMU_MIGRATION_CAP_MAPPED_RAM))
+        header->features |= QEMU_SAVE_FEATURE_MAPPED_RAM;

    header->was_running = running ? 1 : 0;
    header->compressed = compressed;

Also in case we add support for compressed mapped-ram save images this
might screw up later since you record the compression, but don't execute
it (as mentioned in the cover letter).

Attachment: signature.asc
Description: PGP signature


[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