From patchwork Thu Jun 30 15:46:16 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 102784 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id C58D7B6F59 for ; Fri, 1 Jul 2011 02:48:23 +1000 (EST) Received: from localhost ([::1]:43957 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QcKPa-00057k-Si for incoming@patchwork.ozlabs.org; Thu, 30 Jun 2011 12:48:19 -0400 Received: from eggs.gnu.org ([140.186.70.92]:37971) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QcJS1-00069J-VF for qemu-devel@nongnu.org; Thu, 30 Jun 2011 11:46:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QcJRv-0006mx-HO for qemu-devel@nongnu.org; Thu, 30 Jun 2011 11:46:45 -0400 Received: from mail-qy0-f173.google.com ([209.85.216.173]:60023) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QcJRv-0006mO-3Y for qemu-devel@nongnu.org; Thu, 30 Jun 2011 11:46:39 -0400 Received: by mail-qy0-f173.google.com with SMTP id 10so122672qyk.4 for ; Thu, 30 Jun 2011 08:46:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=sender:from:to:subject:date:message-id:x-mailer:in-reply-to :references; bh=9tKSS22P1NIKUZYYhrfgHU/GqOEGlK+0wQ0Q7MzC0j8=; b=ogY6rkN1Uu0vI+oVQUl+7wvJlJBD4XW/pPo6l7dd44H3xsLAueis272gb8/Qqr/uDR JPubll2XdU5DdsTcIVWJBtXi5Zt1iYH8bNAS2+gHYvcVhw69Tqx9W/ronZgP7XN3cOqH Dn8UlwVTeNNLef/TqT++ERJz6jCh89gyW31zw= Received: by 10.229.68.227 with SMTP id w35mr1685597qci.140.1309448798594; Thu, 30 Jun 2011 08:46:38 -0700 (PDT) Received: from localhost.localdomain (nat-pool-mxp-t.redhat.com [209.132.186.18]) by mx.google.com with ESMTPS id e18sm1812462qcs.17.2011.06.30.08.46.37 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 30 Jun 2011 08:46:37 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 30 Jun 2011 17:46:16 +0200 Message-Id: <1309448777-1447-4-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.7.5.2 In-Reply-To: <1309448777-1447-1-git-send-email-pbonzini@redhat.com> References: <1309448777-1447-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 209.85.216.173 Subject: [Qemu-devel] [RFC PATCH 3/4] savevm: define new unambiguous migration format X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org With the current migration format, VMS_STRUCTs with subsections are ambiguous. The protocol cannot tell whether a 0x5 byte after the VMS_STRUCT is a subsection or part of the parent data stream. In the past QEMU assumed it was always a part of a subsection; after commit eb60260 (savevm: fix corruption in vmstate_subsection_load()., 2011-02-03) the choice depends on whether the VMS_STRUCT has subsections defined. Unfortunately, this means that if a destination has no subsections defined for the struct, it will happily read subsection data into its own fields. And if you are "lucky" enough to stumble on a zero byte at the right time, it will be interpreted as QEMU_VM_EOF and migration will be interrupted. There is no way out of this except defining an incompatible migration protocol with a sentinel at the end of embedded structs. Of course, this is restricted to new machine models. Signed-off-by: Paolo Bonzini --- hw/pc_piix.c | 6 ++++++ savevm.c | 27 +++++++++++++++++++-------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 18cc942..d8d629c 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -271,6 +271,7 @@ static QEMUMachine pc_machine_v0_14 = { .desc = "Standard PC", .init = pc_init_pci, .max_cpus = 255, + .migration_format = 3, }; static QEMUMachine pc_machine_v0_13 = { @@ -278,6 +279,7 @@ static QEMUMachine pc_machine_v0_13 = { .desc = "Standard PC", .init = pc_init_pci_no_kvmclock, .max_cpus = 255, + .migration_format = 3, .compat_props = (GlobalProperty[]) { { .driver = "virtio-9p-pci", @@ -317,6 +319,7 @@ static QEMUMachine pc_machine_v0_12 = { .desc = "Standard PC", .init = pc_init_pci_no_kvmclock, .max_cpus = 255, + .migration_format = 3, .compat_props = (GlobalProperty[]) { { .driver = "virtio-serial-pci", @@ -360,6 +363,7 @@ static QEMUMachine pc_machine_v0_11 = { .desc = "Standard PC, qemu 0.11", .init = pc_init_pci_no_kvmclock, .max_cpus = 255, + .migration_format = 3, .compat_props = (GlobalProperty[]) { { .driver = "virtio-blk-pci", @@ -411,6 +415,7 @@ static QEMUMachine pc_machine_v0_10 = { .desc = "Standard PC, qemu 0.10", .init = pc_init_pci_no_kvmclock, .max_cpus = 255, + .migration_format = 3, .compat_props = (GlobalProperty[]) { { .driver = "virtio-blk-pci", @@ -474,6 +479,7 @@ static QEMUMachine isapc_machine = { .desc = "ISA-only PC", .init = pc_init_isa, .max_cpus = 1, + .migration_format = 3, }; #ifdef CONFIG_XEN diff --git a/savevm.c b/savevm.c index 74e6e99..654770a 100644 --- a/savevm.c +++ b/savevm.c @@ -158,6 +158,14 @@ void qemu_announce_self(void) #define IO_BUF_SIZE 32768 +#define QEMU_VM_EOF 0x00 +#define QEMU_VM_SECTION_START 0x01 +#define QEMU_VM_SECTION_PART 0x02 +#define QEMU_VM_SECTION_END 0x03 +#define QEMU_VM_SECTION_FULL 0x04 +#define QEMU_VM_SUBSECTION 0x05 +#define QEMU_VM_SUBSECTIONS_END 0x06 + struct QEMUFile { QEMUFilePutBufferFunc *put_buffer; QEMUFileGetBufferFunc *get_buffer; @@ -1348,6 +1356,12 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, } if (field->flags & VMS_STRUCT) { ret = vmstate_load_state(f, field->vmsd, addr, field->vmsd->version_id); + if (!current_machine->migration_format || + current_machine->migration_format >= 4) { + if (qemu_get_byte(f) != QEMU_VM_SUBSECTIONS_END) { + return -EINVAL; + } + } } else { ret = field->info->get(f, addr, size); @@ -1410,6 +1424,10 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, } if (field->flags & VMS_STRUCT) { vmstate_save_state(f, field->vmsd, addr); + if (!current_machine->migration_format || + current_machine->migration_format >= 4) { + qemu_put_byte(f, QEMU_VM_SUBSECTIONS_END); + } } else { field->info->put(f, addr, size); } @@ -1439,14 +1457,7 @@ static void vmstate_save(QEMUFile *f, SaveStateEntry *se) #define QEMU_VM_FILE_MAGIC 0x5145564d #define QEMU_VM_FILE_VERSION_COMPAT 0x00000002 -#define QEMU_VM_FILE_VERSION 0x00000003 - -#define QEMU_VM_EOF 0x00 -#define QEMU_VM_SECTION_START 0x01 -#define QEMU_VM_SECTION_PART 0x02 -#define QEMU_VM_SECTION_END 0x03 -#define QEMU_VM_SECTION_FULL 0x04 -#define QEMU_VM_SUBSECTION 0x05 +#define QEMU_VM_FILE_VERSION 0x00000004 bool qemu_savevm_state_blocked(Monitor *mon) {