Signed-off-by: Fabiano Rosas <faro...@suse.de> --- migration/file.c | 18 +++++++++++++++++- migration/migration.c | 24 ++++++++++++++++++++++++ migration/options.h | 1 + util/osdep.c | 9 +++++++++ 4 files changed, 51 insertions(+), 1 deletion(-)
diff --git a/migration/file.c b/migration/file.c index 27ccfc6a1d..f1c7615fb6 100644 --- a/migration/file.c +++ b/migration/file.c @@ -57,10 +57,26 @@ int file_send_channel_destroy(QIOChannel *ioc) bool file_send_channel_create(gpointer opaque, Error **errp) { - QIOChannelFile *ioc; + QIOChannelFile *ioc = NULL; int flags = O_WRONLY; int fd = fd_args_get_fd(); + if (migrate_direct_io()) { +#ifdef O_DIRECT + /* + * 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; +#else + error_setg(errp, "System does not support O_DIRECT"); + error_append_hint(errp, + "Try disabling direct-io migration capability\n"); + return false; +#endif + } + if (fd && fd != -1) { ioc = qio_channel_file_new_fd(fd); } else { diff --git a/migration/migration.c b/migration/migration.c index ce7e6f5065..ecc07c4847 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -153,6 +153,16 @@ static bool migration_needs_seekable_channel(void) return migrate_fixed_ram(); } +static bool migration_needs_multiple_fds(void) +{ + /* + * When doing direct-io, multifd requires two different, + * non-duplicated file descriptors so we can use one of them for + * unaligned IO. + */ + return migrate_multifd() && migrate_direct_io(); +} + static bool transport_supports_seeking(MigrationAddress *addr) { if (addr->transport == MIGRATION_ADDRESS_TYPE_FILE) { @@ -171,6 +181,12 @@ static bool transport_supports_seeking(MigrationAddress *addr) return false; } +static bool transport_supports_multiple_fds(MigrationAddress *addr) +{ + /* file: works because QEMU can open it multiple times */ + return addr->transport == MIGRATION_ADDRESS_TYPE_FILE; +} + static bool migration_channels_and_transport_compatible(MigrationAddress *addr, Error **errp) @@ -187,6 +203,14 @@ migration_channels_and_transport_compatible(MigrationAddress *addr, return false; } + if (migration_needs_multiple_fds() && + !transport_supports_multiple_fds(addr)) { + error_setg(errp, + "Migration with direct-io is incompatible with the fd: URI," + " use file: instead"); + return false; + } + return true; } diff --git a/migration/options.h b/migration/options.h index 8680a10b79..39cbc171f7 100644 --- a/migration/options.h +++ b/migration/options.h @@ -79,6 +79,7 @@ uint8_t migrate_cpu_throttle_increment(void); uint8_t migrate_cpu_throttle_initial(void); bool migrate_cpu_throttle_tailslow(void); int migrate_decompress_threads(void); +bool migrate_direct_io(void); uint64_t migrate_downtime_limit(void); uint8_t migrate_max_cpu_throttle(void); uint64_t migrate_max_bandwidth(void); 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