From patchwork Wed Feb 6 00:48:25 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Roth X-Patchwork-Id: 218472 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id B57CC2C02CE for ; Wed, 6 Feb 2013 12:14:54 +1100 (EST) Received: from localhost ([::1]:34048 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U2tbA-0003EX-QG for incoming@patchwork.ozlabs.org; Tue, 05 Feb 2013 20:14:52 -0500 Received: from eggs.gnu.org ([208.118.235.92]:57800) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U2tas-0001na-IX for qemu-devel@nongnu.org; Tue, 05 Feb 2013 20:14:36 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1U2tPM-0006zA-3D for qemu-devel@nongnu.org; Tue, 05 Feb 2013 20:02:42 -0500 Received: from mail-ia0-x233.google.com ([2607:f8b0:4001:c02::233]:62099) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U2tPL-0006yt-TZ; Tue, 05 Feb 2013 20:02:40 -0500 Received: by mail-ia0-f179.google.com with SMTP id x24so886655iak.38 for ; Tue, 05 Feb 2013 17:02:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:sender:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references; bh=RPrAC+47geED0nSTGdNygx3XvsxjkA7oZL1pqJEcE+k=; b=k2nkaB6si/CI4M0YTOIrmMLUcC0qaKl/38u+Cvr2nN+OljZW3oowRaVf0HCLBX1nFi AehulKxvJS26QC2rZX+6M7VJ7fJ/4BFgKgzl9gsMmzQsWk0cerg8PDvTJ1Ws9PFBiqS+ 8+hPO1TttaUenMJsDwapF8azgdJy4dA9YSHzfNAfeUoqk52Y6o4GQL9pCfWrqZ0CphRn 0OJ7ZJiHA+uAzwTa8xLmMrY7WY220P2N+q59FGMdooBoriFxiG6K3vsZFrWsMPqY8V/B DktI7ABqGnUUtTayxFnNriyzL4dCfr2v3WbvNEJZYJXAR8DC1inruWmSXmU1vnnpOlB8 tfhg== X-Received: by 10.50.170.69 with SMTP id ak5mr2165787igc.56.1360112129039; Tue, 05 Feb 2013 16:55:29 -0800 (PST) Received: from localhost ([32.97.110.59]) by mx.google.com with ESMTPS id px5sm500046igc.0.2013.02.05.16.55.27 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Tue, 05 Feb 2013 16:55:28 -0800 (PST) From: Michael Roth To: qemu-devel@nongnu.org Date: Tue, 5 Feb 2013 18:48:25 -0600 Message-Id: <1360111706-13138-2-git-send-email-mdroth@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1360111706-13138-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1360111706-13138-1-git-send-email-mdroth@linux.vnet.ibm.com> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2607:f8b0:4001:c02::233 Cc: owasserm@redhat.com, aliguori@us.ibm.com, kraxel@redhat.com, qemu-stable@nongnu.org, quintela@redhat.com Subject: [Qemu-devel] [PATCH for-1.4 1/2] savevm: add support for RAMBlock resize handlers 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 This allow users to register resize handlers to be called in cases where a RAMBlock is received over the wire that doesn't match the size of the target's corresponding RAMBlock. The handlers are generally responsible for tearing down and re-initializing corresponding MemoryRegions based on knowledge of what the size of the RAMBlock is that they'll be receiving over the wire. Cc: qemu-stable@nongnu.org Signed-off-by: Michael Roth --- arch_init.c | 28 +++++++++++++--- include/migration/vmstate.h | 14 ++++++++ savevm.c | 77 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 5 deletions(-) diff --git a/arch_init.c b/arch_init.c index 8da868b..265ad8c 100644 --- a/arch_init.c +++ b/arch_init.c @@ -793,33 +793,51 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) ram_addr_t total_ram_bytes = addr; while (total_ram_bytes) { - RAMBlock *block; + RAMBlock *block, *block_next; uint8_t len; len = qemu_get_byte(f); qemu_get_buffer(f, (uint8_t *)id, len); id[len] = 0; length = qemu_get_be64(f); + ret = 0; - QTAILQ_FOREACH(block, &ram_list.blocks, next) { + QTAILQ_FOREACH_SAFE(block, &ram_list.blocks, next, + block_next) { if (!strncmp(id, block->idstr, sizeof(id))) { if (block->length != length) { - ret = -EINVAL; - goto done; + const VMStateRAMResizeHandler *rh = + vmstate_find_ram_resize(block->mr); + if (rh) { + ret = vmstate_do_ram_resize(rh, length); + } else { + ret = -EINVAL; + } } break; } } + if (ret) { + break; + } + if (!block) { fprintf(stderr, "Unknown ramblock \"%s\", cannot " "accept migration\n", id); ret = -EINVAL; - goto done; + break; } total_ram_bytes -= length; } + /* end of block synchronization phase, resize handlers are + * no longer useful + */ + vmstate_unregister_ram_resizable_all(); + if (ret) { + goto done; + } } } diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index f27276c..9e50391 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -637,4 +637,18 @@ void vmstate_register_ram(struct MemoryRegion *memory, DeviceState *dev); void vmstate_unregister_ram(struct MemoryRegion *memory, DeviceState *dev); void vmstate_register_ram_global(struct MemoryRegion *memory); +/* definitions for registering resize handlers for memory blocks */ +typedef struct VMStateRAMResizeHandler VMStateRAMResizeHandler; + +typedef int (RAMResizeFunc)(struct MemoryRegion *mr, uint64_t size, void *opaque); +typedef void (RAMResizeCleanupFunc)(void *opaque); + +void vmstate_register_ram_resizable(struct MemoryRegion *mr, + RAMResizeFunc resize_func, + RAMResizeCleanupFunc cleanup_func, + void *opaque); +void vmstate_unregister_ram_resizable_all(void); +const VMStateRAMResizeHandler *vmstate_find_ram_resize(const struct MemoryRegion *mr); +int vmstate_do_ram_resize(const VMStateRAMResizeHandler *rh, uint64_t size); + #endif diff --git a/savevm.c b/savevm.c index 4eb29b2..0553c47 100644 --- a/savevm.c +++ b/savevm.c @@ -2388,3 +2388,80 @@ void vmstate_register_ram_global(MemoryRegion *mr) { vmstate_register_ram(mr, NULL); } + +/* routines for registering resize handlers for memory blocks */ +struct VMStateRAMResizeHandler { + MemoryRegion *mr; + RAMResizeFunc *resize_func; + RAMResizeCleanupFunc *cleanup_func; + void *opaque; + QTAILQ_ENTRY(VMStateRAMResizeHandler) next; +}; + +static QTAILQ_HEAD(, VMStateRAMResizeHandler) ram_resize_handlers = + QTAILQ_HEAD_INITIALIZER(ram_resize_handlers); + +void vmstate_register_ram_resizable(MemoryRegion *mr, + RAMResizeFunc resize_func, + RAMResizeCleanupFunc cleanup_func, + void *opaque) +{ + VMStateRAMResizeHandler *rh; + + assert(mr && resize_func); + + QTAILQ_FOREACH(rh, &ram_resize_handlers, next) { + if (rh->mr == mr) { + /* only one resize handler per MemoryRegion */ + assert(0); + } + } + + rh = g_malloc0(sizeof(VMStateRAMResizeHandler)); + rh->mr = mr; + rh->resize_func = resize_func; + rh->cleanup_func = cleanup_func; + rh->opaque = opaque; + + QTAILQ_INSERT_TAIL(&ram_resize_handlers, rh, next); +} + +void vmstate_unregister_ram_resizable_all(void) +{ + VMStateRAMResizeHandler *rh, *rh_next; + + QTAILQ_FOREACH_SAFE(rh, &ram_resize_handlers, next, rh_next) { + if (rh->cleanup_func) { + rh->cleanup_func(rh->opaque); + QTAILQ_REMOVE(&ram_resize_handlers, rh, next); + } + g_free(rh); + } +} + +const VMStateRAMResizeHandler *vmstate_find_ram_resize(const MemoryRegion *mr) +{ + VMStateRAMResizeHandler *rh; + + QTAILQ_FOREACH(rh, &ram_resize_handlers, next) { + if (rh->mr == mr) { + return rh; + } + } + + return NULL; +} + +int vmstate_do_ram_resize(const VMStateRAMResizeHandler *rh, uint64_t size) +{ + int ret; + + assert(rh); + ret = rh->resize_func(rh->mr, size, rh->opaque); + if (ret) { + fprintf(stderr, "Unable to resize ramblock \"%s\"", + memory_region_name(rh->mr)); + } + + return ret; +}