2 * COarse-grain LOck-stepping Virtual Machines for Non-stop Service (COLO)
3 * (a.k.a. Fault Tolerance or Continuous Replication)
5 * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
6 * Copyright (c) 2016 FUJITSU LIMITED
7 * Copyright (c) 2016 Intel Corporation
9 * This work is licensed under the terms of the GNU GPL, version 2 or
10 * later. See the COPYING file in the top-level directory.
13 #include "qemu/osdep.h"
14 #include "sysemu/sysemu.h"
15 #include "migration/colo.h"
17 #include "qemu/error-report.h"
18 #include "qapi/error.h"
20 bool colo_supported(void)
25 bool migration_in_colo_state(void)
27 MigrationState
*s
= migrate_get_current();
29 return (s
->state
== MIGRATION_STATUS_COLO
);
32 bool migration_incoming_in_colo_state(void)
34 MigrationIncomingState
*mis
= migration_incoming_get_current();
36 return mis
&& (mis
->state
== MIGRATION_STATUS_COLO
);
39 static void colo_send_message(QEMUFile
*f
, COLOMessage msg
,
44 if (msg
>= COLO_MESSAGE__MAX
) {
45 error_setg(errp
, "%s: Invalid message", __func__
);
48 qemu_put_be32(f
, msg
);
51 ret
= qemu_file_get_error(f
);
53 error_setg_errno(errp
, -ret
, "Can't send COLO message");
55 trace_colo_send_message(COLOMessage_lookup
[msg
]);
58 static COLOMessage
colo_receive_message(QEMUFile
*f
, Error
**errp
)
63 msg
= qemu_get_be32(f
);
64 ret
= qemu_file_get_error(f
);
66 error_setg_errno(errp
, -ret
, "Can't receive COLO message");
69 if (msg
>= COLO_MESSAGE__MAX
) {
70 error_setg(errp
, "%s: Invalid message", __func__
);
73 trace_colo_receive_message(COLOMessage_lookup
[msg
]);
77 static void colo_receive_check_message(QEMUFile
*f
, COLOMessage expect_msg
,
81 Error
*local_err
= NULL
;
83 msg
= colo_receive_message(f
, &local_err
);
85 error_propagate(errp
, local_err
);
88 if (msg
!= expect_msg
) {
89 error_setg(errp
, "Unexpected COLO message %d, expected %d",
94 static int colo_do_checkpoint_transaction(MigrationState
*s
)
96 Error
*local_err
= NULL
;
98 colo_send_message(s
->to_dst_file
, COLO_MESSAGE_CHECKPOINT_REQUEST
,
104 colo_receive_check_message(s
->rp_state
.from_dst_file
,
105 COLO_MESSAGE_CHECKPOINT_REPLY
, &local_err
);
110 /* TODO: suspend and save vm state to colo buffer */
112 colo_send_message(s
->to_dst_file
, COLO_MESSAGE_VMSTATE_SEND
, &local_err
);
117 /* TODO: send vmstate to Secondary */
119 colo_receive_check_message(s
->rp_state
.from_dst_file
,
120 COLO_MESSAGE_VMSTATE_RECEIVED
, &local_err
);
125 colo_receive_check_message(s
->rp_state
.from_dst_file
,
126 COLO_MESSAGE_VMSTATE_LOADED
, &local_err
);
131 /* TODO: resume Primary */
136 error_report_err(local_err
);
141 static void colo_process_checkpoint(MigrationState
*s
)
143 Error
*local_err
= NULL
;
146 s
->rp_state
.from_dst_file
= qemu_file_get_return_path(s
->to_dst_file
);
147 if (!s
->rp_state
.from_dst_file
) {
148 error_report("Open QEMUFile from_dst_file failed");
153 * Wait for Secondary finish loading VM states and enter COLO
156 colo_receive_check_message(s
->rp_state
.from_dst_file
,
157 COLO_MESSAGE_CHECKPOINT_READY
, &local_err
);
162 qemu_mutex_lock_iothread();
164 qemu_mutex_unlock_iothread();
165 trace_colo_vm_state_change("stop", "run");
167 while (s
->state
== MIGRATION_STATUS_COLO
) {
168 ret
= colo_do_checkpoint_transaction(s
);
175 /* Throw the unreported error message after exited from loop */
177 error_report_err(local_err
);
180 if (s
->rp_state
.from_dst_file
) {
181 qemu_fclose(s
->rp_state
.from_dst_file
);
185 void migrate_start_colo_process(MigrationState
*s
)
187 qemu_mutex_unlock_iothread();
188 migrate_set_state(&s
->state
, MIGRATION_STATUS_ACTIVE
,
189 MIGRATION_STATUS_COLO
);
190 colo_process_checkpoint(s
);
191 qemu_mutex_lock_iothread();
194 static void colo_wait_handle_message(QEMUFile
*f
, int *checkpoint_request
,
198 Error
*local_err
= NULL
;
200 msg
= colo_receive_message(f
, &local_err
);
202 error_propagate(errp
, local_err
);
207 case COLO_MESSAGE_CHECKPOINT_REQUEST
:
208 *checkpoint_request
= 1;
211 *checkpoint_request
= 0;
212 error_setg(errp
, "Got unknown COLO message: %d", msg
);
217 void *colo_process_incoming_thread(void *opaque
)
219 MigrationIncomingState
*mis
= opaque
;
220 Error
*local_err
= NULL
;
222 migrate_set_state(&mis
->state
, MIGRATION_STATUS_ACTIVE
,
223 MIGRATION_STATUS_COLO
);
225 mis
->to_src_file
= qemu_file_get_return_path(mis
->from_src_file
);
226 if (!mis
->to_src_file
) {
227 error_report("COLO incoming thread: Open QEMUFile to_src_file failed");
231 * Note: the communication between Primary side and Secondary side
232 * should be sequential, we set the fd to unblocked in migration incoming
233 * coroutine, and here we are in the COLO incoming thread, so it is ok to
234 * set the fd back to blocked.
236 qemu_file_set_blocking(mis
->from_src_file
, true);
238 colo_send_message(mis
->to_src_file
, COLO_MESSAGE_CHECKPOINT_READY
,
244 while (mis
->state
== MIGRATION_STATUS_COLO
) {
247 colo_wait_handle_message(mis
->from_src_file
, &request
, &local_err
);
252 /* FIXME: This is unnecessary for periodic checkpoint mode */
253 colo_send_message(mis
->to_src_file
, COLO_MESSAGE_CHECKPOINT_REPLY
,
259 colo_receive_check_message(mis
->from_src_file
,
260 COLO_MESSAGE_VMSTATE_SEND
, &local_err
);
265 /* TODO: read migration data into colo buffer */
267 colo_send_message(mis
->to_src_file
, COLO_MESSAGE_VMSTATE_RECEIVED
,
273 /* TODO: load vm state */
275 colo_send_message(mis
->to_src_file
, COLO_MESSAGE_VMSTATE_LOADED
,
283 /* Throw the unreported error message after exited from loop */
285 error_report_err(local_err
);
288 if (mis
->to_src_file
) {
289 qemu_fclose(mis
->to_src_file
);
291 migration_incoming_exit_colo();