aboutsummaryrefslogtreecommitdiff
path: root/migration/migration.c
diff options
context:
space:
mode:
Diffstat (limited to 'migration/migration.c')
-rw-r--r--migration/migration.c157
1 files changed, 107 insertions, 50 deletions
diff --git a/migration/migration.c b/migration/migration.c
index f5327e8c0a..7ecbadee6f 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -34,6 +34,8 @@
#include "qom/cpu.h"
#include "exec/memory.h"
#include "exec/address-spaces.h"
+#include "io/channel-buffer.h"
+#include "io/channel-tls.h"
#define MAX_THROTTLE (32 << 20) /* Migration transfer speed throttling */
@@ -81,16 +83,13 @@ MigrationState *migrate_get_current(void)
.bandwidth_limit = MAX_THROTTLE,
.xbzrle_cache_size = DEFAULT_MIGRATE_CACHE_SIZE,
.mbps = -1,
- .parameters[MIGRATION_PARAMETER_COMPRESS_LEVEL] =
- DEFAULT_MIGRATE_COMPRESS_LEVEL,
- .parameters[MIGRATION_PARAMETER_COMPRESS_THREADS] =
- DEFAULT_MIGRATE_COMPRESS_THREAD_COUNT,
- .parameters[MIGRATION_PARAMETER_DECOMPRESS_THREADS] =
- DEFAULT_MIGRATE_DECOMPRESS_THREAD_COUNT,
- .parameters[MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL] =
- DEFAULT_MIGRATE_CPU_THROTTLE_INITIAL,
- .parameters[MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT] =
- DEFAULT_MIGRATE_CPU_THROTTLE_INCREMENT,
+ .parameters = {
+ .compress_level = DEFAULT_MIGRATE_COMPRESS_LEVEL,
+ .compress_threads = DEFAULT_MIGRATE_COMPRESS_THREAD_COUNT,
+ .decompress_threads = DEFAULT_MIGRATE_DECOMPRESS_THREAD_COUNT,
+ .cpu_throttle_initial = DEFAULT_MIGRATE_CPU_THROTTLE_INITIAL,
+ .cpu_throttle_increment = DEFAULT_MIGRATE_CPU_THROTTLE_INCREMENT,
+ },
};
if (!once) {
@@ -310,14 +309,12 @@ void qemu_start_incoming_migration(const char *uri, Error **errp)
} else if (strstart(uri, "rdma:", &p)) {
rdma_start_incoming_migration(p, errp);
#endif
-#if !defined(WIN32)
} else if (strstart(uri, "exec:", &p)) {
exec_start_incoming_migration(p, errp);
} else if (strstart(uri, "unix:", &p)) {
unix_start_incoming_migration(p, errp);
} else if (strstart(uri, "fd:", &p)) {
fd_start_incoming_migration(p, errp);
-#endif
} else {
error_setg(errp, "unknown migration protocol: %s", uri);
}
@@ -422,14 +419,60 @@ static void process_incoming_migration_co(void *opaque)
void process_incoming_migration(QEMUFile *f)
{
Coroutine *co = qemu_coroutine_create(process_incoming_migration_co);
- int fd = qemu_get_fd(f);
- assert(fd != -1);
migrate_decompress_threads_create();
- qemu_set_nonblock(fd);
+ qemu_file_set_blocking(f, false);
qemu_coroutine_enter(co, f);
}
+
+void migration_set_incoming_channel(MigrationState *s,
+ QIOChannel *ioc)
+{
+ trace_migration_set_incoming_channel(
+ ioc, object_get_typename(OBJECT(ioc)));
+
+ if (s->parameters.tls_creds &&
+ !object_dynamic_cast(OBJECT(ioc),
+ TYPE_QIO_CHANNEL_TLS)) {
+ Error *local_err = NULL;
+ migration_tls_set_incoming_channel(s, ioc, &local_err);
+ if (local_err) {
+ error_report_err(local_err);
+ }
+ } else {
+ QEMUFile *f = qemu_fopen_channel_input(ioc);
+ process_incoming_migration(f);
+ }
+}
+
+
+void migration_set_outgoing_channel(MigrationState *s,
+ QIOChannel *ioc,
+ const char *hostname)
+{
+ trace_migration_set_outgoing_channel(
+ ioc, object_get_typename(OBJECT(ioc)), hostname);
+
+ if (s->parameters.tls_creds &&
+ !object_dynamic_cast(OBJECT(ioc),
+ TYPE_QIO_CHANNEL_TLS)) {
+ Error *local_err = NULL;
+ migration_tls_set_outgoing_channel(s, ioc, hostname, &local_err);
+ if (local_err) {
+ migrate_fd_error(s, local_err);
+ error_free(local_err);
+ }
+ } else {
+ QEMUFile *f = qemu_fopen_channel_output(ioc);
+
+ s->to_dst_file = f;
+
+ migrate_fd_connect(s);
+ }
+}
+
+
/*
* Send a message on the return channel back to the source
* of the migration.
@@ -516,15 +559,13 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp)
MigrationState *s = migrate_get_current();
params = g_malloc0(sizeof(*params));
- params->compress_level = s->parameters[MIGRATION_PARAMETER_COMPRESS_LEVEL];
- params->compress_threads =
- s->parameters[MIGRATION_PARAMETER_COMPRESS_THREADS];
- params->decompress_threads =
- s->parameters[MIGRATION_PARAMETER_DECOMPRESS_THREADS];
- params->cpu_throttle_initial =
- s->parameters[MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL];
- params->cpu_throttle_increment =
- s->parameters[MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT];
+ params->compress_level = s->parameters.compress_level;
+ params->compress_threads = s->parameters.compress_threads;
+ params->decompress_threads = s->parameters.decompress_threads;
+ params->cpu_throttle_initial = s->parameters.cpu_throttle_initial;
+ params->cpu_throttle_increment = s->parameters.cpu_throttle_increment;
+ params->tls_creds = g_strdup(s->parameters.tls_creds);
+ params->tls_hostname = g_strdup(s->parameters.tls_hostname);
return params;
}
@@ -672,6 +713,10 @@ MigrationInfo *qmp_query_migrate(Error **errp)
break;
case MIGRATION_STATUS_FAILED:
info->has_status = true;
+ if (s->error) {
+ info->has_error_desc = true;
+ info->error_desc = g_strdup(error_get_pretty(s->error));
+ }
break;
case MIGRATION_STATUS_CANCELLED:
info->has_status = true;
@@ -721,7 +766,12 @@ void qmp_migrate_set_parameters(bool has_compress_level,
bool has_cpu_throttle_initial,
int64_t cpu_throttle_initial,
bool has_cpu_throttle_increment,
- int64_t cpu_throttle_increment, Error **errp)
+ int64_t cpu_throttle_increment,
+ bool has_tls_creds,
+ const char *tls_creds,
+ bool has_tls_hostname,
+ const char *tls_hostname,
+ Error **errp)
{
MigrationState *s = migrate_get_current();
@@ -758,26 +808,31 @@ void qmp_migrate_set_parameters(bool has_compress_level,
}
if (has_compress_level) {
- s->parameters[MIGRATION_PARAMETER_COMPRESS_LEVEL] = compress_level;
+ s->parameters.compress_level = compress_level;
}
if (has_compress_threads) {
- s->parameters[MIGRATION_PARAMETER_COMPRESS_THREADS] = compress_threads;
+ s->parameters.compress_threads = compress_threads;
}
if (has_decompress_threads) {
- s->parameters[MIGRATION_PARAMETER_DECOMPRESS_THREADS] =
- decompress_threads;
+ s->parameters.decompress_threads = decompress_threads;
}
if (has_cpu_throttle_initial) {
- s->parameters[MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL] =
- cpu_throttle_initial;
+ s->parameters.cpu_throttle_initial = cpu_throttle_initial;
}
-
if (has_cpu_throttle_increment) {
- s->parameters[MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT] =
- cpu_throttle_increment;
+ s->parameters.cpu_throttle_increment = cpu_throttle_increment;
+ }
+ if (has_tls_creds) {
+ g_free(s->parameters.tls_creds);
+ s->parameters.tls_creds = g_strdup(tls_creds);
+ }
+ if (has_tls_hostname) {
+ g_free(s->parameters.tls_hostname);
+ s->parameters.tls_hostname = g_strdup(tls_hostname);
}
}
+
void qmp_migrate_start_postcopy(Error **errp)
{
MigrationState *s = migrate_get_current();
@@ -844,12 +899,15 @@ static void migrate_fd_cleanup(void *opaque)
notifier_list_notify(&migration_state_notifiers, s);
}
-void migrate_fd_error(MigrationState *s)
+void migrate_fd_error(MigrationState *s, const Error *error)
{
- trace_migrate_fd_error();
+ trace_migrate_fd_error(error ? error_get_pretty(error) : "");
assert(s->to_dst_file == NULL);
migrate_set_state(&s->state, MIGRATION_STATUS_SETUP,
MIGRATION_STATUS_FAILED);
+ if (!s->error) {
+ s->error = error_copy(error);
+ }
notifier_list_notify(&migration_state_notifiers, s);
}
@@ -948,6 +1006,8 @@ MigrationState *migrate_init(const MigrationParams *params)
s->postcopy_after_devices = false;
s->migration_thread_running = false;
s->last_req_rb = NULL;
+ error_free(s->error);
+ s->error = NULL;
migrate_set_state(&s->state, MIGRATION_STATUS_NONE, MIGRATION_STATUS_SETUP);
@@ -1040,14 +1100,12 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
} else if (strstart(uri, "rdma:", &p)) {
rdma_start_outgoing_migration(s, p, &local_err);
#endif
-#if !defined(WIN32)
} else if (strstart(uri, "exec:", &p)) {
exec_start_outgoing_migration(s, p, &local_err);
} else if (strstart(uri, "unix:", &p)) {
unix_start_outgoing_migration(s, p, &local_err);
} else if (strstart(uri, "fd:", &p)) {
fd_start_outgoing_migration(s, p, &local_err);
-#endif
} else {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "uri",
"a valid migration protocol");
@@ -1057,7 +1115,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
}
if (local_err) {
- migrate_fd_error(s);
+ migrate_fd_error(s, local_err);
error_propagate(errp, local_err);
return;
}
@@ -1170,7 +1228,7 @@ int migrate_compress_level(void)
s = migrate_get_current();
- return s->parameters[MIGRATION_PARAMETER_COMPRESS_LEVEL];
+ return s->parameters.compress_level;
}
int migrate_compress_threads(void)
@@ -1179,7 +1237,7 @@ int migrate_compress_threads(void)
s = migrate_get_current();
- return s->parameters[MIGRATION_PARAMETER_COMPRESS_THREADS];
+ return s->parameters.compress_threads;
}
int migrate_decompress_threads(void)
@@ -1188,7 +1246,7 @@ int migrate_decompress_threads(void)
s = migrate_get_current();
- return s->parameters[MIGRATION_PARAMETER_DECOMPRESS_THREADS];
+ return s->parameters.decompress_threads;
}
bool migrate_use_events(void)
@@ -1429,7 +1487,8 @@ static int await_return_path_close_on_source(MigrationState *ms)
static int postcopy_start(MigrationState *ms, bool *old_vm_running)
{
int ret;
- const QEMUSizedBuffer *qsb;
+ QIOChannelBuffer *bioc;
+ QEMUFile *fb;
int64_t time_at_stop = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
migrate_set_state(&ms->state, MIGRATION_STATUS_ACTIVE,
MIGRATION_STATUS_POSTCOPY_ACTIVE);
@@ -1488,11 +1547,9 @@ static int postcopy_start(MigrationState *ms, bool *old_vm_running)
* So we wrap the device state up in a package with a length at the start;
* to do this we use a qemu_buf to hold the whole of the device state.
*/
- QEMUFile *fb = qemu_bufopen("w", NULL);
- if (!fb) {
- error_report("Failed to create buffered file");
- goto fail;
- }
+ bioc = qio_channel_buffer_new(4096);
+ fb = qemu_fopen_channel_output(QIO_CHANNEL(bioc));
+ object_unref(OBJECT(bioc));
/*
* Make sure the receiver can get incoming pages before we send the rest
@@ -1506,10 +1563,9 @@ static int postcopy_start(MigrationState *ms, bool *old_vm_running)
qemu_savevm_send_postcopy_run(fb);
/* <><> end of stuff going into the package */
- qsb = qemu_buf_get(fb);
/* Now send that blob */
- if (qemu_savevm_send_packaged(ms->to_dst_file, qsb)) {
+ if (qemu_savevm_send_packaged(ms->to_dst_file, bioc->data, bioc->usage)) {
goto fail_closefb;
}
qemu_fclose(fb);
@@ -1793,6 +1849,7 @@ void migrate_fd_connect(MigrationState *s)
s->expected_downtime = max_downtime/1000000;
s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s);
+ qemu_file_set_blocking(s->to_dst_file, true);
qemu_file_set_rate_limit(s->to_dst_file,
s->bandwidth_limit / XFER_LIMIT_RATIO);