COLO: Load VMState into QIOChannelBuffer before restore it
We should not destroy the state of SVM (Secondary VM) until we receive the complete data of PVM's state, in case the primary fails in the process of sending the state, so we cache the VM's state in secondary side before load it into SVM. Besides, we should call qemu_system_reset() before load VM state, which can ensure the data is intact. Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com> Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com> Signed-off-by: Gonglei <arei.gonglei@huawei.com> Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Cc: Dr. David Alan Gilbert <dgilbert@redhat.com> Reviewed-by: Amit Shah <amit.shah@redhat.com> Signed-off-by: Amit Shah <amit@amitshah.net>
This commit is contained in:
parent
a91246c95f
commit
4291d372e2
@ -115,6 +115,28 @@ static void colo_receive_check_message(QEMUFile *f, COLOMessage expect_msg,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint64_t colo_receive_message_value(QEMUFile *f, uint32_t expect_msg,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
Error *local_err = NULL;
|
||||||
|
uint64_t value;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
colo_receive_check_message(f, expect_msg, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = qemu_get_be64(f);
|
||||||
|
ret = qemu_file_get_error(f);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_setg_errno(errp, -ret, "Failed to get value for COLO message: %s",
|
||||||
|
COLOMessage_lookup[expect_msg]);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
static int colo_do_checkpoint_transaction(MigrationState *s,
|
static int colo_do_checkpoint_transaction(MigrationState *s,
|
||||||
QIOChannelBuffer *bioc,
|
QIOChannelBuffer *bioc,
|
||||||
QEMUFile *fb)
|
QEMUFile *fb)
|
||||||
@ -288,6 +310,10 @@ static void colo_wait_handle_message(QEMUFile *f, int *checkpoint_request,
|
|||||||
void *colo_process_incoming_thread(void *opaque)
|
void *colo_process_incoming_thread(void *opaque)
|
||||||
{
|
{
|
||||||
MigrationIncomingState *mis = opaque;
|
MigrationIncomingState *mis = opaque;
|
||||||
|
QEMUFile *fb = NULL;
|
||||||
|
QIOChannelBuffer *bioc = NULL; /* Cache incoming device state */
|
||||||
|
uint64_t total_size;
|
||||||
|
uint64_t value;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE,
|
migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE,
|
||||||
@ -306,6 +332,10 @@ void *colo_process_incoming_thread(void *opaque)
|
|||||||
*/
|
*/
|
||||||
qemu_file_set_blocking(mis->from_src_file, true);
|
qemu_file_set_blocking(mis->from_src_file, true);
|
||||||
|
|
||||||
|
bioc = qio_channel_buffer_new(COLO_BUFFER_BASE_SIZE);
|
||||||
|
fb = qemu_fopen_channel_input(QIO_CHANNEL(bioc));
|
||||||
|
object_unref(OBJECT(bioc));
|
||||||
|
|
||||||
colo_send_message(mis->to_src_file, COLO_MESSAGE_CHECKPOINT_READY,
|
colo_send_message(mis->to_src_file, COLO_MESSAGE_CHECKPOINT_READY,
|
||||||
&local_err);
|
&local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
@ -333,7 +363,29 @@ void *colo_process_incoming_thread(void *opaque)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: read migration data into colo buffer */
|
value = colo_receive_message_value(mis->from_src_file,
|
||||||
|
COLO_MESSAGE_VMSTATE_SIZE, &local_err);
|
||||||
|
if (local_err) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read VM device state data into channel buffer,
|
||||||
|
* It's better to re-use the memory allocated.
|
||||||
|
* Here we need to handle the channel buffer directly.
|
||||||
|
*/
|
||||||
|
if (value > bioc->capacity) {
|
||||||
|
bioc->capacity = value;
|
||||||
|
bioc->data = g_realloc(bioc->data, bioc->capacity);
|
||||||
|
}
|
||||||
|
total_size = qemu_get_buffer(mis->from_src_file, bioc->data, value);
|
||||||
|
if (total_size != value) {
|
||||||
|
error_report("Got %" PRIu64 " VMState data, less than expected"
|
||||||
|
" %" PRIu64, total_size, value);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
bioc->usage = total_size;
|
||||||
|
qio_channel_io_seek(QIO_CHANNEL(bioc), 0, 0, NULL);
|
||||||
|
|
||||||
colo_send_message(mis->to_src_file, COLO_MESSAGE_VMSTATE_RECEIVED,
|
colo_send_message(mis->to_src_file, COLO_MESSAGE_VMSTATE_RECEIVED,
|
||||||
&local_err);
|
&local_err);
|
||||||
@ -341,7 +393,14 @@ void *colo_process_incoming_thread(void *opaque)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: load vm state */
|
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();
|
||||||
|
|
||||||
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);
|
||||||
@ -356,6 +415,10 @@ out:
|
|||||||
error_report_err(local_err);
|
error_report_err(local_err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fb) {
|
||||||
|
qemu_fclose(fb);
|
||||||
|
}
|
||||||
|
|
||||||
if (mis->to_src_file) {
|
if (mis->to_src_file) {
|
||||||
qemu_fclose(mis->to_src_file);
|
qemu_fclose(mis->to_src_file);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user