void migration_connect_outgoing(MigrationState *s, MigrationAddress *addr,
Error **errp)
{
+ g_autoptr(QIOChannel) ioc = NULL;
+
if (addr->transport == MIGRATION_ADDRESS_TYPE_SOCKET) {
SocketAddress *saddr = &addr->u.socket;
if (saddr->type == SOCKET_ADDRESS_TYPE_INET ||
saddr->type == SOCKET_ADDRESS_TYPE_UNIX ||
saddr->type == SOCKET_ADDRESS_TYPE_VSOCK) {
socket_connect_outgoing(s, saddr, errp);
+ /*
+ * async: after the socket is connected, calls
+ * migration_channel_connect_outgoing() directly.
+ */
+ return;
+
} else if (saddr->type == SOCKET_ADDRESS_TYPE_FD) {
- fd_connect_outgoing(s, saddr->u.fd.str, errp);
+ ioc = fd_connect_outgoing(s, saddr->u.fd.str, errp);
}
#ifdef CONFIG_RDMA
} else if (addr->transport == MIGRATION_ADDRESS_TYPE_RDMA) {
- rdma_connect_outgoing(s, &addr->u.rdma, errp);
+ ioc = rdma_connect_outgoing(s, &addr->u.rdma, errp);
#endif
} else if (addr->transport == MIGRATION_ADDRESS_TYPE_EXEC) {
- exec_connect_outgoing(s, addr->u.exec.args, errp);
+ ioc = exec_connect_outgoing(s, addr->u.exec.args, errp);
} else if (addr->transport == MIGRATION_ADDRESS_TYPE_FILE) {
- file_connect_outgoing(s, &addr->u.file, errp);
+ ioc = file_connect_outgoing(s, &addr->u.file, errp);
} else {
error_setg(errp, "uri is not a valid migration protocol");
}
+
+ if (ioc) {
+ migration_channel_connect_outgoing(s, ioc);
+ }
+
+ return;
}
void migration_connect_incoming(MigrationAddress *addr, Error **errp)
} else {
error_setg(errp, "unknown migration protocol");
}
+
+ /*
+ * async: the above routines all wait for the incoming connection
+ * and call back to migration_channel_process_incoming() to start
+ * the migration.
+ */
}
bool migration_has_main_and_multifd_channels(void)
}
#endif
-void exec_connect_outgoing(MigrationState *s, strList *command, Error **errp)
+QIOChannel *exec_connect_outgoing(MigrationState *s, strList *command,
+ Error **errp)
{
QIOChannel *ioc = NULL;
g_auto(GStrv) argv = strv_from_str_list(command);
trace_migration_exec_outgoing(new_command);
ioc = QIO_CHANNEL(qio_channel_command_new_spawn(args, O_RDWR, errp));
if (!ioc) {
- return;
+ return NULL;
}
qio_channel_set_name(ioc, "migration-exec-outgoing");
- migration_channel_connect_outgoing(s, ioc);
- object_unref(OBJECT(ioc));
+ return ioc;
}
static gboolean exec_accept_incoming_migration(QIOChannel *ioc,
#ifndef QEMU_MIGRATION_EXEC_H
#define QEMU_MIGRATION_EXEC_H
+#include "io/channel.h"
+
#ifdef WIN32
const char *exec_get_cmd_path(void);
#endif
void exec_connect_incoming(strList *host_port, Error **errp);
-void exec_connect_outgoing(MigrationState *s, strList *host_port, Error **errp);
+QIOChannel *exec_connect_outgoing(MigrationState *s, strList *host_port,
+ Error **errp);
#endif
return false;
}
-void fd_connect_outgoing(MigrationState *s, const char *fdname, Error **errp)
+QIOChannel *fd_connect_outgoing(MigrationState *s, const char *fdname,
+ Error **errp)
{
- QIOChannel *ioc;
+ QIOChannel *ioc = NULL;
int fd = monitor_get_fd(monitor_cur(), fdname, errp);
if (fd == -1) {
- return;
+ goto out;
}
if (!migration_fd_valid(fd)) {
error_setg(errp, "fd: migration to a file is not supported."
" Use file: instead.");
- return;
+ goto out;
}
trace_migration_fd_outgoing(fd);
ioc = qio_channel_new_fd(fd, errp);
if (!ioc) {
close(fd);
- return;
+ goto out;
}
qio_channel_set_name(ioc, "migration-fd-outgoing");
- migration_channel_connect_outgoing(s, ioc);
- object_unref(OBJECT(ioc));
+out:
+ return ioc;
}
static gboolean fd_accept_incoming_migration(QIOChannel *ioc,
#ifndef QEMU_MIGRATION_FD_H
#define QEMU_MIGRATION_FD_H
+
+#include "io/channel.h"
+
void fd_connect_incoming(const char *fdname, Error **errp);
-void fd_connect_outgoing(MigrationState *s, const char *fdname,
- Error **errp);
+QIOChannel *fd_connect_outgoing(MigrationState *s, const char *fdname,
+ Error **errp);
#endif
return ret;
}
-void file_connect_outgoing(MigrationState *s,
- FileMigrationArgs *file_args, Error **errp)
+QIOChannel *file_connect_outgoing(MigrationState *s,
+ FileMigrationArgs *file_args, Error **errp)
{
- g_autoptr(QIOChannelFile) fioc = NULL;
+ QIOChannelFile *fioc = NULL;
g_autofree char *filename = g_strdup(file_args->filename);
uint64_t offset = file_args->offset;
- QIOChannel *ioc;
+ QIOChannel *ioc = NULL;
trace_migration_file_outgoing(filename);
fioc = qio_channel_file_new_path(filename, O_CREAT | O_WRONLY, 0600, errp);
if (!fioc) {
- return;
+ goto out;
}
if (ftruncate(fioc->fd, offset)) {
error_setg_errno(errp, errno,
"failed to truncate migration file to offset %" PRIx64,
offset);
- return;
+ goto out;
}
outgoing_args.fname = g_strdup(filename);
ioc = QIO_CHANNEL(fioc);
if (offset && qio_channel_io_seek(ioc, offset, SEEK_SET, errp) < 0) {
- return;
+ ioc = NULL;
+ goto out;
}
qio_channel_set_name(ioc, "migration-file-outgoing");
- migration_channel_connect_outgoing(s, ioc);
+out:
+ return ioc;
}
static gboolean file_accept_incoming_migration(QIOChannel *ioc,
#define QEMU_MIGRATION_FILE_H
#include "qapi/qapi-types-migration.h"
+#include "io/channel.h"
#include "io/task.h"
#include "channel.h"
#include "multifd.h"
void file_connect_incoming(FileMigrationArgs *file_args, Error **errp);
-void file_connect_outgoing(MigrationState *s,
- FileMigrationArgs *file_args, Error **errp);
+QIOChannel *file_connect_outgoing(MigrationState *s,
+ FileMigrationArgs *file_args, Error **errp);
int file_parse_offset(char *filespec, uint64_t *offsetp, Error **errp);
void file_cleanup_outgoing_migration(void);
bool file_send_channel_create(gpointer opaque, Error **errp);
g_free(rdma);
}
-void rdma_connect_outgoing(void *opaque,
- InetSocketAddress *host_port, Error **errp)
+QIOChannel *rdma_connect_outgoing(void *opaque,
+ InetSocketAddress *host_port, Error **errp)
{
MigrationState *s = opaque;
RDMAContext *rdma_return_path = NULL;
/* Avoid ram_block_discard_disable(), cannot change during migration. */
if (ram_block_discard_is_required()) {
error_setg(errp, "RDMA: cannot disable RAM discard");
- return;
+ return NULL;
}
rdma = qemu_rdma_data_init(host_port, errp);
trace_rdma_connect_outgoing_after_rdma_connect();
s->rdma_migration = true;
- migration_outgoing_setup(rdma_new_output(rdma));
- migration_start_outgoing(s);
- return;
+ return rdma_new_output(rdma);
return_path_err:
qemu_rdma_cleanup(rdma);
err:
g_free(rdma);
g_free(rdma_return_path);
+ return NULL;
}
#include "system/memory.h"
-void rdma_connect_outgoing(void *opaque, InetSocketAddress *host_port,
- Error **errp);
+QIOChannel *rdma_connect_outgoing(void *opaque, InetSocketAddress *host_port,
+ Error **errp);
void rdma_connect_incoming(InetSocketAddress *host_port, Error **errp);