COLO: Don't process failover request while loading VM's state

We should not do failover work while the main thread is loading
VM's state. Otherwise the consistent of VM's memory and
device state will be broken.

We will restart the loading process after jump over the stage,
The new failover status 'RELAUNCH' will help to record if we
need to restart the process.

Cc: Eric Blake <eblake@redhat.com>
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Message-Id: <1484657864-21708-4-git-send-email-zhang.zhanghailiang@huawei.com>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
   Added a missing '(Since 2.9)'
This commit is contained in:
zhanghailiang 2017-01-17 20:57:44 +08:00 committed by Dr. David Alan Gilbert
parent c937b9a6db
commit a8664ba510
2 changed files with 29 additions and 1 deletions

View File

@ -20,6 +20,8 @@
#include "qapi/error.h" #include "qapi/error.h"
#include "migration/failover.h" #include "migration/failover.h"
static bool vmstate_loading;
#define COLO_BUFFER_BASE_SIZE (4 * 1024 * 1024) #define COLO_BUFFER_BASE_SIZE (4 * 1024 * 1024)
bool colo_supported(void) bool colo_supported(void)
@ -51,6 +53,19 @@ static void secondary_vm_do_failover(void)
int old_state; int old_state;
MigrationIncomingState *mis = migration_incoming_get_current(); MigrationIncomingState *mis = migration_incoming_get_current();
/* Can not do failover during the process of VM's loading VMstate, Or
* it will break the secondary VM.
*/
if (vmstate_loading) {
old_state = failover_set_state(FAILOVER_STATUS_ACTIVE,
FAILOVER_STATUS_RELAUNCH);
if (old_state != FAILOVER_STATUS_ACTIVE) {
error_report("Unknown error while do failover for secondary VM,"
"old_state: %s", FailoverStatus_lookup[old_state]);
}
return;
}
migrate_set_state(&mis->state, MIGRATION_STATUS_COLO, migrate_set_state(&mis->state, MIGRATION_STATUS_COLO,
MIGRATION_STATUS_COMPLETED); MIGRATION_STATUS_COMPLETED);
@ -548,13 +563,23 @@ void *colo_process_incoming_thread(void *opaque)
qemu_mutex_lock_iothread(); qemu_mutex_lock_iothread();
qemu_system_reset(VMRESET_SILENT); qemu_system_reset(VMRESET_SILENT);
vmstate_loading = true;
if (qemu_loadvm_state(fb) < 0) { if (qemu_loadvm_state(fb) < 0) {
error_report("COLO: loadvm failed"); error_report("COLO: loadvm failed");
qemu_mutex_unlock_iothread(); qemu_mutex_unlock_iothread();
goto out; goto out;
} }
vmstate_loading = false;
qemu_mutex_unlock_iothread(); qemu_mutex_unlock_iothread();
if (failover_get_state() == FAILOVER_STATUS_RELAUNCH) {
failover_set_state(FAILOVER_STATUS_RELAUNCH,
FAILOVER_STATUS_NONE);
failover_request_active(NULL);
goto out;
}
colo_send_message(mis->to_src_file, COLO_MESSAGE_VMSTATE_LOADED, colo_send_message(mis->to_src_file, COLO_MESSAGE_VMSTATE_LOADED,
&local_err); &local_err);
if (local_err) { if (local_err) {
@ -563,6 +588,7 @@ void *colo_process_incoming_thread(void *opaque)
} }
out: out:
vmstate_loading = false;
/* Throw the unreported error message after exited from loop */ /* Throw the unreported error message after exited from loop */
if (local_err) { if (local_err) {
error_report_err(local_err); error_report_err(local_err);

View File

@ -1193,10 +1193,12 @@
# #
# @completed: finish the process of failover # @completed: finish the process of failover
# #
# @relaunch: restart the failover process, from 'none' -> 'completed' (Since 2.9)
#
# Since: 2.8 # Since: 2.8
## ##
{ 'enum': 'FailoverStatus', { 'enum': 'FailoverStatus',
'data': [ 'none', 'require', 'active', 'completed'] } 'data': [ 'none', 'require', 'active', 'completed', 'relaunch' ] }
## ##
# @x-colo-lost-heartbeat: # @x-colo-lost-heartbeat: