From patchwork Wed Jul 23 14:25:28 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yang Hongyang X-Patchwork-Id: 372957 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 555751401A1 for ; Thu, 24 Jul 2014 00:27:12 +1000 (EST) Received: from localhost ([::1]:45339 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X9xVe-0000U8-Ew for incoming@patchwork.ozlabs.org; Wed, 23 Jul 2014 10:27:10 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:48171) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X9xUZ-00071k-8h for qemu-devel@nongnu.org; Wed, 23 Jul 2014 10:26:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1X9xUT-0005uK-Nv for qemu-devel@nongnu.org; Wed, 23 Jul 2014 10:26:03 -0400 Received: from [59.151.112.132] (port=39675 helo=heian.cn.fujitsu.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X9xUT-0005sB-Bh for qemu-devel@nongnu.org; Wed, 23 Jul 2014 10:25:57 -0400 X-IronPort-AV: E=Sophos;i="5.00,931,1396972800"; d="scan'208";a="33686779" Received: from unknown (HELO edo.cn.fujitsu.com) ([10.167.33.5]) by heian.cn.fujitsu.com with ESMTP; 23 Jul 2014 22:23:07 +0800 Received: from G08CNEXCHPEKD03.g08.fujitsu.local (localhost.localdomain [127.0.0.1]) by edo.cn.fujitsu.com (8.14.3/8.13.1) with ESMTP id s6NEPqpp021551; Wed, 23 Jul 2014 22:25:52 +0800 Received: from localhost (10.167.226.223) by G08CNEXCHPEKD03.g08.fujitsu.local (10.167.33.89) with Microsoft SMTP Server (TLS) id 14.3.181.6; Wed, 23 Jul 2014 22:25:57 +0800 From: Yang Hongyang To: Date: Wed, 23 Jul 2014 22:25:28 +0800 Message-ID: <1406125538-27992-8-git-send-email-yanghy@cn.fujitsu.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1406125538-27992-1-git-send-email-yanghy@cn.fujitsu.com> References: <1406125538-27992-1-git-send-email-yanghy@cn.fujitsu.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 59.151.112.132 Cc: kvm@vger.kernel.org, GuiJianfeng@cn.fujitsu.com, eddie.dong@intel.com, dgilbert@redhat.com, mrhines@linux.vnet.ibm.com, Yang Hongyang Subject: [Qemu-devel] [RFC PATCH 07/17] COLO buffer: implement colo buffer as well as QEMUFileOps based on it 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 We need a buffer to store migration data. On save side: all saved data was write into colo buffer first, so that we can know the total size of the migration data. this can also separate the data transmission from colo control data, we use colo control data over socket fd to synchronous both side's stat. On restore side: all migration data was read into colo buffer first, then load data from the buffer: If network error happens while data transmission, the slaver can still functinal because the migration data are not yet loaded. Signed-off-by: Yang Hongyang --- migration-colo.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/migration-colo.c b/migration-colo.c index d566b9d..b90d9b6 100644 --- a/migration-colo.c +++ b/migration-colo.c @@ -11,6 +11,7 @@ #include "qemu/main-loop.h" #include "qemu/thread.h" #include "block/coroutine.h" +#include "qemu/error-report.h" #include "migration/migration-colo.h" static QEMUBH *colo_bh; @@ -20,14 +21,122 @@ bool colo_supported(void) return true; } +/* colo buffer */ + +#define COLO_BUFFER_BASE_SIZE (1000*1000*4ULL) +#define COLO_BUFFER_MAX_SIZE (1000*1000*1000*10ULL) + +typedef struct colo_buffer { + uint8_t *data; + uint64_t used; + uint64_t freed; + uint64_t size; +} colo_buffer_t; + +static colo_buffer_t colo_buffer; + +static void colo_buffer_init(void) +{ + if (colo_buffer.size == 0) { + colo_buffer.data = g_malloc(COLO_BUFFER_BASE_SIZE); + colo_buffer.size = COLO_BUFFER_BASE_SIZE; + } + colo_buffer.used = 0; + colo_buffer.freed = 0; +} + +static void colo_buffer_destroy(void) +{ + if (colo_buffer.data) { + g_free(colo_buffer.data); + colo_buffer.data = NULL; + } + colo_buffer.used = 0; + colo_buffer.freed = 0; + colo_buffer.size = 0; +} + +static void colo_buffer_extend(uint64_t len) +{ + if (len > colo_buffer.size - colo_buffer.used) { + len = len + colo_buffer.used - colo_buffer.size; + len = ROUND_UP(len, COLO_BUFFER_BASE_SIZE) + COLO_BUFFER_BASE_SIZE; + + colo_buffer.size += len; + if (colo_buffer.size > COLO_BUFFER_MAX_SIZE) { + error_report("colo_buffer overflow!\n"); + exit(EXIT_FAILURE); + } + colo_buffer.data = g_realloc(colo_buffer.data, colo_buffer.size); + } +} + +static int colo_put_buffer(void *opaque, const uint8_t *buf, + int64_t pos, int size) +{ + colo_buffer_extend(size); + memcpy(colo_buffer.data + colo_buffer.used, buf, size); + colo_buffer.used += size; + + return size; +} + +static int colo_get_buffer_internal(uint8_t *buf, int size) +{ + if ((size + colo_buffer.freed) > colo_buffer.used) { + size = colo_buffer.used - colo_buffer.freed; + } + memcpy(buf, colo_buffer.data + colo_buffer.freed, size); + colo_buffer.freed += size; + + return size; +} + +static int colo_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) +{ + return colo_get_buffer_internal(buf, size); +} + +static int colo_close(void *opaque) +{ + colo_buffer_t *cb = opaque ; + + cb->used = 0; + cb->freed = 0; + + return 0; +} + +static int colo_get_fd(void *opaque) +{ + /* colo buffer, no fd */ + return -1; +} + +static const QEMUFileOps colo_write_ops = { + .put_buffer = colo_put_buffer, + .get_fd = colo_get_fd, + .close = colo_close, +}; + +static const QEMUFileOps colo_read_ops = { + .get_buffer = colo_get_buffer, + .get_fd = colo_get_fd, + .close = colo_close, +}; + /* save */ static void *colo_thread(void *opaque) { MigrationState *s = opaque; + colo_buffer_init(); + /*TODO: COLO checkpointed save loop*/ + colo_buffer_destroy(); + if (s->state != MIG_STATE_ERROR) { migrate_set_state(s, MIG_STATE_COLO, MIG_STATE_COMPLETED); } @@ -77,8 +186,11 @@ void colo_process_incoming_checkpoints(QEMUFile *f) colo = qemu_coroutine_self(); assert(colo != NULL); + colo_buffer_init(); + /* TODO: COLO checkpointed restore loop */ + colo_buffer_destroy(); colo = NULL; restore_exit_colo();