@@ -2260,6 +2260,7 @@ void migrate_init(MigrationState *s)
error_free(s->error);
s->error = NULL;
s->hostname = NULL;
+ s->vmdesc = NULL;
migrate_set_state(&s->state, MIGRATION_STATUS_NONE, MIGRATION_STATUS_SETUP);
@@ -1206,13 +1206,25 @@ void qemu_savevm_non_migratable_list(strList **reasons)
void qemu_savevm_state_header(QEMUFile *f)
{
+ MigrationState *s = migrate_get_current();
+
+ s->vmdesc = json_writer_new(false);
+
trace_savevm_state_header();
qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
qemu_put_be32(f, QEMU_VM_FILE_VERSION);
- if (migrate_get_current()->send_configuration) {
+ if (s->send_configuration) {
qemu_put_byte(f, QEMU_VM_CONFIGURATION);
- vmstate_save_state(f, &vmstate_configuration, &savevm_state, 0);
+ /*
+ * This starts the main json object and is paired with the
+ * json_writer_end_object in
+ * qemu_savevm_state_complete_precopy_non_iterable
+ */
+ json_writer_start_object(s->vmdesc, NULL);
+ json_writer_start_object(s->vmdesc, "configuration");
+ vmstate_save_state(f, &vmstate_configuration, &savevm_state, s->vmdesc);
+ json_writer_end_object(s->vmdesc);
}
}
@@ -1237,8 +1249,6 @@ void qemu_savevm_state_setup(QEMUFile *f)
Error *local_err = NULL;
int ret;
- ms->vmdesc = json_writer_new(false);
- json_writer_start_object(ms->vmdesc, NULL);
json_writer_int64(ms->vmdesc, "page_size", qemu_target_page_size());
json_writer_start_array(ms->vmdesc, "devices");
@@ -23,7 +23,7 @@
import collections
import struct
import sys
-
+import math
def mkdir_p(path):
try:
@@ -119,11 +119,16 @@ def __init__(self, file, version_id, ramargs, section_key):
self.file = file
self.section_key = section_key
self.TARGET_PAGE_SIZE = ramargs['page_size']
+ self.TARGET_PAGE_BITS = math.log2(self.TARGET_PAGE_SIZE)
self.dump_memory = ramargs['dump_memory']
self.write_memory = ramargs['write_memory']
+ self.fixed_ram = ramargs['fixed-ram']
self.sizeinfo = collections.OrderedDict()
+ self.bitmap_offset = collections.OrderedDict()
+ self.pages_offset = collections.OrderedDict()
self.data = collections.OrderedDict()
self.data['section sizes'] = self.sizeinfo
+ self.ram_read = False
self.name = ''
if self.write_memory:
self.files = { }
@@ -140,7 +145,13 @@ def __str__(self):
def getDict(self):
return self.data
+ def write_or_dump_fixed_ram(self):
+ pass
+
def read(self):
+ if self.fixed_ram and self.ram_read:
+ return
+
# Read all RAM sections
while True:
addr = self.file.read64()
@@ -167,7 +178,26 @@ def read(self):
f.truncate(0)
f.truncate(len)
self.files[self.name] = f
+
+ if self.fixed_ram:
+ bitmap_len = self.file.read32()
+ # skip the pages_offset which we don't need
+ offset = self.file.tell() + 8
+ self.bitmap_offset[self.name] = offset
+ offset = ((offset + bitmap_len + self.TARGET_PAGE_SIZE - 1) //
+ self.TARGET_PAGE_SIZE) * self.TARGET_PAGE_SIZE
+ self.pages_offset[self.name] = offset
+ self.file.file.seek(offset + len)
+
flags &= ~self.RAM_SAVE_FLAG_MEM_SIZE
+ if self.fixed_ram:
+ self.ram_read = True
+ # now we should rewind to the ram page offset of the first
+ # ram section
+ if self.fixed_ram:
+ if self.write_memory or self.dump_memory:
+ self.write_or_dump_fixed_ram()
+ return
if flags & self.RAM_SAVE_FLAG_COMPRESS:
if flags & self.RAM_SAVE_FLAG_CONTINUE:
@@ -208,7 +238,7 @@ def read(self):
# End of RAM section
if flags & self.RAM_SAVE_FLAG_EOS:
- break
+ return
if flags != 0:
raise Exception("Unknown RAM flags: %x" % flags)
@@ -521,6 +551,7 @@ def read(self, desc_only = False, dump_memory = False, write_memory = False):
ramargs['page_size'] = self.vmsd_desc['page_size']
ramargs['dump_memory'] = dump_memory
ramargs['write_memory'] = write_memory
+ ramargs['fixed-ram'] = False
self.section_classes[('ram',0)][1] = ramargs
while True:
@@ -528,8 +559,20 @@ def read(self, desc_only = False, dump_memory = False, write_memory = False):
if section_type == self.QEMU_VM_EOF:
break
elif section_type == self.QEMU_VM_CONFIGURATION:
- section = ConfigurationSection(file)
- section.read()
+ config_desc = self.vmsd_desc.get('configuration')
+ if config_desc is not None:
+ config = VMSDSection(file, 1, config_desc, 'configuration')
+ config.read()
+ caps = config.data.get("configuration/capabilities")
+ if caps is not None:
+ caps = caps.data["capabilities"]
+ if type(caps) != list:
+ caps = [caps]
+ for i in caps:
+ # chomp out string length
+ cap = i.data[1:].decode("utf8")
+ if cap == "fixed-ram":
+ ramargs['fixed-ram'] = True
elif section_type == self.QEMU_VM_SECTION_START or section_type == self.QEMU_VM_SECTION_FULL:
section_id = file.read32()
name = file.readstr()