@@ -1,4 +1,4 @@
-common-obj-y += migration.o socket.o fd.o exec.o
+common-obj-y += migration.o socket.o fd.o inline-fd.o exec.o
common-obj-y += tls.o channel.o savevm.o
common-obj-y += colo.o colo-failover.o
common-obj-y += vmstate.o vmstate-types.o page_cache.o
new file mode 100644
@@ -0,0 +1,89 @@
+/*
+ * QEMU live migration via generic fd passed with command
+ *
+ * Copyright Yandex, Inc. 2019
+ *
+ * Authors:
+ * Yury Kotov <yury-kotov@yandex-team.ru>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "channel.h"
+#include "inline-fd.h"
+#include "monitor/monitor.h"
+#include "io/channel-util.h"
+#include "trace.h"
+
+
+void inline_fd_start_outgoing_migration(MigrationState *s, Error **errp)
+{
+ QIOChannel *ioc;
+ int fd;
+
+ if (!cur_mon) {
+ error_setg(errp, "Monitor is disabled");
+ return;
+ }
+
+ fd = monitor_recv_fd(cur_mon, errp);
+ if (fd == -1) {
+ return;
+ }
+
+ trace_migration_inline_fd_outgoing(fd);
+ ioc = qio_channel_new_fd(fd, errp);
+ if (!ioc) {
+ close(fd);
+ return;
+ }
+
+ qio_channel_set_name(QIO_CHANNEL(ioc), "migration-infd-outgoing");
+ migration_channel_connect(s, ioc, NULL, NULL);
+ object_unref(OBJECT(ioc));
+}
+
+static gboolean inline_fd_accept_incoming_migration(QIOChannel *ioc,
+ GIOCondition condition,
+ gpointer opaque)
+{
+ migration_channel_process_incoming(ioc);
+ object_unref(OBJECT(ioc));
+ return G_SOURCE_REMOVE;
+}
+
+void inline_fd_start_incoming_migration(Error **errp)
+{
+ QIOChannel *ioc;
+ int fd;
+
+ if (!cur_mon) {
+ error_setg(errp, "Monitor is disabled");
+ return;
+ }
+
+ fd = monitor_recv_fd(cur_mon, errp);
+ if (fd == -1) {
+ return;
+ }
+
+ trace_migration_inline_fd_incoming(fd);
+ ioc = qio_channel_new_fd(fd, errp);
+ if (!ioc) {
+ close(fd);
+ return;
+ }
+
+ qio_channel_set_name(QIO_CHANNEL(ioc), "migration-infd-incoming");
+ qio_channel_add_watch(ioc,
+ G_IO_IN,
+ inline_fd_accept_incoming_migration,
+ NULL,
+ NULL);
+}
new file mode 100644
@@ -0,0 +1,22 @@
+/*
+ * QEMU live migration via generic fd passed with command
+ *
+ * Copyright Yandex, Inc. 2019
+ *
+ * Authors:
+ * Yury Kotov <yury-kotov@yandex-team.ru>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#ifndef QEMU_MIGRATION_INLINE_FD_H
+#define QEMU_MIGRATION_INLINE_FD_H
+
+void inline_fd_start_incoming_migration(Error **errp);
+void inline_fd_start_outgoing_migration(MigrationState *s, Error **errp);
+
+#endif
@@ -19,6 +19,7 @@
#include "migration/blocker.h"
#include "exec.h"
#include "fd.h"
+#include "inline-fd.h"
#include "socket.h"
#include "rdma.h"
#include "ram.h"
@@ -364,6 +365,13 @@ void qemu_start_incoming_migration(const char *uri, Error **errp)
unix_start_incoming_migration(p, errp);
} else if (strstart(uri, "fd:", &p)) {
fd_start_incoming_migration(p, errp);
+ } else if (strstart(uri, "inline-fd:", &p)) {
+ if (!*p) {
+ inline_fd_start_incoming_migration(errp);
+ } else {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "uri",
+ "an empty path for 'inline-fd:' protocol");
+ }
} else {
error_setg(errp, "unknown migration protocol: %s", uri);
}
@@ -1924,6 +1932,13 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
unix_start_outgoing_migration(s, p, &local_err);
} else if (strstart(uri, "fd:", &p)) {
fd_start_outgoing_migration(s, p, &local_err);
+ } else if (strstart(uri, "inline-fd:", &p)) {
+ if (!*p) {
+ inline_fd_start_outgoing_migration(s, &local_err);
+ } else {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "uri",
+ "an empty path for 'inline-fd:' protocol");
+ }
} else {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "uri",
"a valid migration protocol");
@@ -261,6 +261,10 @@ migration_exec_incoming(const char *cmd) "cmd=%s"
migration_fd_outgoing(int fd) "fd=%d"
migration_fd_incoming(int fd) "fd=%d"
+# inline-fd.c
+migration_inline_fd_outgoing(int fd) "fd=%d"
+migration_inline_fd_incoming(int fd) "fd=%d"
+
# socket.c
migration_socket_incoming_accepted(void) ""
migration_socket_outgoing_connected(const char *hostname) "hostname=%s"
Existing 'fd:' proto works with previously added fd by getfd or add-fd commands. If client doesn't want to work with this fd before or after migration then it's easier to send an fd with the migrate-* command. Also, client shouldn't maintain this fd. So, add 'inline-fd:' proto to work with sent fd. Usage: { 'execute': 'migrate', 'arguments': { 'uri': 'inline-fd:' } } { 'execute': 'migrate-incoming', 'arguments': { 'uri': 'inline-fd:' } } Signed-off-by: Yury Kotov <yury-kotov@yandex-team.ru> --- migration/Makefile.objs | 2 +- migration/inline-fd.c | 89 +++++++++++++++++++++++++++++++++++++++++ migration/inline-fd.h | 22 ++++++++++ migration/migration.c | 15 +++++++ migration/trace-events | 4 ++ 5 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 migration/inline-fd.c create mode 100644 migration/inline-fd.h