mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-30 18:50:18 +03:00
qemu: Add support for mapped-ram on restore
Add support for the mapped-ram migration capability on restore. Signed-off-by: Jim Fehlig <jfehlig@suse.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
138737b203
commit
28a0621528
@ -1582,7 +1582,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);
|
||||
@ -5747,6 +5747,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 |
|
||||
@ -5759,9 +5761,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;
|
||||
|
||||
@ -5815,7 +5821,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);
|
||||
@ -5930,7 +5936,8 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path,
|
||||
if (qemuSaveImageGetMetadata(driver, NULL, path, &def, &data) < 0)
|
||||
goto cleanup;
|
||||
|
||||
fd = qemuSaveImageOpen(driver, path, false, NULL, true);
|
||||
fd = qemuSaveImageOpen(driver, path, false, false, NULL, false);
|
||||
|
||||
if (fd < 0)
|
||||
goto cleanup;
|
||||
|
||||
@ -6069,6 +6076,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) {
|
||||
@ -6086,7 +6095,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;
|
||||
|
||||
@ -6128,7 +6141,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:
|
||||
@ -6334,7 +6347,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) {
|
||||
|
@ -3115,9 +3115,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) {
|
||||
@ -3171,8 +3170,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);
|
||||
}
|
||||
|
||||
|
||||
@ -3312,7 +3312,7 @@ qemuMigrationDstPrepareActive(virQEMUDriver *driver,
|
||||
|
||||
if (!(incoming = qemuMigrationDstPrepare(vm, tunnel, protocol,
|
||||
listenAddress, port,
|
||||
dataFD[0])))
|
||||
&dataFD[0])))
|
||||
goto error;
|
||||
|
||||
qemuMigrationDstPrepareDiskSeclabels(vm, migrate_disks, flags);
|
||||
@ -3683,7 +3683,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)
|
||||
|
@ -4862,6 +4862,7 @@ qemuProcessIncomingDefFree(qemuProcessIncomingDef *inc)
|
||||
|
||||
g_free(inc->address);
|
||||
g_free(inc->uri);
|
||||
qemuFDPassFree(inc->fdPassMigrate);
|
||||
g_free(inc);
|
||||
}
|
||||
|
||||
@ -4875,26 +4876,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;
|
||||
@ -8005,8 +8018,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,
|
||||
@ -8425,6 +8441,7 @@ qemuProcessStart(virConnectPtr conn,
|
||||
int migrateFd,
|
||||
const char *migratePath,
|
||||
virDomainMomentObj *snapshot,
|
||||
qemuMigrationParams *migParams,
|
||||
virNetDevVPortProfileOp vmop,
|
||||
unsigned int flags)
|
||||
{
|
||||
@ -8478,7 +8495,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
|
||||
@ -8532,6 +8549,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
|
||||
@ -8558,6 +8576,7 @@ qemuProcessStartWithMemoryState(virConnectPtr conn,
|
||||
const char *path,
|
||||
virDomainMomentObj *snapshot,
|
||||
virQEMUSaveData *data,
|
||||
qemuMigrationParams *migParams,
|
||||
virDomainAsyncJob asyncJob,
|
||||
unsigned int start_flags,
|
||||
const char *reason,
|
||||
@ -8586,7 +8605,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;
|
||||
|
||||
@ -8601,7 +8620,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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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)))
|
||||
@ -656,6 +657,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)
|
||||
*
|
||||
@ -665,6 +667,7 @@ int
|
||||
qemuSaveImageOpen(virQEMUDriver *driver,
|
||||
const char *path,
|
||||
bool bypass_cache,
|
||||
bool sparse,
|
||||
virFileWrapperFd **wrapperFd,
|
||||
bool open_write)
|
||||
{
|
||||
@ -686,15 +689,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;
|
||||
@ -710,6 +716,7 @@ qemuSaveImageStartVM(virConnectPtr conn,
|
||||
int *fd,
|
||||
virQEMUSaveData *data,
|
||||
const char *path,
|
||||
qemuMigrationParams *restoreParams,
|
||||
bool start_paused,
|
||||
bool reset_nvram,
|
||||
virDomainAsyncJob asyncJob)
|
||||
@ -726,8 +733,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;
|
||||
}
|
||||
|
||||
|
@ -83,6 +83,7 @@ qemuSaveImageStartVM(virConnectPtr conn,
|
||||
int *fd,
|
||||
virQEMUSaveData *data,
|
||||
const char *path,
|
||||
qemuMigrationParams *restoreParams,
|
||||
bool start_paused,
|
||||
bool reset_nvram,
|
||||
virDomainAsyncJob asyncJob)
|
||||
@ -105,6 +106,7 @@ int
|
||||
qemuSaveImageOpen(virQEMUDriver *driver,
|
||||
const char *path,
|
||||
bool bypass_cache,
|
||||
bool sparse,
|
||||
virFileWrapperFd **wrapperFd,
|
||||
bool open_write)
|
||||
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4);
|
||||
|
@ -2430,7 +2430,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;
|
||||
|
||||
@ -2670,7 +2670,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) {
|
||||
@ -2824,7 +2824,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) {
|
||||
@ -3300,7 +3300,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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user