@@ -57,6 +57,7 @@ struct MigrationIncomingState {
QemuThread colo_incoming_thread;
/* The coroutine we should enter (back) after failover */
Coroutine *migration_incoming_co;
+ QEMUSizedBuffer *colo_buffer; /* Cache incoming device state */
/* See savevm.c */
LoadStateEntry_Head loadvm_handlers;
@@ -332,7 +332,8 @@ void *colo_process_incoming_checkpoints(void *opaque)
MigrationIncomingState *mis = opaque;
QEMUFile *f = mis->file;
int fd = qemu_get_fd(f);
- QEMUFile *ctl = NULL;
+ QEMUFile *ctl = NULL, *fb = NULL;
+ uint64_t total_size;
int ret;
migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE,
@@ -349,6 +350,12 @@ void *colo_process_incoming_checkpoints(void *opaque)
goto out;
}
+ mis->colo_buffer = qsb_create(NULL, COLO_BUFFER_BASE_SIZE);
+ if (mis->colo_buffer == NULL) {
+ error_report("Failed to allocate colo buffer!");
+ goto out;
+ }
+
ret = colo_ctl_put(ctl, COLO_CHECPOINT_READY);
if (ret < 0) {
goto out;
@@ -388,13 +395,40 @@ void *colo_process_incoming_checkpoints(void *opaque)
goto out;
}
- /*TODO Load VM state */
+ /* read the VM state total size first */
+ ret = colo_ctl_get_value(f, &total_size);
+ if (ret < 0) {
+ goto out;
+ }
+
+ /* read vm device state into colo buffer */
+ ret = qsb_fill_buffer(mis->colo_buffer, f, total_size);
+ if (ret != total_size) {
+ error_report("can't get all migration data");
+ goto out;
+ }
ret = colo_ctl_put(ctl, COLO_CHECKPOINT_RECEIVED);
if (ret < 0) {
goto out;
}
+ /* open colo buffer for read */
+ fb = qemu_bufopen("r", mis->colo_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(ctl, COLO_CHECKPOINT_LOADED);
@@ -407,13 +441,23 @@ void *colo_process_incoming_checkpoints(void *opaque)
vm_start();
qemu_mutex_unlock_iothread();
trace_colo_vm_state_change("stop", "start");
-}
+
+ qemu_fclose(fb);
+ fb = NULL;
+ }
out:
+ if (fb) {
+ qemu_fclose(fb);
+ }
+
release_ram_cache();
if (ctl) {
qemu_fclose(ctl);
}
+
+ qsb_free(mis->colo_buffer);
+
migration_incoming_exit_colo();
return NULL;