From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MOs6P-0007Gj-Pl for qemu-devel@nongnu.org; Thu, 09 Jul 2009 07:47:49 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MOs6K-0007Cp-GL for qemu-devel@nongnu.org; Thu, 09 Jul 2009 07:47:48 -0400 Received: from [199.232.76.173] (port=50840 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MOs6J-0007CR-Tk for qemu-devel@nongnu.org; Thu, 09 Jul 2009 07:47:43 -0400 Received: from mx2.redhat.com ([66.187.237.31]:47174) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1MOs6J-0005dn-2c for qemu-devel@nongnu.org; Thu, 09 Jul 2009 07:47:43 -0400 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id n69BlgLo024651 for ; Thu, 9 Jul 2009 07:47:42 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id n69BlflM010974 for ; Thu, 9 Jul 2009 07:47:42 -0400 Received: from localhost.localdomain (dhcp-lab-149.englab.brq.redhat.com [10.34.33.149]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id n69BldH4028817 for ; Thu, 9 Jul 2009 07:47:41 -0400 From: Paolo Bonzini Date: Thu, 9 Jul 2009 13:47:38 +0200 Message-Id: <1247140059-5034-3-git-send-email-pbonzini@redhat.com> In-Reply-To: <1247140059-5034-1-git-send-email-pbonzini@redhat.com> References: <1247140059-5034-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PATCH 2/3] move vm stop/start to migrate_set_state List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org With this patch, the state machine grows a new state, COMPLETING. This new state corresponds to the VM being stopped while migration is finalized. Stopping and starting the machine is driven exclusively by the state machine mechanisms. Two rare bugs are fixed. The first is a race; the VM used to remain stopped if a migration was canceled exactly in what corresponds to the new COMPLETING state. A bit worse is that if an error occurred exactly during the final stage (for example due to disk full) the VM was unconditionally restarted, even if it was paused before the beginning of the migration. --- migration.c | 36 +++++++++++++++++++++++++----------- migration.h | 2 ++ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/migration.c b/migration.c index 5abce0c..96585dd 100644 --- a/migration.c +++ b/migration.c @@ -150,6 +150,11 @@ void do_info_migrate(Monitor *mon) monitor_printf(mon, "remaining ram: %" PRIu64 " kbytes\n", ram_bytes_remaining() >> 10); monitor_printf(mon, "total ram: %" PRIu64 " kbytes\n", ram_bytes_total() >> 10); break; + case MIG_STATE_COMPLETING: + monitor_printf(mon, "completing\n"); + monitor_printf(mon, "transferred ram: %" PRIu64 " kbytes\n", ram_bytes_transferred() >> 10); + monitor_printf(mon, "total ram: %" PRIu64 " kbytes\n", ram_bytes_total() >> 10); + break; case MIG_STATE_COMPLETED: monitor_printf(mon, "completed\n"); break; @@ -267,18 +272,13 @@ void migrate_fd_put_ready(void *opaque) dprintf("iterate\n"); if (qemu_savevm_state_iterate(s->file) == 1) { - int state; dprintf("done iterating\n"); - vm_stop(0); - bdrv_flush_all(); - if ((qemu_savevm_state_complete(s->file)) < 0) { - vm_start(); - state = MIG_STATE_ERROR; - } else { - state = MIG_STATE_COMPLETED; - } - migrate_set_state(&s->mig_state, state); + migrate_set_state(&s->mig_state, MIG_STATE_COMPLETING); + if ((qemu_savevm_state_complete(s->file)) < 0) + migrate_set_state(&s->mig_state, MIG_STATE_ERROR); + else + migrate_set_state(&s->mig_state, MIG_STATE_COMPLETED); } } @@ -286,11 +286,25 @@ void migrate_set_state(MigrationState *s, int state) { s->state = state; - if (state != MIG_STATE_ACTIVE) { + switch (state) { + case MIG_STATE_COMPLETING: + s->save_vm_running = vm_running; + vm_stop(0); + bdrv_flush_all(); + break; + + case MIG_STATE_ACTIVE: + break; + + default: s->cleanup (s); /* Don't resume monitor until we've flushed all of the buffers */ if (s->mon_resume) monitor_resume(s->mon_resume); + + if (s->save_vm_running && state != MIG_STATE_COMPLETED) + vm_start(); + break; } } diff --git a/migration.h b/migration.h index 81ac361..c44bd75 100644 --- a/migration.h +++ b/migration.h @@ -20,6 +20,7 @@ #define MIG_STATE_COMPLETED 0 #define MIG_STATE_CANCELLED 1 #define MIG_STATE_ACTIVE 2 +#define MIG_STATE_COMPLETING 3 typedef struct MigrationState MigrationState; @@ -27,6 +28,7 @@ struct MigrationState { Monitor *mon_resume; int state; + int save_vm_running; /* FIXME: add more accessors to print migration info */ void (*cleanup)(MigrationState *s); -- 1.5.5.6