Add the direct-io migration parameter that tells the migration code to use O_DIRECT when opening the migration stream file whenever possible.
This is currently only used for the secondary channels of fixed-ram migration, which can guarantee that writes are page aligned. However the parameter could be made to affect other types of file-based migrations in the future. Signed-off-by: Fabiano Rosas <faro...@suse.de> --- include/qemu/osdep.h | 2 ++ migration/file.c | 13 +++++++++++-- migration/migration-hmp-cmds.c | 9 +++++++++ migration/migration.c | 32 ++++++++++++++++++++++++++++++++ migration/migration.h | 1 + qapi/migration.json | 17 ++++++++++++++--- util/osdep.c | 9 +++++++++ 7 files changed, 78 insertions(+), 5 deletions(-) diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index 9eff0be95b..19c1d5f999 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -570,6 +570,8 @@ int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive); bool qemu_has_ofd_lock(void); #endif +bool qemu_has_direct_io(void); + #if defined(__HAIKU__) && defined(__i386__) #define FMT_pid "%ld" #elif defined(WIN64) diff --git a/migration/file.c b/migration/file.c index 6f40894488..1a40da097d 100644 --- a/migration/file.c +++ b/migration/file.c @@ -43,9 +43,18 @@ void file_send_channel_create(QIOTaskFunc f, void *data) QIOChannelFile *ioc; QIOTask *task; Error *errp = NULL; + int flags = outgoing_args.flags; - ioc = qio_channel_file_new_path(outgoing_args.fname, - outgoing_args.flags, + if (migrate_use_direct_io() && qemu_has_direct_io()) { + /* + * Enable O_DIRECT for the secondary channels. These are used + * for sending ram pages and writes should be guaranteed to be + * aligned to at least page size. + */ + flags |= O_DIRECT; + } + + ioc = qio_channel_file_new_path(outgoing_args.fname, flags, outgoing_args.mode, &errp); if (!ioc) { file_migration_cancel(errp); diff --git a/migration/migration-hmp-cmds.c b/migration/migration-hmp-cmds.c index 72519ea99f..c9a8d84714 100644 --- a/migration/migration-hmp-cmds.c +++ b/migration/migration-hmp-cmds.c @@ -344,6 +344,11 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict) } } } + if (params->has_direct_io) { + monitor_printf(mon, "%s: %s\n", + MigrationParameter_str(MIGRATION_PARAMETER_DIRECT_IO), + params->direct_io ? "on" : "off"); + } } qapi_free_MigrationParameters(params); @@ -600,6 +605,10 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) error_setg(&err, "The block-bitmap-mapping parameter can only be set " "through QMP"); break; + case MIGRATION_PARAMETER_DIRECT_IO: + p->has_direct_io = true; + visit_type_bool(v, param, &p->direct_io, &err); + break; default: assert(0); } diff --git a/migration/migration.c b/migration/migration.c index 77d24a5114..65798171e4 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1022,6 +1022,11 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp) s->parameters.block_bitmap_mapping); } + if (s->parameters.has_direct_io) { + params->has_direct_io = true; + params->direct_io = s->parameters.direct_io; + } + return params; } @@ -1782,6 +1787,10 @@ static void migrate_params_test_apply(MigrateSetParameters *params, dest->has_block_bitmap_mapping = true; dest->block_bitmap_mapping = params->block_bitmap_mapping; } + + if (params->has_direct_io) { + dest->direct_io = params->direct_io; + } } static void migrate_params_apply(MigrateSetParameters *params, Error **errp) @@ -1904,6 +1913,10 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp) QAPI_CLONE(BitmapMigrationNodeAliasList, params->block_bitmap_mapping); } + + if (params->has_direct_io) { + s->parameters.direct_io = params->direct_io; + } } void qmp_migrate_set_parameters(MigrateSetParameters *params, Error **errp) @@ -2885,6 +2898,24 @@ bool migrate_postcopy_preempt(void) return s->enabled_capabilities[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]; } +bool migrate_use_direct_io(void) +{ + MigrationState *s; + + /* For now O_DIRECT is only supported with fixed-ram */ + if (!migrate_fixed_ram()) { + return false; + } + + s = migrate_get_current(); + + if (s->parameters.has_direct_io) { + return s->parameters.direct_io; + } + + return false; +} + /* migration thread support */ /* * Something bad happened to the RP stream, mark an error @@ -4666,6 +4697,7 @@ static void migration_instance_init(Object *obj) params->has_announce_max = true; params->has_announce_rounds = true; params->has_announce_step = true; + params->has_direct_io = qemu_has_direct_io(); qemu_sem_init(&ms->postcopy_pause_sem, 0); qemu_sem_init(&ms->postcopy_pause_rp_sem, 0); diff --git a/migration/migration.h b/migration/migration.h index 8459201958..e0c9c78570 100644 --- a/migration/migration.h +++ b/migration/migration.h @@ -422,6 +422,7 @@ bool migrate_ignore_shared(void); bool migrate_validate_uuid(void); int migrate_fixed_ram(void); bool migrate_multifd_use_packets(void); +bool migrate_use_direct_io(void); bool migrate_auto_converge(void); bool migrate_use_multifd(void); bool migrate_pause_before_switchover(void); diff --git a/qapi/migration.json b/qapi/migration.json index 22eea58ce3..2190d98ded 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -776,6 +776,9 @@ # block device name if there is one, and to their node name # otherwise. (Since 5.2) # +# @direct-io: Open migration files with O_DIRECT when possible. Not +# all migration transports support this. (since 8.1) +# # Features: # @unstable: Member @x-checkpoint-delay is experimental. # @@ -796,7 +799,7 @@ 'xbzrle-cache-size', 'max-postcopy-bandwidth', 'max-cpu-throttle', 'multifd-compression', 'multifd-zlib-level' ,'multifd-zstd-level', - 'block-bitmap-mapping' ] } + 'block-bitmap-mapping', 'direct-io' ] } ## # @MigrateSetParameters: @@ -941,6 +944,9 @@ # block device name if there is one, and to their node name # otherwise. (Since 5.2) # +# @direct-io: Open migration files with O_DIRECT when possible. Not +# all migration transports support this. (since 8.1) +# # Features: # @unstable: Member @x-checkpoint-delay is experimental. # @@ -976,7 +982,8 @@ '*multifd-compression': 'MultiFDCompression', '*multifd-zlib-level': 'uint8', '*multifd-zstd-level': 'uint8', - '*block-bitmap-mapping': [ 'BitmapMigrationNodeAlias' ] } } + '*block-bitmap-mapping': [ 'BitmapMigrationNodeAlias' ], + '*direct-io': 'bool' } } ## # @migrate-set-parameters: @@ -1141,6 +1148,9 @@ # block device name if there is one, and to their node name # otherwise. (Since 5.2) # +# @direct-io: Open migration files with O_DIRECT when possible. Not +# all migration transports support this. (since 8.1) +# # Features: # @unstable: Member @x-checkpoint-delay is experimental. # @@ -1174,7 +1184,8 @@ '*multifd-compression': 'MultiFDCompression', '*multifd-zlib-level': 'uint8', '*multifd-zstd-level': 'uint8', - '*block-bitmap-mapping': [ 'BitmapMigrationNodeAlias' ] } } + '*block-bitmap-mapping': [ 'BitmapMigrationNodeAlias' ], + '*direct-io': 'bool' } } ## # @query-migrate-parameters: diff --git a/util/osdep.c b/util/osdep.c index e996c4744a..d0227a60ab 100644 --- a/util/osdep.c +++ b/util/osdep.c @@ -277,6 +277,15 @@ int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive) } #endif +bool qemu_has_direct_io(void) +{ +#ifdef O_DIRECT + return true; +#else + return false; +#endif +} + static int qemu_open_cloexec(const char *name, int flags, mode_t mode) { int ret; -- 2.35.3