qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>
To: qemu-devel@nongnu.org
Cc: kwolf@redhat.com, peter.maydell@linaro.org, war2jordan@live.com,
	crosthwaite.peter@gmail.com, boost.lists@gmail.com,
	artem.k.pisarenko@gmail.com, quintela@redhat.com,
	ciro.santilli@gmail.com, jasowang@redhat.com, mst@redhat.com,
	armbru@redhat.com, mreitz@redhat.com,
	maria.klimushenkova@ispras.ru, dovgaluk@ispras.ru,
	kraxel@redhat.com, pavel.dovgaluk@ispras.ru,
	thomas.dullien@googlemail.com, pbonzini@redhat.com,
	alex.bennee@linaro.org, dgilbert@redhat.com, rth@twiddle.net
Subject: [Qemu-devel] [PATCH v12 08/25] migration: introduce icount field for snapshots
Date: Tue, 05 Feb 2019 11:20:27 +0300	[thread overview]
Message-ID: <154935482702.7509.14721831249423314035.stgit@pasha-VirtualBox> (raw)
In-Reply-To: <154935478086.7509.4349987292919289245.stgit@pasha-VirtualBox>

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 <Pavel.Dovgaluk@ispras.ru>
Acked-by: Markus Armbruster <armbru@redhat.com>

--

v2:
 - made icount in SnapshotInfo optional (suggested by Eric Blake)
v7:
 - added more comments for icount member (suggested by Markus Armbruster)
v9:
 - updated icount comment
v10:
 - updated icount comment again
---
 block/qapi.c             |   18 ++++++++++++++----
 block/qcow2-snapshot.c   |    2 ++
 blockdev.c               |   10 ++++++++++
 include/block/snapshot.h |    1 +
 migration/savevm.c       |    5 +++++
 qapi/block-core.json     |    7 ++++++-
 qapi/block.json          |    3 ++-
 7 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/block/qapi.c b/block/qapi.c
index c66f949db8..ccf23f3b35 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -210,6 +210,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;
@@ -663,14 +665,15 @@ void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f,
                         QEMUSnapshotInfo *sn)
 {
     char buf1[128], date_buf[128], clock_buf[128];
+    char icount_buf[128] = {0};
     struct tm tm;
     time_t ti;
     int64_t secs;
 
     if (!sn) {
         func_fprintf(f,
-                     "%-10s%-20s%7s%20s%15s",
-                     "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
+                     "%-10s%-18s%7s%20s%13s%11s",
+                     "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK", "ICOUNT");
     } else {
         ti = sn->date_sec;
         localtime_r(&ti, &tm);
@@ -683,13 +686,18 @@ void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f,
                  (int)((secs / 60) % 60),
                  (int)(secs % 60),
                  (int)((sn->vm_clock_nsec / 1000000) % 1000));
+        if (sn->icount != -1ULL) {
+            snprintf(icount_buf, sizeof(icount_buf),
+                "%"PRId64, sn->icount);
+        }
         func_fprintf(f,
-                     "%-10s%-20s%7s%20s%15s",
+                     "%-10s%-18s%7s%20s%13s%11s",
                      sn->id_str, sn->name,
                      get_human_readable_size(buf1, sizeof(buf1),
                                              sn->vm_state_size),
                      date_buf,
-                     clock_buf);
+                     clock_buf,
+                     icount_buf);
     }
 }
 
@@ -857,6 +865,8 @@ void bdrv_image_info_dump(fprintf_function func_fprintf, void *f,
                 .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 d68294658a..96b57f4ec8 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -379,6 +379,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;
 
     /* Allocate the L1 table of the snapshot and copy the current one there. */
     l1_table_offset = qcow2_alloc_clusters(bs, s->l1_size * sizeof(uint64_t));
@@ -698,6 +699,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 fb18e9c975..f5775fdf5a 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -57,6 +57,7 @@
 #include "block/trace.h"
 #include "sysemu/arch_init.h"
 #include "sysemu/qtest.h"
+#include "sysemu/replay.h"
 #include "qemu/cutils.h"
 #include "qemu/help_option.h"
 #include "qemu/throttle-options.h"
@@ -1239,6 +1240,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;
 
@@ -1447,6 +1452,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_step();
+    } 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 f73d1094af..c9c89754ef 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 322660438d..fa3b9d1a54 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -2510,6 +2510,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_step();
+    } 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 5f17d67d71..69ec06e8ac 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 4.0)
+#
 # 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:
diff --git a/qapi/block.json b/qapi/block.json
index 5a79d639e8..fd9c0ee715 100644
--- a/qapi/block.json
+++ b/qapi/block.json
@@ -176,7 +176,8 @@
 #                    "date-sec": 1000012,
 #                    "date-nsec": 10,
 #                    "vm-clock-sec": 100,
-#                    "vm-clock-nsec": 20
+#                    "vm-clock-nsec": 20,
+#                    "icount": 220414
 #      }
 #    }
 #

  parent reply	other threads:[~2019-02-05  8:20 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-02-05  8:19 [Qemu-devel] [PATCH v12 00/25] Fixing record/replay and adding reverse debugging Pavel Dovgalyuk
2019-02-05  8:19 ` [Qemu-devel] [PATCH v12 01/25] replay: add missing fix for internal function Pavel Dovgalyuk
2019-02-05  8:19 ` [Qemu-devel] [PATCH v12 02/25] block: implement bdrv_snapshot_goto for blkreplay Pavel Dovgalyuk
2019-02-05  8:19 ` [Qemu-devel] [PATCH v12 03/25] replay: disable default snapshot for record/replay Pavel Dovgalyuk
2019-02-05  8:20 ` [Qemu-devel] [PATCH v12 04/25] replay: update docs for record/replay with block devices Pavel Dovgalyuk
2019-02-05  8:20 ` [Qemu-devel] [PATCH v12 05/25] replay: don't drain/flush bdrv queue while RR is working Pavel Dovgalyuk
2019-02-05  8:20 ` [Qemu-devel] [PATCH v12 06/25] replay: finish record/replay before closing the disks Pavel Dovgalyuk
2019-02-05  8:20 ` [Qemu-devel] [PATCH v12 07/25] qcow2: introduce icount field for snapshots Pavel Dovgalyuk
2019-02-05  8:20 ` Pavel Dovgalyuk [this message]
2019-02-05  8:20 ` [Qemu-devel] [PATCH v12 09/25] replay: provide an accessor for rr filename Pavel Dovgalyuk
2019-02-05  8:20 ` [Qemu-devel] [PATCH v12 10/25] qapi: introduce replay.json for record/replay-related stuff Pavel Dovgalyuk
2019-02-05  8:20 ` [Qemu-devel] [PATCH v12 11/25] replay: introduce info hmp/qmp command Pavel Dovgalyuk
2019-02-05  8:20 ` [Qemu-devel] [PATCH v12 12/25] replay: introduce breakpoint at the specified step Pavel Dovgalyuk
2019-02-05  8:20 ` [Qemu-devel] [PATCH v12 13/25] replay: implement replay-seek command Pavel Dovgalyuk
2019-02-05  8:21 ` [Qemu-devel] [PATCH v12 14/25] replay: refine replay-time module Pavel Dovgalyuk
2019-02-05  8:21 ` [Qemu-devel] [PATCH v12 15/25] replay: flush rr queue before loading the vmstate Pavel Dovgalyuk
2019-02-05  8:21 ` [Qemu-devel] [PATCH v12 16/25] gdbstub: add reverse step support in replay mode Pavel Dovgalyuk
2019-02-05  8:21 ` [Qemu-devel] [PATCH v12 17/25] gdbstub: add reverse continue " Pavel Dovgalyuk
2019-02-05  8:21 ` [Qemu-devel] [PATCH v12 18/25] replay: describe reverse debugging in docs/replay.txt Pavel Dovgalyuk
2019-02-05  8:21 ` [Qemu-devel] [PATCH v12 19/25] replay: add BH oneshot event for block layer Pavel Dovgalyuk
2019-02-05  8:21 ` [Qemu-devel] [PATCH v12 20/25] replay: init rtc after enabling the replay Pavel Dovgalyuk
2019-02-05  8:21 ` [Qemu-devel] [PATCH v12 21/25] replay: document development rules Pavel Dovgalyuk
2019-02-05  8:21 ` [Qemu-devel] [PATCH v12 22/25] util/qemu-timer: refactor deadline calculation for external timers Pavel Dovgalyuk
2019-02-05  8:21 ` [Qemu-devel] [PATCH v12 23/25] replay: fix replay shutdown Pavel Dovgalyuk
2019-02-05  8:21 ` [Qemu-devel] [PATCH v12 24/25] replay: rename step-related variables and functions Pavel Dovgalyuk
2019-02-05  8:22 ` [Qemu-devel] [PATCH v12 25/25] icount: clean up cpu_can_io before jumping to the next block Pavel Dovgalyuk
2019-02-11 12:41 ` [Qemu-devel] [PATCH v12 00/25] Fixing record/replay and adding reverse debugging Pavel Dovgalyuk
2019-02-12  7:14   ` Markus Armbruster
2019-02-12  7:18     ` dovgaluk
2019-02-12  9:18       ` Markus Armbruster
2019-02-18  5:21         ` Pavel Dovgalyuk

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=154935482702.7509.14721831249423314035.stgit@pasha-VirtualBox \
    --to=pavel.dovgaluk@ispras.ru \
    --cc=alex.bennee@linaro.org \
    --cc=armbru@redhat.com \
    --cc=artem.k.pisarenko@gmail.com \
    --cc=boost.lists@gmail.com \
    --cc=ciro.santilli@gmail.com \
    --cc=crosthwaite.peter@gmail.com \
    --cc=dgilbert@redhat.com \
    --cc=dovgaluk@ispras.ru \
    --cc=jasowang@redhat.com \
    --cc=kraxel@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=maria.klimushenkova@ispras.ru \
    --cc=mreitz@redhat.com \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=quintela@redhat.com \
    --cc=rth@twiddle.net \
    --cc=thomas.dullien@googlemail.com \
    --cc=war2jordan@live.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).