Split qemu_loadvm_state(), and introduce qemu_loadvm_state_{begin,iterate,complete,async}. qemu_loadvm_state_async() is a function to handle a single incoming section.
Signed-off-by: Yoshiaki Tamura <tamura.yoshi...@lab.ntt.co.jp> --- savevm.c | 206 +++++++++++++++++++++++++++++++++++++++++++------------------- sysemu.h | 2 + 2 files changed, 146 insertions(+), 62 deletions(-) diff --git a/savevm.c b/savevm.c index dc20390..aa4f98c 100644 --- a/savevm.c +++ b/savevm.c @@ -1005,6 +1005,8 @@ typedef struct SaveStateEntry { static QTAILQ_HEAD(savevm_handlers, SaveStateEntry) savevm_handlers = QTAILQ_HEAD_INITIALIZER(savevm_handlers); +static QLIST_HEAD(, LoadStateEntry) loadvm_handlers = + QLIST_HEAD_INITIALIZER(loadvm_handlers); static int global_section_id; static int calculate_new_instance_id(const char *idstr) @@ -1460,14 +1462,9 @@ typedef struct LoadStateEntry { int version_id; } LoadStateEntry; -int qemu_loadvm_state(QEMUFile *f) +int qemu_loadvm_state_begin(QEMUFile *f) { - QLIST_HEAD(, LoadStateEntry) loadvm_handlers = - QLIST_HEAD_INITIALIZER(loadvm_handlers); - LoadStateEntry *le, *new_le; - uint8_t section_type; unsigned int v; - int ret; v = qemu_get_be32(f); if (v != QEMU_VM_FILE_MAGIC) @@ -1481,73 +1478,157 @@ int qemu_loadvm_state(QEMUFile *f) if (v != QEMU_VM_FILE_VERSION) return -ENOTSUP; - while ((section_type = qemu_get_byte(f)) != QEMU_VM_EOF) { - uint32_t instance_id, version_id, section_id; - SaveStateEntry *se; - char idstr[257]; - int len; + return 0; +} - switch (section_type) { - case QEMU_VM_SECTION_START: - case QEMU_VM_SECTION_FULL: - /* Read section start */ - section_id = qemu_get_be32(f); - len = qemu_get_byte(f); - qemu_get_buffer(f, (uint8_t *)idstr, len); - idstr[len] = 0; - instance_id = qemu_get_be32(f); - version_id = qemu_get_be32(f); - - /* Find savevm section */ - se = find_se(idstr, instance_id); - if (se == NULL) { - fprintf(stderr, "Unknown savevm section or instance '%s' %d\n", idstr, instance_id); - ret = -EINVAL; - goto out; - } +static int qemu_loadvm_state_iterate(QEMUFile *f) +{ + LoadStateEntry *le; + uint32_t section_id; + int ret; - /* Validate version */ - if (version_id > se->version_id) { - fprintf(stderr, "savevm: unsupported version %d for '%s' v%d\n", - version_id, idstr, se->version_id); - ret = -EINVAL; - goto out; - } + section_id = qemu_get_be32(f); + + QLIST_FOREACH(le, &loadvm_handlers, entry) { + if (le->section_id == section_id) { + break; + } + } + if (le == NULL) { + fprintf(stderr, "Unknown savevm section %d\n", section_id); + return -EINVAL; + } + + ret = vmstate_load(f, le->se, le->version_id); + if (ret < 0) { + fprintf(stderr, "qemu: warning: error while loading state section id %d\n", + section_id); + return ret; + } + + return 0; +} + +static int qemu_loadvm_state_complete(QEMUFile *f) +{ + LoadStateEntry *le; + uint32_t instance_id, version_id, section_id; + SaveStateEntry *se; + char idstr[257]; + int ret = -1, len; + + /* Read section start */ + section_id = qemu_get_be32(f); + len = qemu_get_byte(f); + qemu_get_buffer(f, (uint8_t *)idstr, len); + idstr[len] = 0; + instance_id = qemu_get_be32(f); + version_id = qemu_get_be32(f); + + /* Find savevm section */ + se = find_se(idstr, instance_id); + if (se == NULL) { + fprintf(stderr, "Unknown savevm section or instance '%s' %d\n", idstr, instance_id); + return -EINVAL; + } + + /* Validate version */ + if (version_id > se->version_id) { + fprintf(stderr, "savevm: unsupported version %d for '%s' v%d\n", + version_id, idstr, se->version_id); + return -EINVAL; + } + + /* Add entry */ + le = qemu_mallocz(sizeof(*le)); + + le->se = se; + le->section_id = section_id; + le->version_id = version_id; + QLIST_INSERT_HEAD(&loadvm_handlers, le, entry); + + ret = vmstate_load(f, le->se, le->version_id); + if (ret < 0) { + fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n", + instance_id, idstr); + return ret; + } + + return 0; +} - /* Add entry */ - le = qemu_mallocz(sizeof(*le)); +int qemu_loadvm_state_async(QEMUFile *f) +{ + LoadStateEntry *le, *new_le; + int ret; + uint8_t section_type; - le->se = se; - le->section_id = section_id; - le->version_id = version_id; - QLIST_INSERT_HEAD(&loadvm_handlers, le, entry); + section_type = qemu_get_byte(f); + switch (section_type) { + case QEMU_VM_SECTION_START: + case QEMU_VM_SECTION_FULL: + ret = qemu_loadvm_state_complete(f); + if (ret < 0) { + goto out_free; + } + break; + case QEMU_VM_SECTION_PART: + case QEMU_VM_SECTION_END: + ret = qemu_loadvm_state_iterate(f); + if (ret < 0) { + goto out_free; + } + break; + case QEMU_VM_EOF: + cpu_synchronize_all_post_init(); + break; + default: + fprintf(stderr, "Unknown savevm section type %d\n", section_type); + ret = -EINVAL; + goto out_free; + } + + ret = section_type; + if (ret != QEMU_VM_EOF) { + goto out; + } - ret = vmstate_load(f, le->se, le->version_id); +out_free: + QLIST_FOREACH_SAFE(le, &loadvm_handlers, entry, new_le) { + QLIST_REMOVE(le, entry); + qemu_free(le); + } +out: + if (qemu_file_has_error(f)) { + ret = -EIO; + } + + return ret; +} + +int qemu_loadvm_state(QEMUFile *f) +{ + LoadStateEntry *le, *new_le; + int ret; + uint8_t section_type; + + ret = qemu_loadvm_state_begin(f); + if (ret < 0) + goto out; + + while ((section_type = qemu_get_byte(f)) != QEMU_VM_EOF) { + switch (section_type) { + case QEMU_VM_SECTION_START: + case QEMU_VM_SECTION_FULL: + ret = qemu_loadvm_state_complete(f); if (ret < 0) { - fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n", - instance_id, idstr); goto out; } break; case QEMU_VM_SECTION_PART: case QEMU_VM_SECTION_END: - section_id = qemu_get_be32(f); - - QLIST_FOREACH(le, &loadvm_handlers, entry) { - if (le->section_id == section_id) { - break; - } - } - if (le == NULL) { - fprintf(stderr, "Unknown savevm section %d\n", section_id); - ret = -EINVAL; - goto out; - } - - ret = vmstate_load(f, le->se, le->version_id); + ret = qemu_loadvm_state_iterate(f); if (ret < 0) { - fprintf(stderr, "qemu: warning: error while loading state section id %d\n", - section_id); goto out; } break; @@ -1568,8 +1649,9 @@ out: qemu_free(le); } - if (qemu_file_has_error(f)) + if (qemu_file_has_error(f)) { ret = -EIO; + } return ret; } diff --git a/sysemu.h b/sysemu.h index 879446a..c576840 100644 --- a/sysemu.h +++ b/sysemu.h @@ -69,6 +69,8 @@ int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable, int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f); int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f); void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f); +int qemu_loadvm_state_begin(QEMUFile *f); +int qemu_loadvm_state_async(QEMUFile *f); int qemu_loadvm_state(QEMUFile *f); #ifdef _WIN32 -- 1.7.0.31.g1df487