@@ -313,6 +313,9 @@ static int colo_wait_handle_cmd(QEMUFile *f, int *checkpoint_request)
void *colo_process_incoming_thread(void *opaque)
{
MigrationIncomingState *mis = opaque;
+ QEMUFile *fb = NULL;
+ QEMUSizedBuffer *buffer = NULL; /* Cache incoming device state */
+ int total_size;
int fd, ret = 0;
migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE,
@@ -336,6 +339,12 @@ void *colo_process_incoming_thread(void *opaque)
goto out;
}
+ buffer = qsb_create(NULL, COLO_BUFFER_BASE_SIZE);
+ if (buffer == NULL) {
+ error_report("Failed to allocate colo buffer!");
+ goto out;
+ }
+
ret = colo_ctl_put(mis->to_src_file, COLO_CMD_CHECKPOINT_READY, 0);
if (ret < 0) {
goto out;
@@ -363,20 +372,50 @@ void *colo_process_incoming_thread(void *opaque)
goto out;
}
- /*TODO Load VM state */
+ /* read the VM state total size first */
+ total_size = colo_ctl_get(mis->from_src_file, COLO_CMD_VMSTATE_SIZE);
+ if (total_size <= 0) {
+ goto out;
+ }
+
+ /* read vm device state into colo buffer */
+ ret = qsb_fill_buffer(buffer, mis->from_src_file, total_size);
+ if (ret != total_size) {
+ error_report("can't get all migration data");
+ goto out;
+ }
ret = colo_ctl_put(mis->to_src_file, COLO_CMD_VMSTATE_RECEIVED, 0);
if (ret < 0) {
goto out;
}
+ /* open colo buffer for read */
+ fb = qemu_bufopen("r", buffer);
+ if (!fb) {
+ error_report("can't open colo buffer for read");
+ goto out;
+ }
+
+ qemu_mutex_lock_iothread();
+ qemu_system_reset(VMRESET_SILENT);
+ if (qemu_loadvm_state(fb) < 0) {
+ error_report("COLO: loadvm failed");
+ qemu_mutex_unlock_iothread();
+ goto out;
+ }
+ qemu_mutex_unlock_iothread();
+
/* TODO: flush vm state */
ret = colo_ctl_put(mis->to_src_file, COLO_CMD_VMSTATE_LOADED, 0);
if (ret < 0) {
goto out;
}
-}
+
+ qemu_fclose(fb);
+ fb = NULL;
+ }
out:
if (ret < 0) {
@@ -384,6 +423,11 @@ out:
strerror(-ret));
}
+ if (fb) {
+ qemu_fclose(fb);
+ }
+ qsb_free(buffer);
+
qemu_mutex_lock_iothread();
colo_release_ram_cache();
qemu_mutex_unlock_iothread();
@@ -391,6 +435,7 @@ out:
if (mis->to_src_file) {
qemu_fclose(mis->to_src_file);
}
+
migration_incoming_exit_colo();
return NULL;