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 | 10 ++++++----
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, 53 insertions(+), 16 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index ad58ec92f1..803c7be3f7 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2700,7 +2700,8 @@ qemuDomainSaveInternal(virQEMUDriver *driver,
goto endjob;
xml = NULL;
- if (!(saveParams = qemuMigrationParamsForSave(format == QEMU_SAVE_FORMAT_SPARSE)))
+ if (!(saveParams = qemuMigrationParamsForSave(format == QEMU_SAVE_FORMAT_SPARSE,
+ flags)))
goto endjob;
ret = qemuSaveImageCreate(driver, vm, path, data, compressor,
@@ -3152,7 +3153,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;
}
@@ -5798,7 +5799,7 @@ qemuDomainRestoreInternal(virConnectPtr conn,
goto cleanup;
sparse = data->header.format == QEMU_SAVE_FORMAT_SPARSE;
- if (!(restoreParams = qemuMigrationParamsForSave(sparse)))
+ if (!(restoreParams = qemuMigrationParamsForSave(sparse, flags)))
goto cleanup;
fd = qemuSaveImageOpen(driver, path,
@@ -6124,7 +6125,8 @@ qemuDomainObjRestore(virConnectPtr conn,
}
sparse = data->header.format == QEMU_SAVE_FORMAT_SPARSE;
- if (!(restoreParams = qemuMigrationParamsForSave(sparse)))
+ if (!(restoreParams = qemuMigrationParamsForSave(sparse,
+ bypass_cache ?
VIR_DOMAIN_SAVE_BYPASS_CACHE : 0)))
return -1;
fd = qemuSaveImageOpen(driver, path, bypass_cache, sparse, &wrapperFd, false);
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 8af6d1d3e2..61a14dc9d6 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -7135,17 +7135,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)
@@ -7154,7 +7173,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;
}
@@ -7163,6 +7182,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,
@@ -7200,7 +7220,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 b1f894e501..13ce9d33f2 100644
--- a/src/qemu/qemu_migration.h
+++ b/src/qemu/qemu_migration.h
@@ -237,6 +237,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 0faeb6b0c1..79b47333f9 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 sparse)
+qemuMigrationParamsForSave(bool sparse, unsigned int flags)
{
g_autoptr(qemuMigrationParams) saveParams = NULL;
@@ -798,6 +802,11 @@ qemuMigrationParamsForSave(bool sparse)
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 bb24af4ef9..b326aa5bc1 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 sparse);
+qemuMigrationParamsForSave(bool sparse, unsigned int flags);
int
qemuMigrationParamsDump(qemuMigrationParams *migParams,
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index d88e1b1ecd..385d103ad3 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -2233,7 +2233,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;
@@ -2243,7 +2244,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);
@@ -2255,6 +2256,8 @@ qemuMonitorMigrateToFdSet(virDomainObj *vm,
fdPassMigrate = qemuFDPassNew("migrate", priv);
qemuFDPassAddFD(fdPassMigrate, fd, "-fd");
+ if (*directFd != -1)
+ qemuFDPassAddFD(fdPassMigrate, directFd, "-directio-fd");
qemuFDPassTransferMonitor(fdPassMigrate, mon);
if (qemuFDPassGetId(fdPassMigrate, &setId) < 0)
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 7f54203fe3..79dbe5fcd7 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -857,7 +857,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 3e89f88301..d417762749 100644
--- a/src/qemu/qemu_saveimage.c
+++ b/src/qemu/qemu_saveimage.c
@@ -417,7 +417,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.43.0