Signed-off-by: Jim Fehlig <jfehlig@xxxxxxxx> --- src/qemu/qemu_migration.c | 19 +++++++++++---- src/qemu/qemu_migration.h | 3 ++- src/qemu/qemu_process.c | 49 ++++++++++++++++++++++++++++----------- src/qemu/qemu_process.h | 13 +++++++---- src/qemu/qemu_saveimage.c | 26 ++++++++++++++------- 5 files changed, 76 insertions(+), 34 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 3110ef2621..b1d27e07e1 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -2281,13 +2281,23 @@ qemuMigrationDstGetURI(const char *migrateFrom, int qemuMigrationDstRun(virDomainObj *vm, const char *uri, - virDomainAsyncJob asyncJob) + virDomainAsyncJob asyncJob, + unsigned int flags) { qemuDomainObjPrivate *priv = vm->privateData; int rv; VIR_DEBUG("Setting up incoming migration with URI %s", uri); + if (flags & VIR_QEMU_PROCESS_START_MAPPED_RAM) { + g_autoptr(qemuMigrationParams) migParams = NULL; + + if (!(migParams = qemuMigrationParamsForMappedSave())) + return -1; + + qemuMigrationParamsApply(vm, asyncJob, migParams, 0); + } + if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0) return -1; @@ -2945,7 +2955,6 @@ qemuMigrationDstPrepare(virDomainObj *vm, unsigned short port, int fd) { - qemuDomainObjPrivate *priv = vm->privateData; g_autofree char *migrateFrom = NULL; if (tunnel) { @@ -2999,8 +3008,8 @@ 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, 0); } @@ -3238,7 +3247,7 @@ qemuMigrationDstPrepareActive(virQEMUDriver *driver, } if (qemuMigrationDstRun(vm, incoming->uri, - VIR_ASYNC_JOB_MIGRATION_IN) < 0) + VIR_ASYNC_JOB_MIGRATION_IN, 0) < 0) goto error; if (qemuProcessFinishStartup(driver, vm, VIR_ASYNC_JOB_MIGRATION_IN, diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h index f845a0198b..864f3280e5 100644 --- a/src/qemu/qemu_migration.h +++ b/src/qemu/qemu_migration.h @@ -286,7 +286,8 @@ qemuMigrationDstGetURI(const char *migrateFrom, int qemuMigrationDstRun(virDomainObj *vm, const char *uri, - virDomainAsyncJob asyncJob); + virDomainAsyncJob asyncJob, + unsigned int flags); void qemuMigrationSrcPostcopyFailed(virDomainObj *vm); diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 7ef7040a85..f700390a8c 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4684,28 +4684,43 @@ 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) + const char *path, + unsigned int flags) { + 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 (!inc->uri) - goto error; - inc->fd = fd; inc->path = path; + if (flags & VIR_QEMU_PROCESS_START_MAPPED_RAM) { + unsigned int fdsetId; + off_t offset; + + if ((offset = lseek(fd, 0, SEEK_CUR)) == -1) + offset = 0; + + inc->fdPassMigrate = qemuFDPassNew("migrate", priv); + qemuFDPassAddFD(inc->fdPassMigrate, &fd, "-fd"); + qemuFDPassGetId(inc->fdPassMigrate, &fdsetId); + inc->uri = g_strdup_printf("file:/dev/fdset/%u,offset=%#lx", fdsetId, offset); + } else { + inc->uri = qemuMigrationDstGetURI(migrateFrom, fd); + } + + if (!inc->uri) + goto error; + return inc; error: @@ -7667,7 +7682,8 @@ qemuProcessLaunch(virConnectPtr conn, VIR_QEMU_PROCESS_START_AUTODESTROY | VIR_QEMU_PROCESS_START_NEW | VIR_QEMU_PROCESS_START_GEN_VMID | - VIR_QEMU_PROCESS_START_RESET_NVRAM, -1); + VIR_QEMU_PROCESS_START_RESET_NVRAM | + VIR_QEMU_PROCESS_START_MAPPED_RAM, -1); cfg = virQEMUDriverGetConfig(driver); @@ -7717,8 +7733,12 @@ qemuProcessLaunch(virConnectPtr conn, &nnicindexes, &nicindexes))) goto cleanup; - if (incoming && incoming->fd != -1) + if (incoming && incoming->fd != -1) { virCommandPassFD(cmd, incoming->fd, 0); + if (incoming->fdPassMigrate != NULL) { + qemuFDPassTransferCommand(incoming->fdPassMigrate, cmd); + } + } /* now that we know it is about to start call the hook if present */ if (qemuProcessStartHook(driver, vm, @@ -8153,7 +8173,8 @@ qemuProcessStart(virConnectPtr conn, VIR_QEMU_PROCESS_START_PAUSED | VIR_QEMU_PROCESS_START_AUTODESTROY | VIR_QEMU_PROCESS_START_GEN_VMID | - VIR_QEMU_PROCESS_START_RESET_NVRAM, cleanup); + VIR_QEMU_PROCESS_START_RESET_NVRAM | + VIR_QEMU_PROCESS_START_MAPPED_RAM, cleanup); if (!migrateFrom && !snapshot) flags |= VIR_QEMU_PROCESS_START_NEW; @@ -8163,8 +8184,8 @@ qemuProcessStart(virConnectPtr conn, goto cleanup; if (migrateFrom) { - incoming = qemuProcessIncomingDefNew(priv->qemuCaps, NULL, migrateFrom, - migrateFd, migratePath); + incoming = qemuProcessIncomingDefNew(vm, NULL, migrateFrom, + migrateFd, migratePath, flags); if (!incoming) goto stop; } @@ -8191,7 +8212,7 @@ qemuProcessStart(virConnectPtr conn, relabel = true; if (incoming) { - if (qemuMigrationDstRun(vm, incoming->uri, asyncJob) < 0) + if (qemuMigrationDstRun(vm, incoming->uri, asyncJob, flags) < 0) goto stop; } else { /* Refresh state of devices from QEMU. During migration this happens diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h index c1ea949215..a5212ee56e 100644 --- a/src/qemu/qemu_process.h +++ b/src/qemu/qemu_process.h @@ -54,14 +54,16 @@ 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, + unsigned int flags); void qemuProcessIncomingDefFree(qemuProcessIncomingDef *inc); int qemuProcessBeginJob(virDomainObj *vm, @@ -77,6 +79,7 @@ typedef enum { VIR_QEMU_PROCESS_START_NEW = 1 << 4, /* internal, new VM is starting */ VIR_QEMU_PROCESS_START_GEN_VMID = 1 << 5, /* Generate a new VMID */ VIR_QEMU_PROCESS_START_RESET_NVRAM = 1 << 6, /* Re-initialize NVRAM from template */ + VIR_QEMU_PROCESS_START_MAPPED_RAM = 1 << 7, /* Re-initialize NVRAM from template */ } qemuProcessStartFlags; int qemuProcessStart(virConnectPtr conn, diff --git a/src/qemu/qemu_saveimage.c b/src/qemu/qemu_saveimage.c index 8f28770086..1545c00472 100644 --- a/src/qemu/qemu_saveimage.c +++ b/src/qemu/qemu_saveimage.c @@ -628,6 +628,7 @@ qemuSaveImageOpen(virQEMUDriver *driver, int oflags = open_write ? O_RDWR : O_RDONLY; size_t xml_len; size_t cookie_len; + bool use_mapped_ram = false; if (bypass_cache) { int directFlag = virFileDirectFdFlag(); @@ -642,11 +643,6 @@ 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; - data = g_new0(virQEMUSaveData, 1); header = &data->header; @@ -708,10 +704,14 @@ qemuSaveImageOpen(virQEMUDriver *driver, return -1; } - if (header->features && header->features != QEMU_SAVE_FEATURE_MAPPED_RAM) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("image contains unsupported features)")); - return -1; + if (header->features) { + if (header->features == QEMU_SAVE_FEATURE_MAPPED_RAM) { + use_mapped_ram = true; + } else { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("image contains unsupported features)")); + return -1; + } } if (header->cookieOffset) @@ -739,6 +739,11 @@ qemuSaveImageOpen(virQEMUDriver *driver, } } + if (bypass_cache && !use_mapped_ram && + !(*wrapperFd = virFileWrapperFdNew(&fd, path, + VIR_FILE_WRAPPER_BYPASS_CACHE))) + return -1; + /* Create a domain from this XML */ if (!(def = virDomainDefParseString(data->xml, driver->xmlopt, qemuCaps, VIR_DOMAIN_DEF_PARSE_INACTIVE | @@ -777,6 +782,9 @@ qemuSaveImageStartVM(virConnectPtr conn, if (reset_nvram) start_flags |= VIR_QEMU_PROCESS_START_RESET_NVRAM; + 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, asyncJob, start_flags, "restored", &started) < 0) { -- 2.44.0