+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int colo_do_checkpoint_transaction(MigrationState *s)
+{
+ int ret;
+
+ ret = colo_put_cmd(s->to_dst_file, COLO_COMMAND_CHECKPOINT_REQUEST);
+ if (ret < 0) {
+ goto out;
+ }
+
+ ret = colo_get_check_cmd(s->rp_state.from_dst_file,
+ COLO_COMMAND_CHECKPOINT_REPLY);
+ if (ret < 0) {
+ goto out;
+ }
+
+ /* TODO: suspend and save vm state to colo buffer */
+
+ ret = colo_put_cmd(s->to_dst_file, COLO_COMMAND_VMSTATE_SEND);
+ if (ret < 0) {
+ goto out;
+ }
+
+ /* TODO: send vmstate to Secondary */
+
+ ret = colo_get_check_cmd(s->rp_state.from_dst_file,
+ COLO_COMMAND_VMSTATE_RECEIVED);
+ if (ret < 0) {
+ goto out;
+ }
+
+ ret = colo_get_check_cmd(s->rp_state.from_dst_file,
+ COLO_COMMAND_VMSTATE_LOADED);
+ if (ret < 0) {
+ goto out;
+ }
+
+ /* TODO: resume Primary */
+
+out:
+ return ret;
+}
+
static void colo_process_checkpoint(MigrationState *s)
{
int ret = 0;
@@ -45,12 +141,28 @@ static void colo_process_checkpoint(MigrationState *s)
goto out;
}
+ /*
+ * Wait for Secondary finish loading vm states and enter COLO
+ * restore.
+ */
+ ret = colo_get_check_cmd(s->rp_state.from_dst_file,
+ COLO_COMMAND_CHECKPOINT_READY);
+ if (ret < 0) {
+ goto out;
+ }
+
qemu_mutex_lock_iothread();
vm_start();
qemu_mutex_unlock_iothread();
trace_colo_vm_state_change("stop", "run");
- /*TODO: COLO checkpoint savevm loop*/
+ while (s->state == MIGRATION_STATUS_COLO) {
+ /* start a colo checkpoint */
+ ret = colo_do_checkpoint_transaction(s);
+ if (ret < 0) {
+ goto out;
+ }
+ }
out:
if (ret < 0) {
@@ -73,6 +185,31 @@ void migrate_start_colo_process(MigrationState *s)
qemu_mutex_lock_iothread();
}
+/*
+ * return:
+ * 0: start a checkpoint
+ * -1: some error happened, exit colo restore
+ */
+static int colo_wait_handle_cmd(QEMUFile *f, int *checkpoint_request)
+{
+ int ret;
+ uint32_t cmd;
+
+ ret = colo_get_cmd(f, &cmd);
+ if (ret < 0) {
+ /* do failover ? */
+ return ret;
+ }
+
+ switch (cmd) {
+ case COLO_COMMAND_CHECKPOINT_REQUEST:
+ *checkpoint_request = 1;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
void *colo_process_incoming_thread(void *opaque)
{
MigrationIncomingState *mis = opaque;
@@ -93,7 +230,49 @@ void *colo_process_incoming_thread(void *opaque)
*/
qemu_set_block(qemu_get_fd(mis->from_src_file));
- /* TODO: COLO checkpoint restore loop */
+
+ ret = colo_put_cmd(mis->to_src_file, COLO_COMMAND_CHECKPOINT_READY);
+ if (ret < 0) {
+ goto out;
+ }
+
+ while (mis->state == MIGRATION_STATUS_COLO) {
+ int request = 0;
+ int ret = colo_wait_handle_cmd(mis->from_src_file, &request);
+
+ if (ret < 0) {
+ break;
+ } else {
+ if (!request) {
+ continue;
+ }
+ }
+ /* FIXME: This is unnecessary for periodic checkpoint mode */
+ ret = colo_put_cmd(mis->to_src_file, COLO_COMMAND_CHECKPOINT_REPLY);
+ if (ret < 0) {
+ goto out;
+ }
+
+ ret = colo_get_check_cmd(mis->from_src_file,
+ COLO_COMMAND_VMSTATE_SEND);
+ if (ret < 0) {
+ goto out;
+ }
+
+ /* TODO: read migration data into colo buffer */
+
+ ret = colo_put_cmd(mis->to_src_file, COLO_COMMAND_VMSTATE_RECEIVED);
+ if (ret < 0) {
+ goto out;
+ }
+
+ /* TODO: load vm state */
+
+ ret = colo_put_cmd(mis->to_src_file, COLO_COMMAND_VMSTATE_LOADED);
+ if (ret < 0) {
+ goto out;
+ }
+ }
out:
if (ret < 0) {
diff --git a/qapi-schema.json b/qapi-schema.json
index c9ff34e..85f7800 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -720,6 +720,31 @@
{ 'command': 'migrate-start-postcopy' }
##
+# @COLOCommand
+#
+# The commands for COLO fault tolerance
+#
+# @checkpoint-ready: SVM is ready for checkpointing
+#
+# @checkpoint-request: PVM tells SVM to prepare for new checkpointing
+#
+# @checkpoint-reply: SVM gets PVM's checkpoint request
+#
+# @vmstate-send: VM's state will be sent by PVM.
+#
+# @vmstate-size: The total size of VMstate.
+#
+# @vmstate-received: VM's state has been received by SVM.
+#
+# @vmstate-loaded: VM's state has been loaded by SVM.
+#
+# Since: 2.6
+##
+{ 'enum': 'COLOCommand',
+ 'data': [ 'checkpoint-ready', 'checkpoint-request', 'checkpoint-reply',
+ 'vmstate-send', 'vmstate-size','vmstate-received',
+ 'vmstate-loaded' ] }
+
# @MouseInfo:
#
# Information about a mouse device.
diff --git a/trace-events b/trace-events
index 5565e79..39fdd8d 100644
--- a/trace-events
+++ b/trace-events
@@ -1579,6 +1579,8 @@ postcopy_ram_incoming_cleanup_join(void) ""
# migration/colo.c
colo_vm_state_change(const char *old, const char *new) "Change '%s' => '%s'"
+colo_put_cmd(const char *msg) "Send '%s' cmd"
+colo_get_cmd(const char *msg) "Receive '%s' cmd"
# kvm-all.c
kvm_ioctl(int type, void *arg) "type 0x%x, arg %p"
--
1.8.3.1