When using the mapped-ram migration capability, direct IO is
enabled by setting the "direct-io" migration parameter to
"true" and passing QEMU an additional fd with O_DIRECT set.
Signed-off-by: Jim Fehlig <jfehlig(a)suse.com>
---
src/qemu/qemu_driver.c | 9 +++++----
src/qemu/qemu_migration.c | 32 ++++++++++++++++++++++++++------
src/qemu/qemu_migration.h | 1 +
src/qemu/qemu_migration_params.c | 11 ++++++++++-
src/qemu/qemu_migration_params.h | 3 ++-
src/qemu/qemu_monitor.c | 7 +++++--
src/qemu/qemu_monitor.h | 3 ++-
src/qemu/qemu_saveimage.c | 2 +-
8 files changed, 52 insertions(+), 16 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 6d0f52951c..0025bad6e7 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2691,7 +2691,7 @@ qemuDomainSaveInternal(virQEMUDriver *driver,
xml = NULL;
mappedRam = data->header.features & QEMU_SAVE_FEATURE_MAPPED_RAM;
- if (!(saveParams = qemuMigrationParamsForSave(mappedRam)))
+ if (!(saveParams = qemuMigrationParamsForSave(mappedRam, flags)))
goto endjob;
ret = qemuSaveImageCreate(driver, vm, path, data, compressor,
@@ -3143,7 +3143,7 @@ doCoreDump(virQEMUDriver *driver,
if (!(dump_params = qemuMigrationParamsNew()))
goto cleanup;
- if (qemuMigrationSrcToFile(driver, vm, &fd, compressor,
+ if (qemuMigrationSrcToFile(driver, vm, path, &fd, compressor,
dump_params, dump_flags, VIR_ASYNC_JOB_DUMP) < 0)
goto cleanup;
}
@@ -5789,7 +5789,7 @@ qemuDomainRestoreInternal(virConnectPtr conn,
goto cleanup;
mapped_ram = data->header.features & QEMU_SAVE_FEATURE_MAPPED_RAM;
- if (!(restoreParams = qemuMigrationParamsForSave(mapped_ram)))
+ if (!(restoreParams = qemuMigrationParamsForSave(mapped_ram, flags)))
return -1;
fd = qemuSaveImageOpen(driver, path,
@@ -6115,7 +6115,8 @@ qemuDomainObjRestore(virConnectPtr conn,
}
mapped_ram = data->header.features & QEMU_SAVE_FEATURE_MAPPED_RAM;
- if (!(restoreParams = qemuMigrationParamsForSave(mapped_ram)))
+ if (!(restoreParams = qemuMigrationParamsForSave(mapped_ram,
+ bypass_cache ?
VIR_DOMAIN_SAVE_BYPASS_CACHE : 0)))
return -1;
fd = qemuSaveImageOpen(driver, path, bypass_cache, mapped_ram, &wrapperFd,
false);
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 35d3e26908..daa42bcfe4 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -7012,17 +7012,36 @@ qemuMigrationSrcToLegacyFile(virQEMUDriver *driver,
static int
qemuMigrationSrcToMappedFile(virQEMUDriver *driver,
virDomainObj *vm,
+ const char *path,
int *fd,
unsigned int flags,
virDomainAsyncJob asyncJob)
{
+ g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
+ VIR_AUTOCLOSE directFd = -1;
+ int directFlag = 0;
+ bool needUnlink = false;
int ret;
- /* mapped-ram does not support directIO */
+ /* When using directio with mapped-ram, qemu needs two fds. One with
+ * O_DIRECT set writing the memory, and another without it set for
+ * writing small bits of unaligned state. */
if ((flags & VIR_DOMAIN_SAVE_BYPASS_CACHE)) {
- virReportError(VIR_ERR_OPERATION_FAILED, "%s",
- _("bypass cache unsupported by this system"));
- return -1;
+ directFlag = virFileDirectFdFlag();
+ if (directFlag < 0) {
+ virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+ _("bypass cache unsupported by this system"));
+ return -1;
+ }
+ directFd = virQEMUFileOpenAs(cfg->user, cfg->group, false, path,
+ O_WRONLY | directFlag, &needUnlink);
+
+ if (directFd < 0)
+ return -1;
+
+ if (qemuSecuritySetImageFDLabel(driver->securityManager, vm->def, directFd)
< 0)
+ return -1;
+
}
if (qemuSecuritySetImageFDLabel(driver->securityManager, vm->def, *fd) < 0)
@@ -7031,7 +7050,7 @@ qemuMigrationSrcToMappedFile(virQEMUDriver *driver,
if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0)
return -1;
- ret = qemuMonitorMigrateToFdSet(vm, 0, fd);
+ ret = qemuMonitorMigrateToFdSet(vm, 0, fd, &directFd);
qemuDomainObjExitMonitor(vm);
return ret;
}
@@ -7040,6 +7059,7 @@ qemuMigrationSrcToMappedFile(virQEMUDriver *driver,
/* Helper function called while vm is active. */
int
qemuMigrationSrcToFile(virQEMUDriver *driver, virDomainObj *vm,
+ const char *path,
int *fd,
virCommand *compressor,
qemuMigrationParams *migParams,
@@ -7077,7 +7097,7 @@ qemuMigrationSrcToFile(virQEMUDriver *driver, virDomainObj *vm,
if (migParams &&
qemuMigrationParamsCapEnabled(migParams, QEMU_MIGRATION_CAP_MAPPED_RAM)) {
- rc = qemuMigrationSrcToMappedFile(driver, vm, fd, flags, asyncJob);
+ rc = qemuMigrationSrcToMappedFile(driver, vm, path, fd, flags, asyncJob);
} else {
rc = qemuMigrationSrcToLegacyFile(driver, vm, *fd, compressor, asyncJob);
}
diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h
index 5529f2ee21..51d5b680bc 100644
--- a/src/qemu/qemu_migration.h
+++ b/src/qemu/qemu_migration.h
@@ -236,6 +236,7 @@ qemuMigrationSrcIsAllowed(virDomainObj *vm,
int
qemuMigrationSrcToFile(virQEMUDriver *driver,
virDomainObj *vm,
+ const char *path,
int *fd,
virCommand *compressor,
qemuMigrationParams *migParams,
diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c
index 503d6165b0..8f6003005c 100644
--- a/src/qemu/qemu_migration_params.c
+++ b/src/qemu/qemu_migration_params.c
@@ -129,6 +129,7 @@ VIR_ENUM_IMPL(qemuMigrationParam,
"multifd-compression",
"multifd-zlib-level",
"multifd-zstd-level",
+ "direct-io",
);
typedef struct _qemuMigrationParamsAlwaysOnItem qemuMigrationParamsAlwaysOnItem;
@@ -319,6 +320,9 @@ static const qemuMigrationParamInfoItem qemuMigrationParamInfo[] = {
[QEMU_MIGRATION_PARAM_MULTIFD_ZSTD_LEVEL] = {
.type = QEMU_MIGRATION_PARAM_TYPE_INT,
},
+ [QEMU_MIGRATION_PARAM_DIRECT_IO] = {
+ .type = QEMU_MIGRATION_PARAM_TYPE_BOOL,
+ },
};
G_STATIC_ASSERT(G_N_ELEMENTS(qemuMigrationParamInfo) == QEMU_MIGRATION_PARAM_LAST);
@@ -784,7 +788,7 @@ qemuMigrationParamsFromFlags(virTypedParameterPtr params,
qemuMigrationParams *
-qemuMigrationParamsForSave(bool mappedRam)
+qemuMigrationParamsForSave(bool mappedRam, unsigned int flags)
{
g_autoptr(qemuMigrationParams) saveParams = NULL;
@@ -798,6 +802,11 @@ qemuMigrationParamsForSave(bool mappedRam)
return NULL;
saveParams->params[QEMU_MIGRATION_PARAM_MULTIFD_CHANNELS].value.i = 1;
saveParams->params[QEMU_MIGRATION_PARAM_MULTIFD_CHANNELS].set = true;
+
+ if (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) {
+ saveParams->params[QEMU_MIGRATION_PARAM_DIRECT_IO].value.b = true;
+ saveParams->params[QEMU_MIGRATION_PARAM_DIRECT_IO].set = true;
+ }
}
return g_steal_pointer(&saveParams);
diff --git a/src/qemu/qemu_migration_params.h b/src/qemu/qemu_migration_params.h
index fe239d9a8f..9700469b5e 100644
--- a/src/qemu/qemu_migration_params.h
+++ b/src/qemu/qemu_migration_params.h
@@ -65,6 +65,7 @@ typedef enum {
QEMU_MIGRATION_PARAM_MULTIFD_COMPRESSION,
QEMU_MIGRATION_PARAM_MULTIFD_ZLIB_LEVEL,
QEMU_MIGRATION_PARAM_MULTIFD_ZSTD_LEVEL,
+ QEMU_MIGRATION_PARAM_DIRECT_IO,
QEMU_MIGRATION_PARAM_LAST
} qemuMigrationParam;
@@ -87,7 +88,7 @@ qemuMigrationParamsFromFlags(virTypedParameterPtr params,
qemuMigrationParty party);
qemuMigrationParams *
-qemuMigrationParamsForSave(bool mappedRam);
+qemuMigrationParamsForSave(bool mappedRam, unsigned int flags);
int
qemuMigrationParamsDump(qemuMigrationParams *migParams,
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 9a454a1d08..832ede639e 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -2240,7 +2240,8 @@ qemuMonitorMigrateToFd(qemuMonitor *mon,
int
qemuMonitorMigrateToFdSet(virDomainObj *vm,
unsigned int flags,
- int *fd)
+ int *fd,
+ int *directFd)
{
qemuDomainObjPrivate *priv = vm->privateData;
qemuMonitor *mon = priv->mon;
@@ -2250,7 +2251,7 @@ qemuMonitorMigrateToFdSet(virDomainObj *vm,
g_autofree char *uri = NULL;
int ret;
- VIR_DEBUG("fd=%d flags=0x%x", *fd, flags);
+ VIR_DEBUG("fd=%d directFd=%d flags=0x%x", *fd, *directFd, flags);
QEMU_CHECK_MONITOR(mon);
@@ -2262,6 +2263,8 @@ qemuMonitorMigrateToFdSet(virDomainObj *vm,
fdPassMigrate = qemuFDPassNew("migrate", priv);
qemuFDPassAddFD(fdPassMigrate, fd, "-buffered-fd");
+ if (*directFd != -1)
+ qemuFDPassAddFD(fdPassMigrate, directFd, "-directio-fd");
if (qemuFDPassTransferMonitor(fdPassMigrate, mon) < 0)
return -1;
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index ebacdf110e..63385e93f3 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -846,7 +846,8 @@ int qemuMonitorMigrateToFd(qemuMonitor *mon,
int qemuMonitorMigrateToFdSet(virDomainObj *vm,
unsigned int flags,
- int *fd);
+ int *fd,
+ int *directFd);
int qemuMonitorMigrateToHost(qemuMonitor *mon,
unsigned int flags,
diff --git a/src/qemu/qemu_saveimage.c b/src/qemu/qemu_saveimage.c
index b99e0de1ff..8ffd26d57a 100644
--- a/src/qemu/qemu_saveimage.c
+++ b/src/qemu/qemu_saveimage.c
@@ -450,7 +450,7 @@ qemuSaveImageCreate(virQEMUDriver *driver,
goto cleanup;
/* Perform the migration */
- if (qemuMigrationSrcToFile(driver, vm, &fd, compressor, saveParams, flags,
asyncJob) < 0)
+ if (qemuMigrationSrcToFile(driver, vm, path, &fd, compressor, saveParams, flags,
asyncJob) < 0)
goto cleanup;
/* Touch up file header to mark image complete. */
--
2.35.3