/*
* Having preliminary checks for uri and channel
*/
- if (uri && has_channels) {
- error_setg(errp, "'uri' and 'channels' arguments are mutually "
- "exclusive; exactly one of the two should be present in "
- "'migrate-incoming' qmp command ");
+ if (!uri == !channels) {
+ error_setg(errp, "need either 'uri' or 'channels' argument");
return;
- } else if (channels) {
+ }
+
+ if (channels) {
/* To verify that Migrate channel list has only item */
if (channels->next) {
error_setg(errp, "Channel list has more than one entries");
return;
}
addr = channels->value->addr;
- } else if (uri) {
+ }
+
+ if (uri) {
/* caller uses the old URI syntax */
if (!migrate_uri_parse(uri, &channel, errp)) {
return;
}
addr = channel->addr;
- } else {
- error_setg(errp, "neither 'uri' or 'channels' argument are "
- "specified in 'migrate-incoming' qmp command ");
- return;
}
/* transport mechanism not suitable for migration? */
*/
if (!migrate_late_block_activate() ||
(autostart && (!global_state_received() ||
- global_state_get_runstate() == RUN_STATE_RUNNING))) {
+ runstate_is_live(global_state_get_runstate())))) {
/* Make sure all file formats throw away their mutable metadata.
* If we get an error here, just don't restart the VM yet. */
bdrv_activate_all(&local_err);
dirty_bitmap_mig_before_vm_start();
if (!global_state_received() ||
- global_state_get_runstate() == RUN_STATE_RUNNING) {
+ runstate_is_live(global_state_get_runstate())) {
if (autostart) {
vm_start();
} else {
MIGRATION_STATUS_COMPLETED);
qemu_bh_delete(mis->bh);
migration_incoming_state_destroy();
+ object_unref(OBJECT(migrate_get_current()));
}
static void coroutine_fn
}
if (ret < 0) {
+ MigrationState *s = migrate_get_current();
+
+ if (migrate_has_error(s)) {
+ WITH_QEMU_LOCK_GUARD(&s->error_mutex) {
+ error_report_err(s->error);
+ }
+ }
error_report("load of migration failed: %s", strerror(-ret));
goto fail;
}
}
mis->bh = qemu_bh_new(process_incoming_migration_bh, mis);
+ object_ref(OBJECT(migrate_get_current()));
qemu_bh_schedule(mis->bh);
return;
fail:
/**
* migration_incoming_setup: Setup incoming migration
* @f: file for main migration channel
- * @errp: where to put errors
- *
- * Returns: %true on success, %false on error.
*/
-static bool migration_incoming_setup(QEMUFile *f, Error **errp)
+static void migration_incoming_setup(QEMUFile *f)
{
MigrationIncomingState *mis = migration_incoming_get_current();
mis->from_src_file = f;
}
qemu_file_set_blocking(f, false);
- return true;
}
void migration_incoming_process(void)
return false;
}
-void migration_fd_process_incoming(QEMUFile *f, Error **errp)
+void migration_fd_process_incoming(QEMUFile *f)
{
- if (!migration_incoming_setup(f, errp)) {
- return;
- }
+ migration_incoming_setup(f);
if (postcopy_try_recover()) {
return;
}
* issue is not possible.
*/
ret = migration_channel_read_peek(ioc, (void *)&channel_magic,
- sizeof(channel_magic), &local_err);
+ sizeof(channel_magic), errp);
if (ret != 0) {
- error_propagate(errp, local_err);
return;
}
}
if (multifd_load_setup(errp) != 0) {
- error_setg(errp, "Failed to setup multifd channels");
return;
}
if (default_channel) {
f = qemu_file_new_input(ioc);
-
- if (!migration_incoming_setup(f, errp)) {
- return;
- }
+ migration_incoming_setup(f);
} else {
/* Multiple connections */
assert(migration_needs_multiple_sockets());
QEMUFile *tmp;
trace_migrate_fd_cleanup();
- qemu_mutex_unlock_iothread();
+ bql_unlock();
if (s->migration_thread_running) {
qemu_thread_join(&s->thread);
s->migration_thread_running = false;
}
- qemu_mutex_lock_iothread();
+ bql_lock();
multifd_save_cleanup();
qemu_mutex_lock(&s->qemu_file_lock);
s->migration_thread_running = false;
error_free(s->error);
s->error = NULL;
- s->hostname = NULL;
s->vmdesc = NULL;
migrate_set_state(&s->state, MIGRATION_STATUS_NONE, MIGRATION_STATUS_SETUP);
static bool migrate_prepare(MigrationState *s, bool blk, bool blk_inc,
bool resume, Error **errp)
{
- Error *local_err = NULL;
-
if (blk_inc) {
warn_report("parameter 'inc' is deprecated;"
" use blockdev-mirror with NBD instead");
"current migration capabilities");
return false;
}
- if (!migrate_cap_set(MIGRATION_CAPABILITY_BLOCK, true, &local_err)) {
- error_propagate(errp, local_err);
+ if (!migrate_cap_set(MIGRATION_CAPABILITY_BLOCK, true, errp)) {
return false;
}
s->must_remove_block_options = true;
/*
* Having preliminary checks for uri and channel
*/
- if (uri && has_channels) {
- error_setg(errp, "'uri' and 'channels' arguments are mutually "
- "exclusive; exactly one of the two should be present in "
- "'migrate' qmp command ");
+ if (!uri == !channels) {
+ error_setg(errp, "need either 'uri' or 'channels' argument");
return;
- } else if (channels) {
+ }
+
+ if (channels) {
/* To verify that Migrate channel list has only item */
if (channels->next) {
error_setg(errp, "Channel list has more than one entries");
return;
}
addr = channels->value->addr;
- } else if (uri) {
+ }
+
+ if (uri) {
/* caller uses the old URI syntax */
if (!migrate_uri_parse(uri, &channel, errp)) {
return;
}
addr = channel->addr;
- } else {
- error_setg(errp, "neither 'uri' or 'channels' argument are "
- "specified in 'migrate' qmp command ");
- return;
}
/* transport mechanism not suitable for migration? */
}
trace_postcopy_start();
- qemu_mutex_lock_iothread();
+ bql_lock();
trace_postcopy_start_set_run();
migration_downtime_start(ms);
- qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
global_state_store();
ret = migration_stop_vm(RUN_STATE_FINISH_MIGRATE);
if (ret < 0) {
migration_downtime_end(ms);
- qemu_mutex_unlock_iothread();
+ bql_unlock();
if (migrate_postcopy_ram()) {
/*
error_report_err(local_err);
}
}
- qemu_mutex_unlock_iothread();
+ bql_unlock();
return -1;
}
/**
* migration_maybe_pause: Pause if required to by
- * migrate_pause_before_switchover called with the iothread locked
+ * migrate_pause_before_switchover called with the BQL locked
* Returns: 0 on success
*/
static int migration_maybe_pause(MigrationState *s,
* wait for the 'pause_sem' semaphore.
*/
if (s->state != MIGRATION_STATUS_CANCELLING) {
- qemu_mutex_unlock_iothread();
+ bql_unlock();
migrate_set_state(&s->state, *current_active_state,
MIGRATION_STATUS_PRE_SWITCHOVER);
qemu_sem_wait(&s->pause_sem);
migrate_set_state(&s->state, MIGRATION_STATUS_PRE_SWITCHOVER,
new_state);
*current_active_state = new_state;
- qemu_mutex_lock_iothread();
+ bql_lock();
}
return s->state == new_state ? 0 : -EINVAL;
{
int ret;
- qemu_mutex_lock_iothread();
+ bql_lock();
migration_downtime_start(s);
- qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
s->vm_old_state = runstate_get();
global_state_store();
ret = qemu_savevm_state_complete_precopy(s->to_dst_file, false,
s->block_inactive);
out_unlock:
- qemu_mutex_unlock_iothread();
+ bql_unlock();
return ret;
}
{
trace_migration_completion_postcopy_end();
- qemu_mutex_lock_iothread();
+ bql_lock();
qemu_savevm_state_complete_postcopy(s->to_dst_file);
- qemu_mutex_unlock_iothread();
+ bql_unlock();
/*
* Shutdown the postcopy fast path thread. This is only needed when dest
*/
Error *local_err = NULL;
- qemu_mutex_lock_iothread();
+ bql_lock();
bdrv_activate_all(&local_err);
if (local_err) {
error_report_err(local_err);
} else {
s->block_inactive = false;
}
- qemu_mutex_unlock_iothread();
+ bql_unlock();
}
migrate_set_state(&s->state, current_active_state,
/* If we enabled cpu throttling for auto-converge, turn it off. */
cpu_throttle_stop();
- qemu_mutex_lock_iothread();
+ bql_lock();
switch (s->state) {
case MIGRATION_STATUS_COMPLETED:
migration_calculate_complete(s);
case MIGRATION_STATUS_FAILED:
case MIGRATION_STATUS_CANCELLED:
case MIGRATION_STATUS_CANCELLING:
- if (s->vm_old_state == RUN_STATE_RUNNING) {
+ if (runstate_is_live(s->vm_old_state)) {
if (!runstate_check(RUN_STATE_SHUTDOWN)) {
vm_start();
}
break;
}
migrate_fd_cleanup_schedule(s);
- qemu_mutex_unlock_iothread();
+ bql_unlock();
}
static void bg_migration_iteration_finish(MigrationState *s)
*/
ram_write_tracking_stop();
- qemu_mutex_lock_iothread();
+ bql_lock();
switch (s->state) {
case MIGRATION_STATUS_COMPLETED:
migration_calculate_complete(s);
}
migrate_fd_cleanup_schedule(s);
- qemu_mutex_unlock_iothread();
+ bql_unlock();
}
/*
object_ref(OBJECT(s));
update_iteration_initial_status(s);
- qemu_mutex_lock_iothread();
+ bql_lock();
qemu_savevm_state_header(s->to_dst_file);
- qemu_mutex_unlock_iothread();
+ bql_unlock();
/*
* If we opened the return path, we need to make sure dst has it
qemu_savevm_send_colo_enable(s->to_dst_file);
}
- qemu_mutex_lock_iothread();
+ bql_lock();
qemu_savevm_state_setup(s->to_dst_file);
- qemu_mutex_unlock_iothread();
+ bql_unlock();
qemu_savevm_wait_unplug(s, MIGRATION_STATUS_SETUP,
MIGRATION_STATUS_ACTIVE);
qemu_bh_delete(s->vm_start_bh);
s->vm_start_bh = NULL;
- vm_start();
+ vm_resume(s->vm_old_state);
migration_downtime_end(s);
}
ram_write_tracking_prepare();
#endif
- qemu_mutex_lock_iothread();
+ bql_lock();
qemu_savevm_state_header(s->to_dst_file);
qemu_savevm_state_setup(s->to_dst_file);
- qemu_mutex_unlock_iothread();
+ bql_unlock();
qemu_savevm_wait_unplug(s, MIGRATION_STATUS_SETUP,
MIGRATION_STATUS_ACTIVE);
trace_migration_thread_setup_complete();
migration_downtime_start(s);
- qemu_mutex_lock_iothread();
+ bql_lock();
- /*
- * If VM is currently in suspended state, then, to make a valid runstate
- * transition in vm_stop_force_state() we need to wakeup it up.
- */
- qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
s->vm_old_state = runstate_get();
global_state_store();
s->vm_start_bh = qemu_bh_new(bg_migration_vm_start_bh, s);
qemu_bh_schedule(s->vm_start_bh);
- qemu_mutex_unlock_iothread();
+ bql_unlock();
while (migration_is_active(s)) {
MigIterateState iter_state = bg_migration_iteration_run(s);
if (early_fail) {
migrate_set_state(&s->state, MIGRATION_STATUS_ACTIVE,
MIGRATION_STATUS_FAILED);
- qemu_mutex_unlock_iothread();
+ bql_unlock();
}
bg_migration_iteration_finish(s);