aboutsummaryrefslogtreecommitdiff
path: root/migration/migration.c
diff options
context:
space:
mode:
Diffstat (limited to 'migration/migration.c')
-rw-r--r--migration/migration.c80
1 files changed, 44 insertions, 36 deletions
diff --git a/migration/migration.c b/migration/migration.c
index 54060f749a..353f2728cf 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -109,7 +109,6 @@ MigrationState *migrate_get_current(void)
};
if (!once) {
- qemu_mutex_init(&current_migration.src_page_req_mutex);
current_migration.parameters.tls_creds = g_strdup("");
current_migration.parameters.tls_hostname = g_strdup("");
once = true;
@@ -349,6 +348,14 @@ static void process_incoming_migration_bh(void *opaque)
exit(EXIT_FAILURE);
}
+ /* If we get an error here, just don't restart the VM yet. */
+ blk_resume_after_migration(&local_err);
+ if (local_err) {
+ error_free(local_err);
+ local_err = NULL;
+ autostart = false;
+ }
+
/*
* This must happen after all error conditions are dealt with and
* we're sure the VM is going to be running on this host.
@@ -428,9 +435,6 @@ static void process_incoming_migration_co(void *opaque)
qemu_thread_join(&mis->colo_incoming_thread);
}
- qemu_fclose(f);
- free_xbzrle_decoded_buf();
-
if (ret < 0) {
migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE,
MIGRATION_STATUS_FAILED);
@@ -439,6 +443,9 @@ static void process_incoming_migration_co(void *opaque)
exit(EXIT_FAILURE);
}
+ qemu_fclose(f);
+ free_xbzrle_decoded_buf();
+
mis->bh = qemu_bh_new(process_incoming_migration_bh, mis);
qemu_bh_schedule(mis->bh);
}
@@ -643,16 +650,19 @@ static void populate_ram_info(MigrationInfo *info, MigrationState *s)
info->ram->transferred = ram_bytes_transferred();
info->ram->total = ram_bytes_total();
info->ram->duplicate = dup_mig_pages_transferred();
- info->ram->skipped = skipped_mig_pages_transferred();
+ /* legacy value. It is not used anymore */
+ info->ram->skipped = 0;
info->ram->normal = norm_mig_pages_transferred();
- info->ram->normal_bytes = norm_mig_bytes_transferred();
+ info->ram->normal_bytes = norm_mig_pages_transferred() *
+ qemu_target_page_size();
info->ram->mbps = s->mbps;
- info->ram->dirty_sync_count = s->dirty_sync_count;
- info->ram->postcopy_requests = s->postcopy_requests;
+ info->ram->dirty_sync_count = ram_dirty_sync_count();
+ info->ram->postcopy_requests = ram_postcopy_requests();
+ info->ram->page_size = qemu_target_page_size();
if (s->state != MIGRATION_STATUS_COMPLETED) {
info->ram->remaining = ram_bytes_remaining();
- info->ram->dirty_pages_rate = s->dirty_pages_rate;
+ info->ram->dirty_pages_rate = ram_dirty_pages_rate();
}
}
@@ -947,7 +957,7 @@ static void migrate_fd_cleanup(void *opaque)
qemu_bh_delete(s->cleanup_bh);
s->cleanup_bh = NULL;
- flush_page_queue(s);
+ migration_page_queue_free();
if (s->to_dst_file) {
trace_migrate_fd_cleanup();
@@ -1053,21 +1063,21 @@ bool migration_has_failed(MigrationState *s)
s->state == MIGRATION_STATUS_FAILED);
}
-bool migration_in_postcopy(MigrationState *s)
+bool migration_in_postcopy(void)
{
+ MigrationState *s = migrate_get_current();
+
return (s->state == MIGRATION_STATUS_POSTCOPY_ACTIVE);
}
bool migration_in_postcopy_after_devices(MigrationState *s)
{
- return migration_in_postcopy(s) && s->postcopy_after_devices;
+ return migration_in_postcopy() && s->postcopy_after_devices;
}
-bool migration_is_idle(MigrationState *s)
+bool migration_is_idle(void)
{
- if (!s) {
- s = migrate_get_current();
- }
+ MigrationState *s = migrate_get_current();
switch (s->state) {
case MIGRATION_STATUS_NONE:
@@ -1108,22 +1118,15 @@ MigrationState *migrate_init(const MigrationParams *params)
s->mbps = 0.0;
s->downtime = 0;
s->expected_downtime = 0;
- s->dirty_pages_rate = 0;
- s->dirty_bytes_rate = 0;
s->setup_time = 0;
- s->dirty_sync_count = 0;
s->start_postcopy = false;
s->postcopy_after_devices = false;
- s->postcopy_requests = 0;
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);
- QSIMPLEQ_INIT(&s->src_page_requests);
-
s->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
return s;
}
@@ -1139,7 +1142,7 @@ int migrate_add_blocker(Error *reason, Error **errp)
return -EACCES;
}
- if (migration_is_idle(NULL)) {
+ if (migration_is_idle()) {
migration_blockers = g_slist_prepend(migration_blockers, reason);
return 0;
}
@@ -1477,7 +1480,7 @@ static void migrate_handle_rp_req_pages(MigrationState *ms, const char* rbname,
return;
}
- if (ram_save_queue_pages(ms, rbname, start, len)) {
+ if (ram_save_queue_pages(rbname, start, len)) {
mark_source_rp_bad(ms);
}
}
@@ -1907,7 +1910,12 @@ static void *migration_thread(void *opaque)
int64_t initial_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
int64_t setup_start = qemu_clock_get_ms(QEMU_CLOCK_HOST);
int64_t initial_bytes = 0;
- int64_t max_size = 0;
+ /*
+ * The final stage happens when the remaining data is smaller than
+ * this threshold; it's calculated from the requested downtime and
+ * measured bandwidth
+ */
+ int64_t threshold_size = 0;
int64_t start_time = initial_time;
int64_t end_time;
bool old_vm_running = false;
@@ -1938,7 +1946,6 @@ static void *migration_thread(void *opaque)
qemu_savevm_state_begin(s->to_dst_file, &s->params);
s->setup_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) - setup_start;
- current_active_state = MIGRATION_STATUS_ACTIVE;
migrate_set_state(&s->state, MIGRATION_STATUS_SETUP,
MIGRATION_STATUS_ACTIVE);
@@ -1952,17 +1959,17 @@ static void *migration_thread(void *opaque)
if (!qemu_file_rate_limit(s->to_dst_file)) {
uint64_t pend_post, pend_nonpost;
- qemu_savevm_state_pending(s->to_dst_file, max_size, &pend_nonpost,
- &pend_post);
+ qemu_savevm_state_pending(s->to_dst_file, threshold_size,
+ &pend_nonpost, &pend_post);
pending_size = pend_nonpost + pend_post;
- trace_migrate_pending(pending_size, max_size,
+ trace_migrate_pending(pending_size, threshold_size,
pend_post, pend_nonpost);
- if (pending_size && pending_size >= max_size) {
+ if (pending_size && pending_size >= threshold_size) {
/* Still a significant amount to transfer */
if (migrate_postcopy_ram() &&
s->state != MIGRATION_STATUS_POSTCOPY_ACTIVE &&
- pend_nonpost <= max_size &&
+ pend_nonpost <= threshold_size &&
atomic_read(&s->start_postcopy)) {
if (!postcopy_start(s, &old_vm_running)) {
@@ -1994,17 +2001,18 @@ static void *migration_thread(void *opaque)
initial_bytes;
uint64_t time_spent = current_time - initial_time;
double bandwidth = (double)transferred_bytes / time_spent;
- max_size = bandwidth * s->parameters.downtime_limit;
+ threshold_size = bandwidth * s->parameters.downtime_limit;
s->mbps = (((double) transferred_bytes * 8.0) /
((double) time_spent / 1000.0)) / 1000.0 / 1000.0;
trace_migrate_transferred(transferred_bytes, time_spent,
- bandwidth, max_size);
+ bandwidth, threshold_size);
/* if we haven't sent anything, we don't want to recalculate
10000 is a small enough number for our purposes */
- if (s->dirty_bytes_rate && transferred_bytes > 10000) {
- s->expected_downtime = s->dirty_bytes_rate / bandwidth;
+ if (ram_dirty_pages_rate() && transferred_bytes > 10000) {
+ s->expected_downtime = ram_dirty_pages_rate() *
+ qemu_target_page_size() / bandwidth;
}
qemu_file_reset_rate_limit(s->to_dst_file);