mirror of
https://github.com/qemu/qemu.git
synced 2024-11-25 03:43:37 +08:00
migration: rebuild channel on source
This patch detects the "resume" flag of migration command, rebuild the channels only if the flag is set. Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Signed-off-by: Peter Xu <peterx@redhat.com> Message-Id: <20180502104740.12123-9-peterx@redhat.com> Signed-off-by: Juan Quintela <quintela@redhat.com>
This commit is contained in:
parent
7a4da28b26
commit
d3e35b8f62
@ -1411,6 +1411,61 @@ bool migration_is_blocked(Error **errp)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Returns true if continue to migrate, or false if error detected */
|
||||
static bool migrate_prepare(MigrationState *s, bool blk, bool blk_inc,
|
||||
bool resume, Error **errp)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (resume) {
|
||||
if (s->state != MIGRATION_STATUS_POSTCOPY_PAUSED) {
|
||||
error_setg(errp, "Cannot resume if there is no "
|
||||
"paused migration");
|
||||
return false;
|
||||
}
|
||||
/* This is a resume, skip init status */
|
||||
return true;
|
||||
}
|
||||
|
||||
if (migration_is_setup_or_active(s->state) ||
|
||||
s->state == MIGRATION_STATUS_CANCELLING ||
|
||||
s->state == MIGRATION_STATUS_COLO) {
|
||||
error_setg(errp, QERR_MIGRATION_ACTIVE);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (runstate_check(RUN_STATE_INMIGRATE)) {
|
||||
error_setg(errp, "Guest is waiting for an incoming migration");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (migration_is_blocked(errp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (blk || blk_inc) {
|
||||
if (migrate_use_block() || migrate_use_block_incremental()) {
|
||||
error_setg(errp, "Command options are incompatible with "
|
||||
"current migration capabilities");
|
||||
return false;
|
||||
}
|
||||
migrate_set_block_enabled(true, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return false;
|
||||
}
|
||||
s->must_remove_block_options = true;
|
||||
}
|
||||
|
||||
if (blk_inc) {
|
||||
migrate_set_block_incremental(s, true);
|
||||
}
|
||||
|
||||
migrate_init(s);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void qmp_migrate(const char *uri, bool has_blk, bool blk,
|
||||
bool has_inc, bool inc, bool has_detach, bool detach,
|
||||
bool has_resume, bool resume, Error **errp)
|
||||
@ -1419,40 +1474,11 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
|
||||
MigrationState *s = migrate_get_current();
|
||||
const char *p;
|
||||
|
||||
if (migration_is_setup_or_active(s->state) ||
|
||||
s->state == MIGRATION_STATUS_CANCELLING ||
|
||||
s->state == MIGRATION_STATUS_COLO) {
|
||||
error_setg(errp, QERR_MIGRATION_ACTIVE);
|
||||
if (!migrate_prepare(s, has_blk && blk, has_inc && inc,
|
||||
has_resume && resume, errp)) {
|
||||
/* Error detected, put into errp */
|
||||
return;
|
||||
}
|
||||
if (runstate_check(RUN_STATE_INMIGRATE)) {
|
||||
error_setg(errp, "Guest is waiting for an incoming migration");
|
||||
return;
|
||||
}
|
||||
|
||||
if (migration_is_blocked(errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((has_blk && blk) || (has_inc && inc)) {
|
||||
if (migrate_use_block() || migrate_use_block_incremental()) {
|
||||
error_setg(errp, "Command options are incompatible with "
|
||||
"current migration capabilities");
|
||||
return;
|
||||
}
|
||||
migrate_set_block_enabled(true, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
s->must_remove_block_options = true;
|
||||
}
|
||||
|
||||
if (has_inc && inc) {
|
||||
migrate_set_block_incremental(s, true);
|
||||
}
|
||||
|
||||
migrate_init(s);
|
||||
|
||||
if (strstart(uri, "tcp:", &p)) {
|
||||
tcp_start_outgoing_migration(s, p, &local_err);
|
||||
@ -1928,7 +1954,8 @@ out:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int open_return_path_on_source(MigrationState *ms)
|
||||
static int open_return_path_on_source(MigrationState *ms,
|
||||
bool create_thread)
|
||||
{
|
||||
|
||||
ms->rp_state.from_dst_file = qemu_file_get_return_path(ms->to_dst_file);
|
||||
@ -1937,6 +1964,12 @@ static int open_return_path_on_source(MigrationState *ms)
|
||||
}
|
||||
|
||||
trace_open_return_path_on_source();
|
||||
|
||||
if (!create_thread) {
|
||||
/* We're done */
|
||||
return 0;
|
||||
}
|
||||
|
||||
qemu_thread_create(&ms->rp_state.rp_thread, "return path",
|
||||
source_return_path_thread, ms, QEMU_THREAD_JOINABLE);
|
||||
|
||||
@ -2593,6 +2626,9 @@ static void *migration_thread(void *opaque)
|
||||
|
||||
void migrate_fd_connect(MigrationState *s, Error *error_in)
|
||||
{
|
||||
int64_t rate_limit;
|
||||
bool resume = s->state == MIGRATION_STATUS_POSTCOPY_PAUSED;
|
||||
|
||||
s->expected_downtime = s->parameters.downtime_limit;
|
||||
s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s);
|
||||
if (error_in) {
|
||||
@ -2601,12 +2637,21 @@ void migrate_fd_connect(MigrationState *s, Error *error_in)
|
||||
return;
|
||||
}
|
||||
|
||||
qemu_file_set_blocking(s->to_dst_file, true);
|
||||
qemu_file_set_rate_limit(s->to_dst_file,
|
||||
s->parameters.max_bandwidth / XFER_LIMIT_RATIO);
|
||||
if (resume) {
|
||||
/* This is a resumed migration */
|
||||
rate_limit = INT64_MAX;
|
||||
} else {
|
||||
/* This is a fresh new migration */
|
||||
rate_limit = s->parameters.max_bandwidth / XFER_LIMIT_RATIO;
|
||||
s->expected_downtime = s->parameters.downtime_limit;
|
||||
s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s);
|
||||
|
||||
/* Notify before starting migration thread */
|
||||
notifier_list_notify(&migration_state_notifiers, s);
|
||||
/* Notify before starting migration thread */
|
||||
notifier_list_notify(&migration_state_notifiers, s);
|
||||
}
|
||||
|
||||
qemu_file_set_rate_limit(s->to_dst_file, rate_limit);
|
||||
qemu_file_set_blocking(s->to_dst_file, true);
|
||||
|
||||
/*
|
||||
* Open the return path. For postcopy, it is used exclusively. For
|
||||
@ -2614,15 +2659,19 @@ void migrate_fd_connect(MigrationState *s, Error *error_in)
|
||||
* QEMU uses the return path.
|
||||
*/
|
||||
if (migrate_postcopy_ram() || migrate_use_return_path()) {
|
||||
if (open_return_path_on_source(s)) {
|
||||
if (open_return_path_on_source(s, !resume)) {
|
||||
error_report("Unable to open return-path for postcopy");
|
||||
migrate_set_state(&s->state, MIGRATION_STATUS_SETUP,
|
||||
MIGRATION_STATUS_FAILED);
|
||||
migrate_set_state(&s->state, s->state, MIGRATION_STATUS_FAILED);
|
||||
migrate_fd_cleanup(s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (resume) {
|
||||
/* TODO: do the resume logic */
|
||||
return;
|
||||
}
|
||||
|
||||
if (multifd_save_setup() != 0) {
|
||||
migrate_set_state(&s->state, MIGRATION_STATUS_SETUP,
|
||||
MIGRATION_STATUS_FAILED);
|
||||
|
Loading…
Reference in New Issue
Block a user