From patchwork Mon Jul 26 19:38:43 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Juan Quintela X-Patchwork-Id: 59942 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id EA0B5B70B1 for ; Tue, 27 Jul 2010 05:48:30 +1000 (EST) Received: from localhost ([127.0.0.1]:46288 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OdTf2-0007Io-6n for incoming@patchwork.ozlabs.org; Mon, 26 Jul 2010 15:48:28 -0400 Received: from [140.186.70.92] (port=54113 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OdTX6-0003tm-Ky for qemu-devel@nongnu.org; Mon, 26 Jul 2010 15:40:18 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OdTX4-0007Sp-Sn for qemu-devel@nongnu.org; Mon, 26 Jul 2010 15:40:16 -0400 Received: from mx1.redhat.com ([209.132.183.28]:46705) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OdTX4-0007Si-Ey for qemu-devel@nongnu.org; Mon, 26 Jul 2010 15:40:14 -0400 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o6QJeDA5022565 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 26 Jul 2010 15:40:13 -0400 Received: from trasno.mitica (ovpn-113-23.phx2.redhat.com [10.3.113.23]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o6QJe73S016073; Mon, 26 Jul 2010 15:40:11 -0400 From: Juan Quintela To: qemu-devel@nongnu.org Date: Mon, 26 Jul 2010 21:38:43 +0200 Message-Id: In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. Cc: Subject: [Qemu-devel] [PATCH 3/6] vmstate: add subsections code X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This commit adds subsections for each device section. Subsections is the way to handle information that don't need to be sent to de destination of a migration because its values are not needed. It is the way to handle optional information. Notice that only the source can decide if the information is optional or not. The destination needs to understand all subsections that it receives to have a sucessful load. Signed-off-by: Juan Quintela --- hw/hw.h | 6 ++++ savevm.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 1 deletions(-) diff --git a/hw/hw.h b/hw/hw.h index c2de6fe..e3c3db2 100644 --- a/hw/hw.h +++ b/hw/hw.h @@ -313,6 +313,11 @@ typedef struct { bool (*field_exists)(void *opaque, int version_id); } VMStateField; +typedef struct VMStateSubsection { + const VMStateDescription *vmsd; + bool (*needed)(void *opaque); +} VMStateSubsection; + struct VMStateDescription { const char *name; int version_id; @@ -323,6 +328,7 @@ struct VMStateDescription { int (*post_load)(void *opaque, int version_id); void (*pre_save)(void *opaque); VMStateField *fields; + const VMStateSubsection *subsections; }; extern const VMStateInfo vmstate_info_int8; diff --git a/savevm.c b/savevm.c index ee27989..7a1de3c 100644 --- a/savevm.c +++ b/savevm.c @@ -551,6 +551,19 @@ int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size1) return size1 - size; } +static int qemu_peek_byte(QEMUFile *f) +{ + if (f->is_write) + abort(); + + if (f->buf_index >= f->buf_size) { + qemu_fill_buffer(f); + if (f->buf_index >= f->buf_size) + return 0; + } + return f->buf[f->buf_index]; +} + int qemu_get_byte(QEMUFile *f) { if (f->is_write) @@ -1198,10 +1211,16 @@ void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd, } } +static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd, + void *opaque); +static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd, + void *opaque); + int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, void *opaque, int version_id) { VMStateField *field = vmsd->fields; + int ret; if (version_id > vmsd->version_id) { return -EINVAL; @@ -1223,7 +1242,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, (!field->field_exists && field->version_id <= version_id)) { void *base_addr = opaque + field->offset; - int ret, i, n_elems = 1; + int i, n_elems = 1; int size = field->size; if (field->flags & VMS_VBUFFER) { @@ -1261,6 +1280,10 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, } field++; } + ret = vmstate_subsection_load(f, vmsd, opaque); + if (ret != 0) { + return ret; + } if (vmsd->post_load) { return vmsd->post_load(opaque, version_id); } @@ -1313,6 +1336,7 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, } field++; } + vmstate_subsection_save(f, vmsd, opaque); } static int vmstate_load(QEMUFile *f, SaveStateEntry *se, int version_id) @@ -1341,6 +1365,7 @@ static void vmstate_save(QEMUFile *f, SaveStateEntry *se) #define QEMU_VM_SECTION_PART 0x02 #define QEMU_VM_SECTION_END 0x03 #define QEMU_VM_SECTION_FULL 0x04 +#define QEMU_VM_SUBSECTION 0x05 int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable, int shared) @@ -1529,6 +1554,65 @@ static SaveStateEntry *find_se(const char *idstr, int instance_id) return NULL; } +static const VMStateDescription *vmstate_get_subsection(const VMStateSubsection *sub, char *idstr) +{ + while(sub && sub->needed) { + if (strcmp(idstr, sub->vmsd->name) == 0) { + return sub->vmsd; + } + sub++; + } + return NULL; +} + +static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd, + void *opaque) +{ + while (qemu_peek_byte(f) == QEMU_VM_SUBSECTION) { + char idstr[256]; + int ret; + uint8_t version_id, subsection, len; + const VMStateDescription *sub_vmsd; + + subsection = qemu_get_byte(f); + len = qemu_get_byte(f); + qemu_get_buffer(f, (uint8_t *)idstr, len); + idstr[len] = 0; + version_id = qemu_get_be32(f); + + sub_vmsd = vmstate_get_subsection(vmsd->subsections, idstr); + if (sub_vmsd == NULL) { + return -ENOENT; + } + ret = vmstate_load_state(f, sub_vmsd, opaque, version_id); + if (ret) { + return ret; + } + } + return 0; +} + +static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd, + void *opaque) +{ + const VMStateSubsection *sub = vmsd->subsections; + + while (sub && sub->needed) { + if (sub->needed(opaque)) { + const VMStateDescription *vmsd = sub->vmsd; + uint8_t len; + + qemu_put_byte(f, QEMU_VM_SUBSECTION); + len = strlen(vmsd->name); + qemu_put_byte(f, len); + qemu_put_buffer(f, (uint8_t *)vmsd->name, len); + qemu_put_be32(f, vmsd->version_id); + vmstate_save_state(f, vmsd, opaque); + } + sub++; + } +} + typedef struct LoadStateEntry { QLIST_ENTRY(LoadStateEntry) entry; SaveStateEntry *se;