@@ -23,6 +23,7 @@
#include "qapi-types.h"
#include "net/filter.h"
#include "net/net.h"
+#include "block/block_int.h"
/*
* The delay time before qemu begin the procedure of default failover treatment.
@@ -83,6 +84,7 @@ static void secondary_vm_do_failover(void)
{
int old_state;
MigrationIncomingState *mis = migration_incoming_get_current();
+ Error *local_err = NULL;
/* Can not do failover during the process of VM's loading VMstate, Or
* it will break the secondary VM.
@@ -100,6 +102,12 @@ static void secondary_vm_do_failover(void)
migrate_set_state(&mis->state, MIGRATION_STATUS_COLO,
MIGRATION_STATUS_COMPLETED);
+ bdrv_stop_replication_all(true, &local_err);
+ if (local_err) {
+ error_report_err(local_err);
+ }
+ trace_colo_stop_block_replication("failover");
+
if (!autostart) {
error_report("\"-S\" qemu option will be ignored in secondary side");
/* recover runstate to normal migration finish state */
@@ -130,6 +138,7 @@ static void primary_vm_do_failover(void)
{
MigrationState *s = migrate_get_current();
int old_state;
+ Error *local_err = NULL;
if (s->state != MIGRATION_STATUS_FAILED) {
migrate_set_state(&s->state, MIGRATION_STATUS_COLO,
@@ -145,6 +154,12 @@ static void primary_vm_do_failover(void)
}
colo_cleanup_filter_buffers();
+ bdrv_stop_replication_all(true, &local_err);
+ if (local_err) {
+ error_report_err(local_err);
+ }
+ trace_colo_stop_block_replication("failover");
+
vm_start();
old_state = failover_set_state(FAILOVER_STATUS_HANDLING,
@@ -234,6 +249,7 @@ static int colo_do_checkpoint_transaction(MigrationState *s,
int colo_shutdown, ret;
size_t size;
QEMUFile *trans = NULL;
+ Error *local_err = NULL;
ret = colo_ctl_put(s->to_dst_file, COLO_COMMAND_CHECKPOINT_REQUEST, 0);
if (ret < 0) {
@@ -271,6 +287,16 @@ static int colo_do_checkpoint_transaction(MigrationState *s,
goto out;
}
+ /* we call this api although this may do nothing on primary side */
+ qemu_mutex_lock_iothread();
+ bdrv_do_checkpoint_all(&local_err);
+ qemu_mutex_unlock_iothread();
+ if (local_err) {
+ error_report_err(local_err);
+ ret = -1;
+ goto out;
+ }
+
ret = colo_ctl_put(s->to_dst_file, COLO_COMMAND_VMSTATE_SEND, 0);
if (ret < 0) {
goto out;
@@ -315,6 +341,10 @@ static int colo_do_checkpoint_transaction(MigrationState *s,
filter_buffer_release_all();
if (colo_shutdown) {
+ qemu_mutex_lock_iothread();
+ bdrv_stop_replication_all(false, NULL);
+ trace_colo_stop_block_replication("shutdown");
+ qemu_mutex_unlock_iothread();
colo_ctl_put(s->to_dst_file, COLO_COMMAND_GUEST_SHUTDOWN, 0);
qemu_fflush(s->to_dst_file);
colo_shutdown_requested = 0;
@@ -359,6 +389,7 @@ static void colo_process_checkpoint(MigrationState *s)
int64_t current_time, checkpoint_time = qemu_clock_get_ms(QEMU_CLOCK_HOST);
int64_t error_time;
int fd, ret = 0;
+ Error *local_err = NULL;
failover_init_state();
@@ -403,6 +434,15 @@ static void colo_process_checkpoint(MigrationState *s)
}
qemu_mutex_lock_iothread();
+ /* start block replication */
+ bdrv_start_replication_all(REPLICATION_MODE_PRIMARY, &local_err);
+ if (local_err) {
+ qemu_mutex_unlock_iothread();
+ error_report_err(local_err);
+ ret = -EINVAL;
+ goto out;
+ }
+ trace_colo_start_block_replication();
vm_start();
qemu_mutex_unlock_iothread();
trace_colo_vm_state_change("stop", "run");
@@ -514,6 +554,8 @@ static int colo_wait_handle_cmd(QEMUFile *f, int *checkpoint_request)
case COLO_COMMAND_GUEST_SHUTDOWN:
qemu_mutex_lock_iothread();
vm_stop_force_state(RUN_STATE_COLO);
+ bdrv_stop_replication_all(false, NULL);
+ trace_colo_stop_block_replication("shutdown");
qemu_system_shutdown_request_core();
qemu_mutex_unlock_iothread();
/* the main thread will exit and termiante the whole
@@ -545,6 +587,7 @@ void *colo_process_incoming_thread(void *opaque)
int total_size;
int64_t error_time, current_time;
int fd, ret = 0;
+ Error *local_err = NULL;
migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE,
MIGRATION_STATUS_COLO);
@@ -580,6 +623,16 @@ void *colo_process_incoming_thread(void *opaque)
goto out;
}
+ qemu_mutex_lock_iothread();
+ /* start block replication */
+ bdrv_start_replication_all(REPLICATION_MODE_SECONDARY, &local_err);
+ qemu_mutex_unlock_iothread();
+ if (local_err) {
+ error_report_err(local_err);
+ goto out;
+ }
+ trace_colo_start_block_replication();
+
ret = colo_ctl_put(mis->to_src_file, COLO_COMMAND_CHECKPOINT_READY, 0);
if (ret < 0) {
goto out;
@@ -655,8 +708,15 @@ void *colo_process_incoming_thread(void *opaque)
goto out;
}
- vmstate_loading = false;
+ /* discard colo disk buffer */
+ bdrv_do_checkpoint_all(&local_err);
qemu_mutex_unlock_iothread();
+ if (local_err) {
+ vmstate_loading = false;
+ goto out;
+ }
+
+ vmstate_loading = false;
if (failover_get_state() == FAILOVER_STATUS_RELAUNCH) {
failover_set_state(FAILOVER_STATUS_RELAUNCH, FAILOVER_STATUS_NONE);
@@ -328,16 +328,6 @@ static void process_incoming_migration_co(void *opaque)
exit(EXIT_FAILURE);
}
- /* Make sure all file formats flush their mutable metadata */
- bdrv_invalidate_cache_all(&local_err);
- if (local_err) {
- migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE,
- MIGRATION_STATUS_FAILED);
- error_report_err(local_err);
- migrate_decompress_threads_join();
- exit(EXIT_FAILURE);
- }
-
/*
* This must happen after all error conditions are dealt with and
* we're sure the VM is going to be running on this host.
@@ -1503,6 +1503,8 @@ colo_vm_state_change(const char *old, const char *new) "Change '%s' => '%s'"
colo_ctl_put(const char *msg, uint64_t value) "Send '%s' cmd, value: %" PRIu64""
colo_ctl_get(const char *msg) "Receive '%s' cmd"
colo_failover_set_state(int new_state) "new state %d"
+colo_start_block_replication(void) "Block replication is started"
+colo_stop_block_replication(const char *reason) "Block replication is stopped(reason: '%s')"
# kvm-all.c
kvm_ioctl(int type, void *arg) "type 0x%x, arg %p"