From patchwork Fri Jun 26 10:19:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Dovgalyuk X-Patchwork-Id: 279338 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 623F7C433DF for ; Fri, 26 Jun 2020 13:47:53 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3551E20679 for ; Fri, 26 Jun 2020 13:47:53 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3551E20679 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=ispras.ru Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:47102 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1joohs-0005T6-Ge for qemu-devel@archiver.kernel.org; Fri, 26 Jun 2020 09:47:52 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:38112) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jolSj-00086H-HY for qemu-devel@nongnu.org; Fri, 26 Jun 2020 06:20:01 -0400 Received: from mail.ispras.ru ([83.149.199.84]:59354) by eggs.gnu.org with esmtps (TLS1.2:DHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jolSh-00009B-Af for qemu-devel@nongnu.org; Fri, 26 Jun 2020 06:20:01 -0400 Received: from [127.0.1.1] (unknown [62.118.151.149]) by mail.ispras.ru (Postfix) with ESMTPSA id 7DDC94089EEF; Fri, 26 Jun 2020 10:19:57 +0000 (UTC) Subject: [PATCH 03/13] migration: introduce icount field for snapshots From: Pavel Dovgalyuk To: qemu-devel@nongnu.org Date: Fri, 26 Jun 2020 13:19:57 +0300 Message-ID: <159316679721.10508.17702224865978496006.stgit@pasha-ThinkPad-X280> In-Reply-To: <159316678008.10508.6615172353109944370.stgit@pasha-ThinkPad-X280> References: <159316678008.10508.6615172353109944370.stgit@pasha-ThinkPad-X280> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Received-SPF: pass client-ip=83.149.199.84; envelope-from=pavel.dovgalyuk@ispras.ru; helo=mail.ispras.ru X-detected-operating-system: by eggs.gnu.org: First seen = 2020/06/26 06:19:41 X-ACL-Warn: Detected OS = Linux 3.11 and newer X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-Mailman-Approved-At: Fri, 26 Jun 2020 09:41:37 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, wrampazz@redhat.com, pavel.dovgalyuk@ispras.ru, ehabkost@redhat.com, alex.bennee@linaro.org, mtosatti@redhat.com, armbru@redhat.com, mreitz@redhat.com, stefanha@redhat.com, crosa@redhat.com, pbonzini@redhat.com, philmd@redhat.com, zhiwei_liu@c-sky.com, rth@twiddle.net Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Pavel Dovgalyuk Saving icount as a parameters of the snapshot allows navigation between them in the execution replay scenario. This information can be used for finding a specific snapshot for proceeding the recorded execution to the specific moment of the time. E.g., 'reverse step' action (introduced in one of the following patches) needs to load the nearest snapshot which is prior to the current moment of time. Signed-off-by: Pavel Dovgalyuk Acked-by: Markus Armbruster Acked-by: Kevin Wolf --- 0 files changed diff --git a/block/qapi.c b/block/qapi.c index afd9f3b4a7..3c73db54c4 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -226,6 +226,8 @@ int bdrv_query_snapshot_info_list(BlockDriverState *bs, info->date_nsec = sn_tab[i].date_nsec; info->vm_clock_sec = sn_tab[i].vm_clock_nsec / 1000000000; info->vm_clock_nsec = sn_tab[i].vm_clock_nsec % 1000000000; + info->icount = sn_tab[i].icount; + info->has_icount = sn_tab[i].icount != -1ULL; info_list = g_new0(SnapshotInfoList, 1); info_list->value = info; @@ -658,14 +660,15 @@ BlockStatsList *qmp_query_blockstats(bool has_query_nodes, void bdrv_snapshot_dump(QEMUSnapshotInfo *sn) { char date_buf[128], clock_buf[128]; + char icount_buf[128] = {0}; struct tm tm; time_t ti; int64_t secs; char *sizing = NULL; if (!sn) { - qemu_printf("%-10s%-20s%11s%20s%15s", - "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK"); + qemu_printf("%-10s%-18s%7s%20s%13s%11s", + "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK", "ICOUNT"); } else { ti = sn->date_sec; localtime_r(&ti, &tm); @@ -679,11 +682,16 @@ void bdrv_snapshot_dump(QEMUSnapshotInfo *sn) (int)(secs % 60), (int)((sn->vm_clock_nsec / 1000000) % 1000)); sizing = size_to_str(sn->vm_state_size); - qemu_printf("%-10s%-20s%11s%20s%15s", + if (sn->icount != -1ULL) { + snprintf(icount_buf, sizeof(icount_buf), + "%"PRId64, sn->icount); + } + qemu_printf("%-10s%-18s%7s%20s%13s%11s", sn->id_str, sn->name, sizing, date_buf, - clock_buf); + clock_buf, + icount_buf); } g_free(sizing); } @@ -845,6 +853,8 @@ void bdrv_image_info_dump(ImageInfo *info) .date_nsec = elem->value->date_nsec, .vm_clock_nsec = elem->value->vm_clock_sec * 1000000000ULL + elem->value->vm_clock_nsec, + .icount = elem->value->has_icount ? + elem->value->icount : -1ULL, }; pstrcpy(sn.id_str, sizeof(sn.id_str), elem->value->id); diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index d14e7be1aa..4b127ea6af 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -663,6 +663,7 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) sn->date_sec = sn_info->date_sec; sn->date_nsec = sn_info->date_nsec; sn->vm_clock_nsec = sn_info->vm_clock_nsec; + sn->icount = sn_info->icount; sn->extra_data_size = sizeof(QCowSnapshotExtraData); /* Allocate the L1 table of the snapshot and copy the current one there. */ @@ -1007,6 +1008,7 @@ int qcow2_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab) sn_info->date_sec = sn->date_sec; sn_info->date_nsec = sn->date_nsec; sn_info->vm_clock_nsec = sn->vm_clock_nsec; + sn_info->icount = sn->icount; } *psn_tab = sn_tab; return s->nb_snapshots; diff --git a/blockdev.c b/blockdev.c index 31d5eaf6bf..50496700af 100644 --- a/blockdev.c +++ b/blockdev.c @@ -59,6 +59,7 @@ #include "sysemu/arch_init.h" #include "sysemu/qtest.h" #include "sysemu/runstate.h" +#include "sysemu/replay.h" #include "qemu/cutils.h" #include "qemu/help_option.h" #include "qemu/main-loop.h" @@ -1200,6 +1201,10 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device, info->vm_state_size = sn.vm_state_size; info->vm_clock_nsec = sn.vm_clock_nsec % 1000000000; info->vm_clock_sec = sn.vm_clock_nsec / 1000000000; + if (sn.icount != -1ULL) { + info->icount = sn.icount; + info->has_icount = true; + } return info; @@ -1360,6 +1365,11 @@ static void internal_snapshot_prepare(BlkActionState *common, sn->date_sec = tv.tv_sec; sn->date_nsec = tv.tv_usec * 1000; sn->vm_clock_nsec = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + if (replay_mode != REPLAY_MODE_NONE) { + sn->icount = replay_get_current_icount(); + } else { + sn->icount = -1ULL; + } ret1 = bdrv_snapshot_create(bs, sn); if (ret1 < 0) { diff --git a/include/block/snapshot.h b/include/block/snapshot.h index 2bfcd57578..b0fe42993d 100644 --- a/include/block/snapshot.h +++ b/include/block/snapshot.h @@ -42,6 +42,7 @@ typedef struct QEMUSnapshotInfo { uint32_t date_sec; /* UTC date of the snapshot */ uint32_t date_nsec; uint64_t vm_clock_nsec; /* VM clock relative to boot */ + uint64_t icount; /* record/replay step */ } QEMUSnapshotInfo; int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info, diff --git a/migration/savevm.c b/migration/savevm.c index b979ea6e7f..f583b9bd08 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -2689,6 +2689,11 @@ int save_snapshot(const char *name, Error **errp) sn->date_sec = tv.tv_sec; sn->date_nsec = tv.tv_usec * 1000; sn->vm_clock_nsec = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + if (replay_mode != REPLAY_MODE_NONE) { + sn->icount = replay_get_current_icount(); + } else { + sn->icount = -1ULL; + } if (name) { ret = bdrv_snapshot_find(bs, old_sn, name); diff --git a/qapi/block-core.json b/qapi/block-core.json index 0e1c6a59f2..125ef7b1c2 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -26,13 +26,18 @@ # # @vm-clock-nsec: fractional part in nano seconds to be used with vm-clock-sec # +# @icount: Current instruction count. Appears when execution record/replay +# is enabled. Used for "time-traveling" to match the moment +# in the recorded execution with the snapshots. (since 5.1) +# # Since: 1.3 # ## { 'struct': 'SnapshotInfo', 'data': { 'id': 'str', 'name': 'str', 'vm-state-size': 'int', 'date-sec': 'int', 'date-nsec': 'int', - 'vm-clock-sec': 'int', 'vm-clock-nsec': 'int' } } + 'vm-clock-sec': 'int', 'vm-clock-nsec': 'int', + '*icount': 'int' } } ## # @ImageInfoSpecificQCow2EncryptionBase: @@ -5458,7 +5463,8 @@ # "date-sec": 1000012, # "date-nsec": 10, # "vm-clock-sec": 100, -# "vm-clock-nsec": 20 +# "vm-clock-nsec": 20, +# "icount": 220414 # } # } # diff --git a/stubs/replay.c b/stubs/replay.c index 5974ec1f50..eacb366aa8 100644 --- a/stubs/replay.c +++ b/stubs/replay.c @@ -88,3 +88,8 @@ int replay_read_random(void *buf, size_t len) { return 0; } + +uint64_t replay_get_current_icount(void) +{ + return 0; +}