From patchwork Wed Oct 7 06:20:44 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Denis V. Lunev" X-Patchwork-Id: 527149 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 5495B140DA5 for ; Wed, 7 Oct 2015 17:21:45 +1100 (AEDT) Received: from localhost ([::1]:55431 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zji6h-0003r0-5r for incoming@patchwork.ozlabs.org; Wed, 07 Oct 2015 02:21:43 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:48965) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zji60-0002Zm-3z for qemu-devel@nongnu.org; Wed, 07 Oct 2015 02:21:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Zji5z-0000Qh-2k for qemu-devel@nongnu.org; Wed, 07 Oct 2015 02:21:00 -0400 Received: from mailhub.sw.ru ([195.214.232.25]:4382 helo=relay.sw.ru) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zji5y-0000Q7-Ni for qemu-devel@nongnu.org; Wed, 07 Oct 2015 02:20:59 -0400 Received: from irbis.sw.ru ([10.30.2.139]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id t976KkkV031932; Wed, 7 Oct 2015 09:20:56 +0300 (MSK) From: "Denis V. Lunev" To: Date: Wed, 7 Oct 2015 09:20:44 +0300 Message-Id: <1444198846-5383-7-git-send-email-den@openvz.org> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1444198846-5383-1-git-send-email-den@openvz.org> References: <5614531B.5080107@redhat.com> <1444198846-5383-1-git-send-email-den@openvz.org> MIME-Version: 1.0 X-MIME-Autoconverted: from 8bit to quoted-printable by relay.sw.ru id t976KkkV031932 X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x X-Received-From: 195.214.232.25 Cc: "Denis V. Lunev" , Igor Redko , jsnow@redhat.com, qemu-devel@nongnu.org, annam@virtuozzo.com Subject: [Qemu-devel] [PATCH 6/8] migration: implementation of hook_ram_sync 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 From: Igor Redko The key feature of the test transport is receiving information about dirty memory. The qemu_test_sync_hook() allows to use the migration infrastructure(code) for this purpose. All calls of this hook will be from ram_save_pending(). At the first call of this hook we need to save the initial size of VM memory and put the migration thread to sleep for decent period (downtime for example). During this period guest would dirty memory. The second and the last call. We make our estimation of dirty bytes rate assuming that time between two synchronizations of dirty bitmap differs from downtime negligibly. An alternative to this approach is receiving information about size of data “transmitted” through the transport. However, this way creates large time and memory overheads: 1/Transmitted guest’s memory pages are copied to QEMUFile’s buffer (~8 sec per 4GB VM) 2/Dirty memory pages are processed one by one (~60msec per 4GB VM) Signed-off-by: Igor Redko Reviewed-by: Anna Melekhova Signed-off-by: Denis V. Lunev --- migration/migration.c | 8 ++++++++ migration/test.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/migration/migration.c b/migration/migration.c index d6cb3e2..3182e15 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1058,6 +1058,14 @@ static void *migration_thread(void *opaque) MIGRATION_STATUS_FAILED); break; } + + if (migrate_is_test()) { + /* since no data is transfered during estimation all + all measurements below will be incorrect. + as well no need for delays. */ + continue; + } + current_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); if (current_time >= initial_time + BUFFER_DELAY) { uint64_t transferred_bytes = qemu_ftell(s->file) - initial_bytes; diff --git a/migration/test.c b/migration/test.c index 8d06988..b4d0761 100644 --- a/migration/test.c +++ b/migration/test.c @@ -18,6 +18,7 @@ typedef struct QEMUFileTest { static uint64_t transfered_bytes; static uint64_t initial_bytes; +static int sync_cnt; static ssize_t qemu_test_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, size_t size) @@ -31,7 +32,41 @@ static int qemu_test_close(void *opaque) return 0; } +static int qemu_test_sync_hook(QEMUFile *f, void *opaque, + uint64_t flags, void *data) +{ + static uint64_t dirtied_bytes; + static uint64_t sleeptime_mcs; + int64_t time_delta; + uint64_t remaining_bytes = *((uint64_t *) data); + MigrationState *s = (MigrationState *) opaque; + switch (sync_cnt++) { + case 0: + /* First call will be from ram_save_begin + * so we need to save initial size of VM memory + * and sleep for decent period (downtime for example). */ + sleeptime_mcs = migrate_max_downtime()/1000; + initial_bytes = remaining_bytes; + usleep(sleeptime_mcs); + break; + case 1: + /* Second and last call. + * We assume that time between two synchronizations of + * dirty bitmap differs from downtime negligibly and + * make our estimation of dirty bytes rate. */ + dirtied_bytes = remaining_bytes; + time_delta = sleeptime_mcs / 1000; + s->dirty_bytes_rate = dirtied_bytes * 1000 / time_delta; + return -42; + default: + /* All calls after second are errors */ + return -1; + } + return 0; +} + static const QEMUFileOps test_write_ops = { + .hook_ram_sync = qemu_test_sync_hook, .put_buffer = qemu_test_put_buffer, .close = qemu_test_close, }; @@ -41,6 +76,7 @@ static void *qemu_fopen_test(MigrationState *s, const char *mode) QEMUFileTest *t; transfered_bytes = 0; initial_bytes = 0; + sync_cnt = 0; if (qemu_file_mode_is_not_valid(mode)) { return NULL; }