[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH COLO-Frame v11 10/39] COLO: Implement colo checkpoin
From: |
zhanghailiang |
Subject: |
[Qemu-devel] [PATCH COLO-Frame v11 10/39] COLO: Implement colo checkpoint protocol |
Date: |
Tue, 24 Nov 2015 17:25:20 +0800 |
We need communications protocol of user-defined to control the checkpoint
process.
The new checkpoint request is started by Primary VM, and the interactive process
like below:
Checkpoint synchronizing points,
Primary Secondary
initial work
'checkpoint-ready' <------------------------------ @
'checkpoint-request' @ ----------------------------->
Suspend (Only in hybrid
mode)
'checkpoint-reply' <------------------------------ @
Suspend&Save state
'vmstate-send' @ ----------------------------->
Send state Receive state
'vmstate-received' <------------------------------ @
Release packets Load state
'vmstate-load' <------------------------------ @
Resume Resume (Only in hybrid
mode)
Start Comparing (Only in hybrid mode)
NOTE:
1) '@' who sends the message
2) Every sync-point is synchronized by two sides with only
one handshake(single direction) for low-latency.
If more strict synchronization is required, a opposite direction
sync-point should be added.
3) Since sync-points are single direction, the remote side may
go forward a lot when this side just receives the sync-point.
4) For now, we only support 'periodic' checkpoint, for which
the Secondary VM is not running, later we will support 'hybrid' mode.
Signed-off-by: zhanghailiang <address@hidden>
Signed-off-by: Li Zhijian <address@hidden>
Signed-off-by: Gonglei <address@hidden>
Cc: Eric Blake <address@hidden>
---
v11:
- Add missing 'checkpoint-ready' communication in comment.
- Use parameter to return 'value' for colo_ctl_get() (Dave's suggestion)
- Fix trace for colo_ctl_get() to trace command and value both
v10:
- Rename enum COLOCmd to COLOCommand (Eric's suggestion).
- Remove unused 'ram-steal'
---
migration/colo.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
qapi-schema.json | 27 ++++++++
trace-events | 2 +
3 files changed, 225 insertions(+), 2 deletions(-)
diff --git a/migration/colo.c b/migration/colo.c
index 0ab9618..c045d61 100644
--- a/migration/colo.c
+++ b/migration/colo.c
@@ -10,10 +10,12 @@
* later. See the COPYING file in the top-level directory.
*/
+#include <unistd.h>
#include "sysemu/sysemu.h"
#include "migration/colo.h"
#include "trace.h"
#include "qemu/error-report.h"
+#include "qemu/sockets.h"
bool colo_supported(void)
{
@@ -34,9 +36,107 @@ bool migration_incoming_in_colo_state(void)
return mis && (mis->state == MIGRATION_STATUS_COLO);
}
+/* colo checkpoint control helper */
+static int colo_ctl_put(QEMUFile *f, uint32_t cmd, uint64_t value)
+{
+ int ret = 0;
+
+ qemu_put_be32(f, cmd);
+ qemu_put_be64(f, value);
+ qemu_fflush(f);
+
+ ret = qemu_file_get_error(f);
+ trace_colo_ctl_put(COLOCommand_lookup[cmd], value);
+
+ return ret;
+}
+
+static int colo_ctl_get_cmd(QEMUFile *f, uint32_t *cmd)
+{
+ int ret = 0;
+
+ *cmd = qemu_get_be32(f);
+ ret = qemu_file_get_error(f);
+ if (ret < 0) {
+ return ret;
+ }
+ if (*cmd >= COLO_COMMAND_MAX) {
+ error_report("Invalid colo command, got cmd:%d", *cmd);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int colo_ctl_get(QEMUFile *f, uint32_t require, uint64_t *value)
+{
+ int ret;
+ uint32_t cmd;
+
+ ret = colo_ctl_get_cmd(f, &cmd);
+ if (ret < 0) {
+ return ret;
+ }
+ if (cmd != require) {
+ error_report("Unexpect colo command, expect:%d, but got cmd:%d",
+ require, cmd);
+ return -EINVAL;
+ }
+
+ *value = qemu_get_be64(f);
+ trace_colo_ctl_get(COLOCommand_lookup[cmd], *value);
+ ret = qemu_file_get_error(f);
+
+ return ret;
+}
+
+static int colo_do_checkpoint_transaction(MigrationState *s)
+{
+ int ret;
+ uint64_t value;
+
+ ret = colo_ctl_put(s->to_dst_file, COLO_COMMAND_CHECKPOINT_REQUEST, 0);
+ if (ret < 0) {
+ goto out;
+ }
+
+ ret = colo_ctl_get(s->rp_state.from_dst_file,
+ COLO_COMMAND_CHECKPOINT_REPLY, &value);
+ if (ret < 0) {
+ goto out;
+ }
+
+ /* TODO: suspend and save vm state to colo buffer */
+
+ ret = colo_ctl_put(s->to_dst_file, COLO_COMMAND_VMSTATE_SEND, 0);
+ if (ret < 0) {
+ goto out;
+ }
+
+ /* TODO: send vmstate to Secondary */
+
+ ret = colo_ctl_get(s->rp_state.from_dst_file,
+ COLO_COMMAND_VMSTATE_RECEIVED, &value);
+ if (ret < 0) {
+ goto out;
+ }
+
+ ret = colo_ctl_get(s->rp_state.from_dst_file,
+ COLO_COMMAND_VMSTATE_LOADED, &value);
+ if (ret < 0) {
+ goto out;
+ }
+
+ /* TODO: resume Primary */
+
+out:
+ return ret;
+}
+
static void colo_process_checkpoint(MigrationState *s)
{
int ret = 0;
+ uint64_t value;
s->rp_state.from_dst_file = qemu_file_get_return_path(s->to_dst_file);
if (!s->rp_state.from_dst_file) {
@@ -45,12 +145,28 @@ static void colo_process_checkpoint(MigrationState *s)
goto out;
}
+ /*
+ * Wait for Secondary finish loading vm states and enter COLO
+ * restore.
+ */
+ ret = colo_ctl_get(s->rp_state.from_dst_file,
+ COLO_COMMAND_CHECKPOINT_READY, &value);
+ 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,10 +189,46 @@ 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;
+ uint64_t value;
+
+ ret = colo_ctl_get_cmd(f, &cmd);
+ if (ret < 0) {
+ /* do failover ? */
+ return ret;
+ }
+ /* Fix me: this value should be 0, which is not so good,
+ * should be used for checking ?
+ */
+ value = qemu_get_be64(f);
+ if (value != 0) {
+ error_report("Got unexpected value %" PRIu64 " for '%s' command",
+ value, COLOCommand_lookup[cmd]);
+ return -EINVAL;
+ }
+
+ 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;
int ret = 0;
+ uint64_t value;
migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE,
MIGRATION_STATUS_COLO);
@@ -93,7 +245,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_ctl_put(mis->to_src_file, COLO_COMMAND_CHECKPOINT_READY, 0);
+ 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_ctl_put(mis->to_src_file, COLO_COMMAND_CHECKPOINT_REPLY, 0);
+ if (ret < 0) {
+ goto out;
+ }
+
+ ret = colo_ctl_get(mis->from_src_file, COLO_COMMAND_VMSTATE_SEND,
+ &value);
+ if (ret < 0) {
+ goto out;
+ }
+
+ /* TODO: read migration data into colo buffer */
+
+ ret = colo_ctl_put(mis->to_src_file, COLO_COMMAND_VMSTATE_RECEIVED, 0);
+ if (ret < 0) {
+ goto out;
+ }
+
+ /* TODO: load vm state */
+
+ ret = colo_ctl_put(mis->to_src_file, COLO_COMMAND_VMSTATE_LOADED, 0);
+ if (ret < 0) {
+ goto out;
+ }
+ }
out:
if (ret < 0) {
diff --git a/qapi-schema.json b/qapi-schema.json
index c2f3b63..48a87af 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -722,6 +722,33 @@
{ 'command': 'migrate-start-postcopy' }
##
+# @COLOCommand
+#
+# The commands for COLO fault tolerance
+#
+# @invalid: unknown command
+#
+# @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': [ 'invalid', '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 c98d473..f8a0959 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_ctl_put(const char *msg, uint64_t value) "Send '%s' cmd, value: %"
PRIu64""
+colo_ctl_get(const char *msg, uint64_t value) "Receive '%s' cmd, value: %"
PRIu64""
# kvm-all.c
kvm_ioctl(int type, void *arg) "type 0x%x, arg %p"
--
1.8.3.1
- [Qemu-devel] [PATCH COLO-Frame v11 05/39] migration: Add state records for migration incoming, (continued)
- [Qemu-devel] [PATCH COLO-Frame v11 05/39] migration: Add state records for migration incoming, zhanghailiang, 2015/11/24
- [Qemu-devel] [PATCH COLO-Frame v11 02/39] migration: Introduce capability 'x-colo' to migration, zhanghailiang, 2015/11/24
- [Qemu-devel] [PATCH COLO-Frame v11 20/39] COLO: synchronize PVM's state to SVM periodically, zhanghailiang, 2015/11/24
- [Qemu-devel] [PATCH COLO-Frame v11 28/39] COLO failover: Don't do failover during loading VM's state, zhanghailiang, 2015/11/24
- [Qemu-devel] [PATCH COLO-Frame v11 19/39] COLO: Add checkpoint-delay parameter for migrate-set-parameters, zhanghailiang, 2015/11/24
- [Qemu-devel] [PATCH COLO-Frame v11 30/39] COLO: Update the global runstate after going into colo state, zhanghailiang, 2015/11/24
- [Qemu-devel] [PATCH COLO-Frame v11 32/39] COLO: Separate the process of saving/loading ram and device state, zhanghailiang, 2015/11/24
- [Qemu-devel] [PATCH COLO-Frame v11 38/39] colo: Use default buffer-filter to buffer and release packets, zhanghailiang, 2015/11/24
- [Qemu-devel] [PATCH COLO-Frame v11 09/39] COLO/migration: Create a new communication path from destination to source, zhanghailiang, 2015/11/24
- [Qemu-devel] [PATCH COLO-Frame v11 10/39] COLO: Implement colo checkpoint protocol,
zhanghailiang <=
- [Qemu-devel] [PATCH COLO-Frame v11 12/39] QEMUSizedBuffer: Introduce two help functions for qsb, zhanghailiang, 2015/11/24
- [Qemu-devel] [PATCH COLO-Frame v11 11/39] COLO: Add a new RunState RUN_STATE_COLO, zhanghailiang, 2015/11/24
- [Qemu-devel] [PATCH COLO-Frame v11 14/39] ram: Split host_from_stream_offset() into two helper functions, zhanghailiang, 2015/11/24
- [Qemu-devel] [PATCH COLO-Frame v11 23/39] COLO: Implement failover work for Primary VM, zhanghailiang, 2015/11/24
- [Qemu-devel] [PATCH COLO-Frame v11 25/39] COLO: implement default failover treatment, zhanghailiang, 2015/11/24
- [Qemu-devel] [PATCH COLO-Frame v11 34/39] net/filter-buffer: Add default filter-buffer for each netdev, zhanghailiang, 2015/11/24