diff options
Diffstat (limited to 'migration')
-rw-r--r-- | migration/block.c | 4 | ||||
-rw-r--r-- | migration/migration.c | 374 | ||||
-rw-r--r-- | migration/migration.h | 22 | ||||
-rw-r--r-- | migration/ram.c | 3 | ||||
-rw-r--r-- | migration/rdma.c | 2 | ||||
-rw-r--r-- | migration/socket.c | 4 |
6 files changed, 241 insertions, 168 deletions
diff --git a/migration/block.c b/migration/block.c index e68e090c6f..1f03946797 100644 --- a/migration/block.c +++ b/migration/block.c @@ -631,7 +631,7 @@ static int flush_blks(QEMUFile *f) int ret = 0; DPRINTF("%s Enter submitted %d read_done %d transferred %d\n", - __FUNCTION__, block_mig_state.submitted, block_mig_state.read_done, + __func__, block_mig_state.submitted, block_mig_state.read_done, block_mig_state.transferred); blk_mig_lock(); @@ -658,7 +658,7 @@ static int flush_blks(QEMUFile *f) } blk_mig_unlock(); - DPRINTF("%s Exit submitted %d read_done %d transferred %d\n", __FUNCTION__, + DPRINTF("%s Exit submitted %d read_done %d transferred %d\n", __func__, block_mig_state.submitted, block_mig_state.read_done, block_mig_state.transferred); return ret; diff --git a/migration/migration.c b/migration/migration.c index 4de3b551fe..c99a4e62d7 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -132,6 +132,11 @@ void migration_object_init(void) } } +void migration_object_finalize(void) +{ + object_unref(OBJECT(current_migration)); +} + /* For outgoing */ MigrationState *migrate_get_current(void) { @@ -613,7 +618,7 @@ MigrationInfo *qmp_query_migrate(Error **errp) info->has_status = true; info->has_total_time = true; info->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) - - s->total_time; + - s->start_time; info->has_expected_downtime = true; info->expected_downtime = s->expected_downtime; info->has_setup_time = true; @@ -741,22 +746,20 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params, static bool migrate_params_check(MigrationParameters *params, Error **errp) { if (params->has_compress_level && - (params->compress_level < 0 || params->compress_level > 9)) { + (params->compress_level > 9)) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "compress_level", "is invalid, it should be in the range of 0 to 9"); return false; } - if (params->has_compress_threads && - (params->compress_threads < 1 || params->compress_threads > 255)) { + if (params->has_compress_threads && (params->compress_threads < 1)) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "compress_threads", "is invalid, it should be in the range of 1 to 255"); return false; } - if (params->has_decompress_threads && - (params->decompress_threads < 1 || params->decompress_threads > 255)) { + if (params->has_decompress_threads && (params->decompress_threads < 1)) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "decompress_threads", "is invalid, it should be in the range of 1 to 255"); @@ -781,38 +784,31 @@ static bool migrate_params_check(MigrationParameters *params, Error **errp) return false; } - if (params->has_max_bandwidth && - (params->max_bandwidth < 0 || params->max_bandwidth > SIZE_MAX)) { + if (params->has_max_bandwidth && (params->max_bandwidth > SIZE_MAX)) { error_setg(errp, "Parameter 'max_bandwidth' expects an integer in the" " range of 0 to %zu bytes/second", SIZE_MAX); return false; } if (params->has_downtime_limit && - (params->downtime_limit < 0 || - params->downtime_limit > MAX_MIGRATE_DOWNTIME)) { + (params->downtime_limit > MAX_MIGRATE_DOWNTIME)) { error_setg(errp, "Parameter 'downtime_limit' expects an integer in " "the range of 0 to %d milliseconds", MAX_MIGRATE_DOWNTIME); return false; } - if (params->has_x_checkpoint_delay && (params->x_checkpoint_delay < 0)) { - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, - "x_checkpoint_delay", - "is invalid, it should be positive"); - return false; - } - if (params->has_x_multifd_channels && - (params->x_multifd_channels < 1 || params->x_multifd_channels > 255)) { + /* x_checkpoint_delay is now always positive */ + + if (params->has_x_multifd_channels && (params->x_multifd_channels < 1)) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "multifd_channels", "is invalid, it should be in the range of 1 to 255"); return false; } if (params->has_x_multifd_page_count && - (params->x_multifd_page_count < 1 || - params->x_multifd_page_count > 10000)) { + (params->x_multifd_page_count < 1 || + params->x_multifd_page_count > 10000)) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "multifd_page_count", "is invalid, it should be in the range of 1 to 10000"); @@ -1077,6 +1073,8 @@ static void migrate_fd_cleanup(void *opaque) qemu_bh_delete(s->cleanup_bh); s->cleanup_bh = NULL; + qemu_savevm_state_cleanup(); + if (s->to_dst_file) { Error *local_err = NULL; @@ -1127,8 +1125,6 @@ void migrate_fd_error(MigrationState *s, const Error *error) migrate_set_state(&s->state, MIGRATION_STATUS_SETUP, MIGRATION_STATUS_FAILED); migrate_set_error(s, error); - notifier_list_notify(&migration_state_notifiers, s); - block_cleanup_parameters(s); } static void migrate_fd_cancel(MigrationState *s) @@ -1174,7 +1170,6 @@ static void migrate_fd_cancel(MigrationState *s) s->block_inactive = false; } } - block_cleanup_parameters(s); } void add_migration_state_change_notifier(Notifier *notify) @@ -1268,7 +1263,11 @@ MigrationState *migrate_init(void) migrate_set_state(&s->state, MIGRATION_STATUS_NONE, MIGRATION_STATUS_SETUP); - s->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); + s->start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); + s->total_time = 0; + s->vm_was_running = false; + s->iteration_initial_bytes = 0; + s->threshold_size = 0; return s; } @@ -1843,7 +1842,7 @@ static int await_return_path_close_on_source(MigrationState *ms) * Switch from normal iteration to postcopy * Returns non-0 on error */ -static int postcopy_start(MigrationState *ms, bool *old_vm_running) +static int postcopy_start(MigrationState *ms) { int ret; QIOChannelBuffer *bioc; @@ -1861,7 +1860,6 @@ static int postcopy_start(MigrationState *ms, bool *old_vm_running) trace_postcopy_start_set_run(); qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); - *old_vm_running = runstate_is_running(); global_state_store(); ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE); if (ret < 0) { @@ -2051,21 +2049,17 @@ static int migration_maybe_pause(MigrationState *s, * The caller 'breaks' the loop when this returns. * * @s: Current migration state - * @current_active_state: The migration state we expect to be in - * @*old_vm_running: Pointer to old_vm_running flag - * @*start_time: Pointer to time to update */ -static void migration_completion(MigrationState *s, int current_active_state, - bool *old_vm_running, - int64_t *start_time) +static void migration_completion(MigrationState *s) { int ret; + int current_active_state = s->state; if (s->state == MIGRATION_STATUS_ACTIVE) { qemu_mutex_lock_iothread(); - *start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); + s->downtime_start = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); - *old_vm_running = runstate_is_running(); + s->vm_was_running = runstate_is_running(); ret = global_state_store(); if (!ret) { @@ -2152,6 +2146,155 @@ bool migrate_colo_enabled(void) return s->enabled_capabilities[MIGRATION_CAPABILITY_X_COLO]; } +static void migration_calculate_complete(MigrationState *s) +{ + uint64_t bytes = qemu_ftell(s->to_dst_file); + int64_t end_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); + + s->total_time = end_time - s->start_time; + if (!s->downtime) { + /* + * It's still not set, so we are precopy migration. For + * postcopy, downtime is calculated during postcopy_start(). + */ + s->downtime = end_time - s->downtime_start; + } + + if (s->total_time) { + s->mbps = ((double) bytes * 8.0) / s->total_time / 1000; + } +} + +static void migration_update_counters(MigrationState *s, + int64_t current_time) +{ + uint64_t transferred, time_spent; + int64_t threshold_size; + double bandwidth; + + if (current_time < s->iteration_start_time + BUFFER_DELAY) { + return; + } + + transferred = qemu_ftell(s->to_dst_file) - s->iteration_initial_bytes; + time_spent = current_time - s->iteration_start_time; + bandwidth = (double)transferred / time_spent; + threshold_size = bandwidth * s->parameters.downtime_limit; + + s->mbps = (((double) transferred * 8.0) / + ((double) time_spent / 1000.0)) / 1000.0 / 1000.0; + + /* + * if we haven't sent anything, we don't want to + * recalculate. 10000 is a small enough number for our purposes + */ + if (ram_counters.dirty_pages_rate && transferred > 10000) { + s->expected_downtime = ram_counters.dirty_pages_rate * + qemu_target_page_size() / bandwidth; + } + + qemu_file_reset_rate_limit(s->to_dst_file); + + s->iteration_start_time = current_time; + s->iteration_initial_bytes = qemu_ftell(s->to_dst_file); + + trace_migrate_transferred(transferred, time_spent, + bandwidth, threshold_size); +} + +/* Migration thread iteration status */ +typedef enum { + MIG_ITERATE_RESUME, /* Resume current iteration */ + MIG_ITERATE_SKIP, /* Skip current iteration */ + MIG_ITERATE_BREAK, /* Break the loop */ +} MigIterateState; + +/* + * Return true if continue to the next iteration directly, false + * otherwise. + */ +static MigIterateState migration_iteration_run(MigrationState *s) +{ + uint64_t pending_size, pend_post, pend_nonpost; + bool in_postcopy = s->state == MIGRATION_STATUS_POSTCOPY_ACTIVE; + + qemu_savevm_state_pending(s->to_dst_file, s->threshold_size, + &pend_nonpost, &pend_post); + pending_size = pend_nonpost + pend_post; + + trace_migrate_pending(pending_size, s->threshold_size, + pend_post, pend_nonpost); + + if (pending_size && pending_size >= s->threshold_size) { + /* Still a significant amount to transfer */ + if (migrate_postcopy() && !in_postcopy && + pend_nonpost <= s->threshold_size && + atomic_read(&s->start_postcopy)) { + if (postcopy_start(s)) { + error_report("%s: postcopy failed to start", __func__); + } + return MIG_ITERATE_SKIP; + } + /* Just another iteration step */ + qemu_savevm_state_iterate(s->to_dst_file, + s->state == MIGRATION_STATUS_POSTCOPY_ACTIVE); + } else { + trace_migration_thread_low_pending(pending_size); + migration_completion(s); + return MIG_ITERATE_BREAK; + } + + return MIG_ITERATE_RESUME; +} + +static void migration_iteration_finish(MigrationState *s) +{ + /* If we enabled cpu throttling for auto-converge, turn it off. */ + cpu_throttle_stop(); + + qemu_mutex_lock_iothread(); + switch (s->state) { + case MIGRATION_STATUS_COMPLETED: + migration_calculate_complete(s); + runstate_set(RUN_STATE_POSTMIGRATE); + break; + + case MIGRATION_STATUS_ACTIVE: + /* + * We should really assert here, but since it's during + * migration, let's try to reduce the usage of assertions. + */ + if (!migrate_colo_enabled()) { + error_report("%s: critical error: calling COLO code without " + "COLO enabled", __func__); + } + migrate_start_colo_process(s); + /* + * Fixme: we will run VM in COLO no matter its old running state. + * After exited COLO, we will keep running. + */ + s->vm_was_running = true; + /* Fallthrough */ + case MIGRATION_STATUS_FAILED: + case MIGRATION_STATUS_CANCELLED: + if (s->vm_was_running) { + vm_start(); + } else { + if (runstate_check(RUN_STATE_FINISH_MIGRATE)) { + runstate_set(RUN_STATE_POSTMIGRATE); + } + } + break; + + default: + /* Should not reach here, but if so, forgive the VM. */ + error_report("%s: Unknown ending state %d", __func__, s->state); + break; + } + qemu_bh_schedule(s->cleanup_bh); + qemu_mutex_unlock_iothread(); +} + /* * Master migration thread on the source VM. * It drives the migration and pumps the data down the outgoing channel. @@ -2159,26 +2302,12 @@ bool migrate_colo_enabled(void) static void *migration_thread(void *opaque) { MigrationState *s = opaque; - /* Used by the bandwidth calcs, updated later */ - 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; - /* - * 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; - bool entered_postcopy = false; - /* The active state we expect to be in; ACTIVE or POSTCOPY_ACTIVE */ - enum MigrationStatus current_active_state = MIGRATION_STATUS_ACTIVE; - bool enable_colo = migrate_colo_enabled(); rcu_register_thread(); + s->iteration_start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); + qemu_savevm_state_header(s->to_dst_file); /* @@ -2213,122 +2342,38 @@ static void *migration_thread(void *opaque) while (s->state == MIGRATION_STATUS_ACTIVE || s->state == MIGRATION_STATUS_POSTCOPY_ACTIVE) { int64_t current_time; - uint64_t pending_size; if (!qemu_file_rate_limit(s->to_dst_file)) { - uint64_t pend_post, pend_nonpost; - - 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, threshold_size, - pend_post, pend_nonpost); - if (pending_size && pending_size >= threshold_size) { - /* Still a significant amount to transfer */ - - if (migrate_postcopy() && - s->state != MIGRATION_STATUS_POSTCOPY_ACTIVE && - pend_nonpost <= threshold_size && - atomic_read(&s->start_postcopy)) { - - if (!postcopy_start(s, &old_vm_running)) { - current_active_state = MIGRATION_STATUS_POSTCOPY_ACTIVE; - entered_postcopy = true; - } - - continue; - } - /* Just another iteration step */ - qemu_savevm_state_iterate(s->to_dst_file, entered_postcopy); - } else { - trace_migration_thread_low_pending(pending_size); - migration_completion(s, current_active_state, - &old_vm_running, &start_time); + MigIterateState iter_state = migration_iteration_run(s); + if (iter_state == MIG_ITERATE_SKIP) { + continue; + } else if (iter_state == MIG_ITERATE_BREAK) { break; } } if (qemu_file_get_error(s->to_dst_file)) { - migrate_set_state(&s->state, current_active_state, - MIGRATION_STATUS_FAILED); + if (migration_is_setup_or_active(s->state)) { + migrate_set_state(&s->state, s->state, + MIGRATION_STATUS_FAILED); + } trace_migration_thread_file_err(); break; } + current_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); - if (current_time >= initial_time + BUFFER_DELAY) { - uint64_t transferred_bytes = qemu_ftell(s->to_dst_file) - - initial_bytes; - uint64_t time_spent = current_time - initial_time; - double bandwidth = (double)transferred_bytes / time_spent; - 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, threshold_size); - /* if we haven't sent anything, we don't want to recalculate - 10000 is a small enough number for our purposes */ - if (ram_counters.dirty_pages_rate && transferred_bytes > 10000) { - s->expected_downtime = ram_counters.dirty_pages_rate * - qemu_target_page_size() / bandwidth; - } - qemu_file_reset_rate_limit(s->to_dst_file); - initial_time = current_time; - initial_bytes = qemu_ftell(s->to_dst_file); - } + migration_update_counters(s, current_time); + if (qemu_file_rate_limit(s->to_dst_file)) { /* usleep expects microseconds */ - g_usleep((initial_time + BUFFER_DELAY - current_time)*1000); + g_usleep((s->iteration_start_time + BUFFER_DELAY - + current_time) * 1000); } } trace_migration_thread_after_loop(); - /* If we enabled cpu throttling for auto-converge, turn it off. */ - cpu_throttle_stop(); - end_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); - - qemu_mutex_lock_iothread(); - /* - * The resource has been allocated by migration will be reused in COLO - * process, so don't release them. - */ - if (!enable_colo) { - qemu_savevm_state_cleanup(); - } - if (s->state == MIGRATION_STATUS_COMPLETED) { - uint64_t transferred_bytes = qemu_ftell(s->to_dst_file); - s->total_time = end_time - s->total_time; - if (!entered_postcopy) { - s->downtime = end_time - start_time; - } - if (s->total_time) { - s->mbps = (((double) transferred_bytes * 8.0) / - ((double) s->total_time)) / 1000; - } - runstate_set(RUN_STATE_POSTMIGRATE); - } else { - if (s->state == MIGRATION_STATUS_ACTIVE && enable_colo) { - migrate_start_colo_process(s); - qemu_savevm_state_cleanup(); - /* - * Fixme: we will run VM in COLO no matter its old running state. - * After exited COLO, we will keep running. - */ - old_vm_running = true; - } - if (old_vm_running && !entered_postcopy) { - vm_start(); - } else { - if (runstate_check(RUN_STATE_FINISH_MIGRATE)) { - runstate_set(RUN_STATE_POSTMIGRATE); - } - } - } - qemu_bh_schedule(s->cleanup_bh); - qemu_mutex_unlock_iothread(); - + migration_iteration_finish(s); rcu_unregister_thread(); return NULL; } @@ -2375,10 +2420,15 @@ void migration_global_dump(Monitor *mon) { MigrationState *ms = migrate_get_current(); - monitor_printf(mon, "globals: store-global-state=%d, only_migratable=%d, " - "send-configuration=%d, send-section-footer=%d\n", - ms->store_global_state, ms->only_migratable, - ms->send_configuration, ms->send_section_footer); + monitor_printf(mon, "globals:\n"); + monitor_printf(mon, "store-global-state: %s\n", + ms->store_global_state ? "on" : "off"); + monitor_printf(mon, "only-migratable: %s\n", + ms->only_migratable ? "on" : "off"); + monitor_printf(mon, "send-configuration: %s\n", + ms->send_configuration ? "on" : "off"); + monitor_printf(mon, "send-section-footer: %s\n", + ms->send_section_footer ? "on" : "off"); } #define DEFINE_PROP_MIG_CAP(name, x) \ @@ -2394,33 +2444,33 @@ static Property migration_properties[] = { send_section_footer, true), /* Migration parameters */ - DEFINE_PROP_INT64("x-compress-level", MigrationState, + DEFINE_PROP_UINT8("x-compress-level", MigrationState, parameters.compress_level, DEFAULT_MIGRATE_COMPRESS_LEVEL), - DEFINE_PROP_INT64("x-compress-threads", MigrationState, + DEFINE_PROP_UINT8("x-compress-threads", MigrationState, parameters.compress_threads, DEFAULT_MIGRATE_COMPRESS_THREAD_COUNT), - DEFINE_PROP_INT64("x-decompress-threads", MigrationState, + DEFINE_PROP_UINT8("x-decompress-threads", MigrationState, parameters.decompress_threads, DEFAULT_MIGRATE_DECOMPRESS_THREAD_COUNT), - DEFINE_PROP_INT64("x-cpu-throttle-initial", MigrationState, + DEFINE_PROP_UINT8("x-cpu-throttle-initial", MigrationState, parameters.cpu_throttle_initial, DEFAULT_MIGRATE_CPU_THROTTLE_INITIAL), - DEFINE_PROP_INT64("x-cpu-throttle-increment", MigrationState, + DEFINE_PROP_UINT8("x-cpu-throttle-increment", MigrationState, parameters.cpu_throttle_increment, DEFAULT_MIGRATE_CPU_THROTTLE_INCREMENT), - DEFINE_PROP_INT64("x-max-bandwidth", MigrationState, + DEFINE_PROP_SIZE("x-max-bandwidth", MigrationState, parameters.max_bandwidth, MAX_THROTTLE), - DEFINE_PROP_INT64("x-downtime-limit", MigrationState, + DEFINE_PROP_UINT64("x-downtime-limit", MigrationState, parameters.downtime_limit, DEFAULT_MIGRATE_SET_DOWNTIME), - DEFINE_PROP_INT64("x-checkpoint-delay", MigrationState, + DEFINE_PROP_UINT32("x-checkpoint-delay", MigrationState, parameters.x_checkpoint_delay, DEFAULT_MIGRATE_X_CHECKPOINT_DELAY), - DEFINE_PROP_INT64("x-multifd-channels", MigrationState, + DEFINE_PROP_UINT8("x-multifd-channels", MigrationState, parameters.x_multifd_channels, DEFAULT_MIGRATE_MULTIFD_CHANNELS), - DEFINE_PROP_INT64("x-multifd-page-count", MigrationState, + DEFINE_PROP_UINT32("x-multifd-page-count", MigrationState, parameters.x_multifd_page_count, DEFAULT_MIGRATE_MULTIFD_PAGE_COUNT), DEFINE_PROP_SIZE("xbzrle-cache-size", MigrationState, diff --git a/migration/migration.h b/migration/migration.h index 663415fe48..786d971ce2 100644 --- a/migration/migration.h +++ b/migration/migration.h @@ -90,6 +90,17 @@ struct MigrationState QEMUBH *cleanup_bh; QEMUFile *to_dst_file; + /* bytes already send at the beggining of current interation */ + uint64_t iteration_initial_bytes; + /* time at the start of current iteration */ + int64_t iteration_start_time; + /* + * 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; + /* params from 'migrate-set-parameters' */ MigrationParameters parameters; @@ -103,11 +114,22 @@ struct MigrationState } rp_state; double mbps; + /* Timestamp when recent migration starts (ms) */ + int64_t start_time; + /* Total time used by latest migration (ms) */ int64_t total_time; + /* Timestamp when VM is down (ms) to migrate the last stuff */ + int64_t downtime_start; int64_t downtime; int64_t expected_downtime; bool enabled_capabilities[MIGRATION_CAPABILITY__MAX]; int64_t setup_time; + /* + * Whether guest was running when we enter the completion stage. + * If migration is interrupted by any reason, we need to continue + * running the guest on source. + */ + bool vm_was_running; /* Flag set once the migration has been asked to enter postcopy */ bool start_postcopy; diff --git a/migration/ram.c b/migration/ram.c index 021d583b9b..cb1950f3eb 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -237,7 +237,8 @@ static RAMState *ram_state; uint64_t ram_bytes_remaining(void) { - return ram_state->migration_dirty_pages * TARGET_PAGE_SIZE; + return ram_state ? (ram_state->migration_dirty_pages * TARGET_PAGE_SIZE) : + 0; } MigrationStats ram_counters; diff --git a/migration/rdma.c b/migration/rdma.c index ca56594328..9d5a424011 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -88,7 +88,7 @@ static uint32_t known_capabilities = RDMA_CAPABILITY_PIN_ALL; } \ return rdma->error_state; \ } \ - } while (0); + } while (0) /* * A work request ID is 64-bits and we split up these bits diff --git a/migration/socket.c b/migration/socket.c index dee869044a..3a8232dd2d 100644 --- a/migration/socket.c +++ b/migration/socket.c @@ -172,7 +172,6 @@ static void socket_start_incoming_migration(SocketAddress *saddr, if (qio_channel_socket_listen_sync(listen_ioc, saddr, errp) < 0) { object_unref(OBJECT(listen_ioc)); - qapi_free_SocketAddress(saddr); return; } @@ -181,7 +180,6 @@ static void socket_start_incoming_migration(SocketAddress *saddr, socket_accept_incoming_migration, listen_ioc, (GDestroyNotify)object_unref); - qapi_free_SocketAddress(saddr); } void tcp_start_incoming_migration(const char *host_port, Error **errp) @@ -191,6 +189,7 @@ void tcp_start_incoming_migration(const char *host_port, Error **errp) if (!err) { socket_start_incoming_migration(saddr, &err); } + qapi_free_SocketAddress(saddr); error_propagate(errp, err); } @@ -198,4 +197,5 @@ void unix_start_incoming_migration(const char *path, Error **errp) { SocketAddress *saddr = unix_build_address(path); socket_start_incoming_migration(saddr, errp); + qapi_free_SocketAddress(saddr); } |