From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34563) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YQfCg-0008Qk-S4 for qemu-devel@nongnu.org; Wed, 25 Feb 2015 11:52:59 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YQfCf-0001Dc-KI for qemu-devel@nongnu.org; Wed, 25 Feb 2015 11:52:54 -0500 Received: from mx1.redhat.com ([209.132.183.28]:56911) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YQfCf-0001DP-At for qemu-devel@nongnu.org; Wed, 25 Feb 2015 11:52:53 -0500 From: "Dr. David Alan Gilbert (git)" Date: Wed, 25 Feb 2015 16:51:38 +0000 Message-Id: <1424883128-9841-16-git-send-email-dgilbert@redhat.com> In-Reply-To: <1424883128-9841-1-git-send-email-dgilbert@redhat.com> References: <1424883128-9841-1-git-send-email-dgilbert@redhat.com> Subject: [Qemu-devel] [PATCH v5 15/45] Rework loadvm path for subloops List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: aarcange@redhat.com, yamahata@private.email.ne.jp, quintela@redhat.com, amit.shah@redhat.com, pbonzini@redhat.com, yanghy@cn.fujitsu.com, david@gibson.dropbear.id.au From: "Dr. David Alan Gilbert" Postcopy needs to have two migration streams loading concurrently; one from memory (with the device state) and the other from the fd with the memory transactions. Split the core of qemu_loadvm_state out so we can use it for both. Allow the inner loadvm loop to quit and signal whether the parent should. Signed-off-by: Dr. David Alan Gilbert --- savevm.c | 106 ++++++++++++++++++++++++++++++++++++----------------------- trace-events | 4 +++ 2 files changed, 69 insertions(+), 41 deletions(-) diff --git a/savevm.c b/savevm.c index f42713d..4b619da 100644 --- a/savevm.c +++ b/savevm.c @@ -951,6 +951,16 @@ static SaveStateEntry *find_se(const char *idstr, int instance_id) return NULL; } +/* ORable flags that control the (potentially nested) loadvm_state loops */ +enum LoadVMExitCodes { + /* Quit the loop level that received this command */ + LOADVM_QUIT_LOOP = 1, + /* Quit this loop and our parent */ + LOADVM_QUIT_PARENT = 2, +}; + +static int qemu_loadvm_state_main(QEMUFile *f, MigrationIncomingState *mis); + static int loadvm_process_command_simple_lencheck(const char *name, unsigned int actual, unsigned int expected) @@ -967,6 +977,8 @@ static int loadvm_process_command_simple_lencheck(const char *name, /* * Process an incoming 'QEMU_VM_COMMAND' * negative return on error (will issue error message) + * 0 just a normal return + * 1 All good, but exit the loop */ static int loadvm_process_command(QEMUFile *f) { @@ -1036,36 +1048,13 @@ void loadvm_free_handlers(MigrationIncomingState *mis) } } -int qemu_loadvm_state(QEMUFile *f) +static int qemu_loadvm_state_main(QEMUFile *f, MigrationIncomingState *mis) { - MigrationIncomingState *mis = migration_incoming_get_current(); - Error *local_err = NULL; uint8_t section_type; - unsigned int v; int ret; + int exitcode = 0; - if (qemu_savevm_state_blocked(&local_err)) { - error_report("%s", error_get_pretty(local_err)); - error_free(local_err); - return -EINVAL; - } - - v = qemu_get_be32(f); - if (v != QEMU_VM_FILE_MAGIC) { - error_report("Not a migration stream"); - return -EINVAL; - } - - v = qemu_get_be32(f); - if (v == QEMU_VM_FILE_VERSION_COMPAT) { - error_report("SaveVM v2 format is obsolete and don't work anymore"); - return -ENOTSUP; - } - if (v != QEMU_VM_FILE_VERSION) { - error_report("Unsupported migration stream version"); - return -ENOTSUP; - } - + trace_qemu_loadvm_state_main(); while ((section_type = qemu_get_byte(f)) != QEMU_VM_EOF) { uint32_t instance_id, version_id, section_id; SaveStateEntry *se; @@ -1093,16 +1082,14 @@ int qemu_loadvm_state(QEMUFile *f) if (se == NULL) { error_report("Unknown savevm section or instance '%s' %d", idstr, instance_id); - ret = -EINVAL; - goto out; + return -EINVAL; } /* Validate version */ if (version_id > se->version_id) { error_report("savevm: unsupported version %d for '%s' v%d", version_id, idstr, se->version_id); - ret = -EINVAL; - goto out; + return -EINVAL; } /* Add entry */ @@ -1117,7 +1104,7 @@ int qemu_loadvm_state(QEMUFile *f) if (ret < 0) { error_report("error while loading state for instance 0x%x of" " device '%s'", instance_id, idstr); - goto out; + return ret; } break; case QEMU_VM_SECTION_PART: @@ -1132,36 +1119,73 @@ int qemu_loadvm_state(QEMUFile *f) } if (le == NULL) { error_report("Unknown savevm section %d", section_id); - ret = -EINVAL; - goto out; + return -EINVAL; } ret = vmstate_load(f, le->se, le->version_id); if (ret < 0) { error_report("error while loading state section id %d(%s)", section_id, le->se->idstr); - goto out; + return ret; } break; case QEMU_VM_COMMAND: ret = loadvm_process_command(f); - if (ret < 0) { - goto out; + trace_qemu_loadvm_state_section_command(ret); + if ((ret < 0) || (ret & LOADVM_QUIT_LOOP)) { + return ret; } + exitcode |= ret; /* Lets us pass flags up to the parent */ break; default: error_report("Unknown savevm section type %d", section_type); - ret = -EINVAL; - goto out; + return -EINVAL; } } - cpu_synchronize_all_post_init(); + if (exitcode & LOADVM_QUIT_PARENT) { + trace_qemu_loadvm_state_main_quit_parent(); + exitcode &= ~LOADVM_QUIT_PARENT; + exitcode |= LOADVM_QUIT_LOOP; + } + + return exitcode; +} + +int qemu_loadvm_state(QEMUFile *f) +{ + MigrationIncomingState *mis = migration_incoming_get_current(); + Error *local_err = NULL; + unsigned int v; + int ret; + + if (qemu_savevm_state_blocked(&local_err)) { + error_report("%s", error_get_pretty(local_err)); + error_free(local_err); + return -EINVAL; + } + + v = qemu_get_be32(f); + if (v != QEMU_VM_FILE_MAGIC) { + error_report("Not a migration stream"); + return -EINVAL; + } + + v = qemu_get_be32(f); + if (v == QEMU_VM_FILE_VERSION_COMPAT) { + error_report("SaveVM v2 format is obsolete and don't work anymore"); + return -ENOTSUP; + } + if (v != QEMU_VM_FILE_VERSION) { + error_report("Unsupported migration stream version"); + return -ENOTSUP; + } - ret = 0; + ret = qemu_loadvm_state_main(f, mis); -out: + trace_qemu_loadvm_state_post_main(ret); if (ret == 0) { + cpu_synchronize_all_post_init(); ret = qemu_file_get_error(f); } diff --git a/trace-events b/trace-events index 1951b25..4ff55fe 100644 --- a/trace-events +++ b/trace-events @@ -1165,7 +1165,11 @@ vmware_setmode(uint32_t w, uint32_t h, uint32_t bpp) "%dx%d @ %d bpp" # savevm.c qemu_loadvm_state_section(unsigned int section_type) "%d" +qemu_loadvm_state_section_command(int ret) "%d" qemu_loadvm_state_section_partend(uint32_t section_id) "%u" +qemu_loadvm_state_main(void) "" +qemu_loadvm_state_main_quit_parent(void) "" +qemu_loadvm_state_post_main(int ret) "%d" qemu_loadvm_state_section_startfull(uint32_t section_id, const char *idstr, uint32_t instance_id, uint32_t version_id) "%u(%s) %u %u" loadvm_process_command(uint16_t com, uint16_t len) "com=0x%x len=%d" loadvm_process_command_ping(uint32_t val) "%x" -- 2.1.0