From patchwork Thu Oct 27 15:32:12 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Dr. David Alan Gilbert" X-Patchwork-Id: 9399853 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 7A07F60588 for ; Thu, 27 Oct 2016 16:13:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 688712A30D for ; Thu, 27 Oct 2016 16:13:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5D1152A354; Thu, 27 Oct 2016 16:13:38 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_HK_NAME_DR autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id DE4402A30D for ; Thu, 27 Oct 2016 16:13:33 +0000 (UTC) Received: from localhost ([::1]:42572 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bznJ7-0005qO-4G for patchwork-qemu-devel@patchwork.kernel.org; Thu, 27 Oct 2016 12:13:33 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:48725) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bzmfN-000687-Rd for qemu-devel@nongnu.org; Thu, 27 Oct 2016 11:32:33 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bzmfK-0001sj-0r for qemu-devel@nongnu.org; Thu, 27 Oct 2016 11:32:29 -0400 Received: from mx1.redhat.com ([209.132.183.28]:57464) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1bzmfJ-0001sQ-Pz for qemu-devel@nongnu.org; Thu, 27 Oct 2016 11:32:25 -0400 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 19BBC7F08B; Thu, 27 Oct 2016 15:32:25 +0000 (UTC) Received: from dgilbert-t530.redhat.com ([10.33.36.3]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u9RFWIR9000489; Thu, 27 Oct 2016 11:32:23 -0400 From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, quintela@redhat.com, amit.shah@redhat.com, samuel.thibault@ens-lyon.org, jan.kiszka@siemens.com Date: Thu, 27 Oct 2016 16:32:12 +0100 Message-Id: <20161027153217.16984-4-dgilbert@redhat.com> In-Reply-To: <20161027153217.16984-1-dgilbert@redhat.com> References: <20161027153217.16984-1-dgilbert@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Thu, 27 Oct 2016 15:32:25 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 3/8] migration: Add VMSTATE_WITH_TMP X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: duanj@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: "Dr. David Alan Gilbert" VMSTATE_WITH_TMP is for handling structures where some calculation or rearrangement of the data needs to be performed before the data hits the wire. For example, where the value on the wire is an offset from a non-migrated base, but the data in the structure is the actual pointer. To use it, a temporary type is created and a vmsd used on that type. The first element of the type must be 'parent' a pointer back to the type of the main structure. VMSTATE_WITH_TMP takes care of allocating and freeing the temporary before running the child vmsd. The post_load/pre_save on the child vmsd can copy things from the parent to the temporary using the parent pointer and do any other calculations needed; it can then use normal VMSD entries to do the actual data storage without having to fiddle around with qemu_get_*/qemu_put_* Signed-off-by: Dr. David Alan Gilbert Reviewed-by: David Gibson Reviewed-by: Juan Quintela --- include/migration/vmstate.h | 19 +++++++++++++++++++ migration/vmstate.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index d0e37b5..b404360 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -250,6 +250,7 @@ extern const VMStateInfo vmstate_info_cpudouble; extern const VMStateInfo vmstate_info_timer; extern const VMStateInfo vmstate_info_buffer; extern const VMStateInfo vmstate_info_unused_buffer; +extern const VMStateInfo vmstate_info_tmp; extern const VMStateInfo vmstate_info_bitmap; #define type_check_2darray(t1,t2,n,m) ((t1(*)[n][m])0 - (t2*)0) @@ -641,6 +642,24 @@ extern const VMStateInfo vmstate_info_bitmap; .offset = offsetof(_state, _field), \ } +/* Allocate a temporary of type 'tmp_type', set tmp->parent to _state + * and execute the vmsd on the temporary. Note that we're working with + * the whole of _state here, not a field within it. + * We compile time check that: + * That _tmp_type contains a 'parent' member that's a pointer to the + * '_state' type + * That the pointer is right at the start of _tmp_type. + */ +#define VMSTATE_WITH_TMP(_state, _tmp_type, _vmsd) { \ + .name = "tmp", \ + .size = sizeof(_tmp_type) + \ + QEMU_BUILD_BUG_EXPR(offsetof(_tmp_type, parent) != 0) + \ + type_check_pointer(_state, \ + typeof_field(_tmp_type, parent)), \ + .vmsd = &(_vmsd), \ + .info = &vmstate_info_tmp, \ +} + #define VMSTATE_UNUSED_BUFFER(_test, _version, _size) { \ .name = "unused", \ .field_exists = (_test), \ diff --git a/migration/vmstate.c b/migration/vmstate.c index 75922dd..6df65ca 100644 --- a/migration/vmstate.c +++ b/migration/vmstate.c @@ -918,6 +918,44 @@ const VMStateInfo vmstate_info_unused_buffer = { .put = put_unused_buffer, }; +/* vmstate_info_tmp, see VMSTATE_WITH_TMP, the idea is that we allocate + * a temporary buffer and the pre_load/pre_save methods in the child vmsd + * copy stuff from the parent into the child and do calculations to fill + * in fields that don't really exist in the parent but need to be in the + * stream. + */ +static int get_tmp(QEMUFile *f, void *pv, size_t size, VMStateField *field) +{ + int ret; + const VMStateDescription *vmsd = field->vmsd; + int version_id = field->version_id; + void *tmp = g_malloc(size); + + /* Writes the parent field which is at the start of the tmp */ + *(void **)tmp = pv; + ret = vmstate_load_state(f, vmsd, tmp, version_id); + g_free(tmp); + return ret; +} + +static void put_tmp(QEMUFile *f, void *pv, size_t size, VMStateField *field, + QJSON *vmdesc) +{ + const VMStateDescription *vmsd = field->vmsd; + void *tmp = g_malloc(size); + + /* Writes the parent field which is at the start of the tmp */ + *(void **)tmp = pv; + vmstate_save_state(f, vmsd, tmp, vmdesc); + g_free(tmp); +} + +const VMStateInfo vmstate_info_tmp = { + .name = "tmp", + .get = get_tmp, + .put = put_tmp, +}; + /* bitmaps (as defined by bitmap.h). Note that size here is the size * of the bitmap in bits. The on-the-wire format of a bitmap is 64 * bit words with the bits in big endian order. The in-memory format