aboutsummaryrefslogtreecommitdiff
path: root/migration
diff options
context:
space:
mode:
authorDr. David Alan Gilbert <dgilbert@redhat.com>2015-11-05 18:10:45 +0000
committerJuan Quintela <quintela@redhat.com>2015-11-10 15:00:25 +0100
commitc76ca1888f49b4155a9de5a915dc9f814800c817 (patch)
tree5b44b1cbb71dfecf34d8afbfe0d17470eee627e9 /migration
parent3e4097b564386b1fd1b62f2cd20e056d4b3403da (diff)
Migration commands
Create QEMU_VM_COMMAND section type for sending commands from source to destination. These commands are not intended to convey guest state but to control the migration process. For use in postcopy. Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Reviewed-by: Amit Shah <amit.shah@redhat.com> Reviewed-by: Juan Quintela <quintela@redhat.com> Signed-off-by: Juan Quintela <quintela@redhat.com>
Diffstat (limited to 'migration')
-rw-r--r--migration/savevm.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/migration/savevm.c b/migration/savevm.c
index fed41e6d0d..a6829e1fe6 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -59,6 +59,14 @@
static bool skip_section_footers;
+static struct mig_cmd_args {
+ ssize_t len; /* -1 = variable */
+ const char *name;
+} mig_cmd_args[] = {
+ [MIG_CMD_INVALID] = { .len = -1, .name = "INVALID" },
+ [MIG_CMD_MAX] = { .len = -1, .name = "MAX" },
+};
+
static int announce_self_create(uint8_t *buf,
uint8_t *mac_addr)
{
@@ -694,6 +702,28 @@ static void save_section_footer(QEMUFile *f, SaveStateEntry *se)
}
}
+/**
+ * qemu_savevm_command_send: Send a 'QEMU_VM_COMMAND' type element with the
+ * command and associated data.
+ *
+ * @f: File to send command on
+ * @command: Command type to send
+ * @len: Length of associated data
+ * @data: Data associated with command.
+ */
+void qemu_savevm_command_send(QEMUFile *f,
+ enum qemu_vm_cmd command,
+ uint16_t len,
+ uint8_t *data)
+{
+ trace_savevm_command_send(command, len);
+ qemu_put_byte(f, QEMU_VM_COMMAND);
+ qemu_put_be16(f, (uint16_t)command);
+ qemu_put_be16(f, len);
+ qemu_put_buffer(f, data, len);
+ qemu_fflush(f);
+}
+
bool qemu_savevm_state_blocked(Error **errp)
{
SaveStateEntry *se;
@@ -1004,6 +1034,41 @@ static SaveStateEntry *find_se(const char *idstr, int instance_id)
return NULL;
}
+/**
+ * loadvm_process_command: Process an incoming 'QEMU_VM_COMMAND'
+ *
+ * Returns: 0 on success, negative on error (in which case it will issue an
+ * error message).
+ * @f: The stream to read the command data from.
+ */
+static int loadvm_process_command(QEMUFile *f)
+{
+ uint16_t cmd;
+ uint16_t len;
+
+ cmd = qemu_get_be16(f);
+ len = qemu_get_be16(f);
+
+ trace_loadvm_process_command(cmd, len);
+ if (cmd >= MIG_CMD_MAX || cmd == MIG_CMD_INVALID) {
+ error_report("MIG_CMD 0x%x unknown (len 0x%x)", cmd, len);
+ return -EINVAL;
+ }
+
+ if (mig_cmd_args[cmd].len != -1 && mig_cmd_args[cmd].len != len) {
+ error_report("%s received with bad length - expecting %zu, got %d",
+ mig_cmd_args[cmd].name,
+ (size_t)mig_cmd_args[cmd].len, len);
+ return -ERANGE;
+ }
+
+ switch (cmd) {
+ /* Filling added in next patch */
+ }
+
+ return 0;
+}
+
struct LoadStateEntry {
QLIST_ENTRY(LoadStateEntry) entry;
SaveStateEntry *se;
@@ -1183,6 +1248,12 @@ int qemu_loadvm_state(QEMUFile *f)
goto out;
}
break;
+ case QEMU_VM_COMMAND:
+ ret = loadvm_process_command(f);
+ if (ret < 0) {
+ goto out;
+ }
+ break;
default:
error_report("Unknown savevm section type %d", section_type);
ret = -EINVAL;