mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 07:43:54 -06:00
migration: Create the postcopy preempt channel asynchronously
This patch allows the postcopy preempt channel to be created asynchronously. The benefit is that when the connection is slow, we won't take the BQL (and potentially block all things like QMP) for a long time without releasing. A function postcopy_preempt_wait_channel() is introduced, allowing the migration thread to be able to wait on the channel creation. The channel is always created by the main thread, in which we'll kick a new semaphore to tell the migration thread that the channel has created. We'll need to wait for the new channel in two places: (1) when there's a new postcopy migration that is starting, or (2) when there's a postcopy migration to resume. For the start of migration, we don't need to wait for this channel until when we want to start postcopy, aka, postcopy_start(). We'll fail the migration if we found that the channel creation failed (which should probably not happen at all in 99% of the cases, because the main channel is using the same network topology). For a postcopy recovery, we'll need to wait in postcopy_pause(). In that case if the channel creation failed, we can't fail the migration or we'll crash the VM, instead we keep in PAUSED state, waiting for yet another recovery. Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Reviewed-by: Manish Mishra <manish.mishra@nutanix.com> Signed-off-by: Peter Xu <peterx@redhat.com> Message-Id: <20220707185509.27311-1-peterx@redhat.com> Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
This commit is contained in:
parent
60bb3c5871
commit
d0edb8a173
4 changed files with 68 additions and 12 deletions
|
@ -3053,6 +3053,12 @@ static int postcopy_start(MigrationState *ms)
|
|||
int64_t bandwidth = migrate_max_postcopy_bandwidth();
|
||||
bool restart_block = false;
|
||||
int cur_state = MIGRATION_STATUS_ACTIVE;
|
||||
|
||||
if (postcopy_preempt_wait_channel(ms)) {
|
||||
migrate_set_state(&ms->state, ms->state, MIGRATION_STATUS_FAILED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!migrate_pause_before_switchover()) {
|
||||
migrate_set_state(&ms->state, MIGRATION_STATUS_ACTIVE,
|
||||
MIGRATION_STATUS_POSTCOPY_ACTIVE);
|
||||
|
@ -3534,6 +3540,14 @@ static MigThrError postcopy_pause(MigrationState *s)
|
|||
if (s->state == MIGRATION_STATUS_POSTCOPY_RECOVER) {
|
||||
/* Woken up by a recover procedure. Give it a shot */
|
||||
|
||||
if (postcopy_preempt_wait_channel(s)) {
|
||||
/*
|
||||
* Preempt enabled, and new channel create failed; loop
|
||||
* back to wait for another recovery.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Firstly, let's wake up the return path now, with a new
|
||||
* return path channel.
|
||||
|
@ -4398,6 +4412,7 @@ static void migration_instance_finalize(Object *obj)
|
|||
qemu_sem_destroy(&ms->postcopy_pause_sem);
|
||||
qemu_sem_destroy(&ms->postcopy_pause_rp_sem);
|
||||
qemu_sem_destroy(&ms->rp_state.rp_sem);
|
||||
qemu_sem_destroy(&ms->postcopy_qemufile_src_sem);
|
||||
error_free(ms->error);
|
||||
}
|
||||
|
||||
|
@ -4444,6 +4459,7 @@ static void migration_instance_init(Object *obj)
|
|||
qemu_sem_init(&ms->rp_state.rp_sem, 0);
|
||||
qemu_sem_init(&ms->rate_limit_sem, 0);
|
||||
qemu_sem_init(&ms->wait_unplug_sem, 0);
|
||||
qemu_sem_init(&ms->postcopy_qemufile_src_sem, 0);
|
||||
qemu_mutex_init(&ms->qemu_file_lock);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue