diff mbox series

[v4,28/34] migration/multifd: Add direct-io support

Message ID 20240220224138.24759-29-farosas@suse.de (mailing list archive)
State New, archived
Headers show
Series migration: File based migration with multifd and fixed-ram | expand

Commit Message

Fabiano Rosas Feb. 20, 2024, 10:41 p.m. UTC
Signed-off-by: Fabiano Rosas <farosas@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 mbox series

Patch

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;