If we receive a file descriptor that points to a regular file, there's
nothing stopping us from doing multifd migration with mapped-ram to
that file.
Enable the fd: URI to work with multifd + mapped-ram.
Note that the fds passed into multifd are duplicated because we want
to avoid cross-thread effects when doing cleanup (i.e. close(fd)). The
original fd doesn't need to be duplicated because monitor_get_fd()
transfers ownership to the caller.
Signed-off-by: Fabiano Rosas <farosas@suse.de>
---
- dup() the fds that are passed to multifd.
- update the commit message
---
migration/fd.c | 44 +++++++++++++++++++++++++++++++++++++++++++
migration/fd.h | 2 ++
migration/file.c | 16 +++++++++++-----
migration/migration.c | 4 ++++
migration/multifd.c | 2 ++
5 files changed, 63 insertions(+), 5 deletions(-)
diff --git a/migration/fd.c b/migration/fd.c
index 0eb677dcae..d4ae72d132 100644
--- a/migration/fd.c
+++ b/migration/fd.c
@@ -15,18 +15,41 @@
*/
#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "channel.h"
#include "fd.h"
#include "migration.h"
#include "monitor/monitor.h"
+#include "io/channel-file.h"
#include "io/channel-util.h"
+#include "options.h"
#include "trace.h"
+static struct FdOutgoingArgs {
+ int fd;
+} outgoing_args;
+
+int fd_args_get_fd(void)
+{
+ return outgoing_args.fd;
+}
+
+void fd_cleanup_outgoing_migration(void)
+{
+ if (outgoing_args.fd > 0) {
+ close(outgoing_args.fd);
+ outgoing_args.fd = -1;
+ }
+}
+
void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **errp)
{
QIOChannel *ioc;
int fd = monitor_get_fd(monitor_cur(), fdname, errp);
+
+ outgoing_args.fd = -1;
+
if (fd == -1) {
return;
}
@@ -38,6 +61,8 @@ void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **
return;
}
+ outgoing_args.fd = fd;
+
qio_channel_set_name(ioc, "migration-fd-outgoing");
migration_channel_connect(s, ioc, NULL, NULL);
object_unref(OBJECT(ioc));
@@ -73,4 +98,23 @@ void fd_start_incoming_migration(const char *fdname, Error **errp)
fd_accept_incoming_migration,
NULL, NULL,
g_main_context_get_thread_default());
+
+ if (migrate_multifd()) {
+ int channels = migrate_multifd_channels();
+
+ while (channels--) {
+ ioc = QIO_CHANNEL(qio_channel_file_new_fd(dup(fd)));
+
+ if (QIO_CHANNEL_FILE(ioc)->fd == -1) {
+ error_setg(errp, "Failed to duplicate fd %d", fd);
+ return;
+ }
+
+ qio_channel_set_name(ioc, "migration-fd-incoming");
+ qio_channel_add_watch_full(ioc, G_IO_IN,
+ fd_accept_incoming_migration,
+ NULL, NULL,
+ g_main_context_get_thread_default());
+ }
+ }
}
diff --git a/migration/fd.h b/migration/fd.h
index b901bc014e..0c0a18d9e7 100644
--- a/migration/fd.h
+++ b/migration/fd.h
@@ -20,4 +20,6 @@ void fd_start_incoming_migration(const char *fdname, Error **errp);
void fd_start_outgoing_migration(MigrationState *s, const char *fdname,
Error **errp);
+void fd_cleanup_outgoing_migration(void);
+int fd_args_get_fd(void);
#endif
diff --git a/migration/file.c b/migration/file.c
index 44b73bf9e5..9a8cba2c3d 100644
--- a/migration/file.c
+++ b/migration/file.c
@@ -11,6 +11,7 @@
#include "qemu/error-report.h"
#include "qapi/error.h"
#include "channel.h"
+#include "fd.h"
#include "file.h"
#include "migration.h"
#include "io/channel-file.h"
@@ -53,15 +54,20 @@ bool file_send_channel_create(gpointer opaque, Error **errp)
{
QIOChannelFile *ioc;
int flags = O_WRONLY;
- bool ret = true;
+ bool ret = false;
+ int fd = fd_args_get_fd();
- ioc = qio_channel_file_new_path(outgoing_args.fname, flags, 0, errp);
- if (!ioc) {
- ret = false;
- goto out;
+ if (fd && fd != -1) {
+ ioc = qio_channel_file_new_fd(dup(fd));
+ } else {
+ ioc = qio_channel_file_new_path(outgoing_args.fname, flags, 0, errp);
+ if (!ioc) {
+ goto out;
+ }
}
multifd_channel_connect(opaque, QIO_CHANNEL(ioc));
+ ret = true;
out:
/*
diff --git a/migration/migration.c b/migration/migration.c
index 957d2890b7..0f1c044707 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -139,6 +139,10 @@ static bool transport_supports_multi_channels(MigrationAddress *addr)
if (addr->transport == MIGRATION_ADDRESS_TYPE_SOCKET) {
SocketAddress *saddr = &addr->u.socket;
+ if (saddr->type == SOCKET_ADDRESS_TYPE_FD) {
+ return migrate_mapped_ram();
+ }
+
return (saddr->type == SOCKET_ADDRESS_TYPE_INET ||
saddr->type == SOCKET_ADDRESS_TYPE_UNIX ||
saddr->type == SOCKET_ADDRESS_TYPE_VSOCK);
diff --git a/migration/multifd.c b/migration/multifd.c
index 7a3977fc34..e46e1f2bf3 100644
--- a/migration/multifd.c
+++ b/migration/multifd.c
@@ -17,6 +17,7 @@
#include "exec/ramblock.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
+#include "fd.h"
#include "file.h"
#include "migration.h"
#include "migration-stats.h"
@@ -731,6 +732,7 @@ static bool multifd_send_cleanup_channel(MultiFDSendParams *p, Error **errp)
static void multifd_send_cleanup_state(void)
{
file_cleanup_outgoing_migration();
+ fd_cleanup_outgoing_migration();
socket_cleanup_outgoing_migration();
qemu_sem_destroy(&multifd_send_state->channels_created);
qemu_sem_destroy(&multifd_send_state->channels_ready);
--
2.35.3