diff mbox

[v4,2/8] replay: save/load initial state

Message ID 20160921113315.1420.49751.stgit@PASHA-ISP.def.inno
State New
Headers show

Commit Message

Pavel Dovgalyuk Sept. 21, 2016, 11:33 a.m. UTC
This patch implements initial vmstate creation or loading at the start
of record/replay. It is needed for rewinding the execution in the replay mode.

v4 changes:
 - snapshots are not created by default anymore

v3 changes:
 - added rrsnapshot option

Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
---
 docs/replay.txt          |   16 ++++++++++++++++
 include/sysemu/replay.h  |    9 +++++++++
 qemu-options.hx          |    8 ++++++--
 replay/Makefile.objs     |    1 +
 replay/replay-snapshot.c |   37 +++++++++++++++++++++++++++++++++++++
 replay/replay.c          |    6 ++++++
 vl.c                     |   10 ++++++++--
 7 files changed, 83 insertions(+), 4 deletions(-)
 create mode 100644 replay/replay-snapshot.c

Comments

Paolo Bonzini Sept. 21, 2016, 3:39 p.m. UTC | #1
On 21/09/2016 13:33, Pavel Dovgalyuk wrote:
> +New VM snapshots may be created in replay mode. They can be used later
> +to recover the desired VM state. All VM states created in replay mode
> +are associated with the moment of time in the replay scenario.
> +After recovering the VM state replay will start from that position.
> +
> +Default starting snapshot name may be specified with icount field
> +rrsnapshot as follows:
> + -icount shift=7,rr=record,rrfile=replay.bin,rrsnapshot=snapshot_name
> +
> +This snapshot is created at start of recording and restored at start
> +of replaying. It also can be loaded while replaying to roll back
> +the execution.

Should you mention somewhere that you need -snapshot for raw images?

Paolo
Pavel Dovgalyuk Sept. 21, 2016, 3:49 p.m. UTC | #2
> From: Paolo Bonzini [mailto:pbonzini@redhat.com]
> On 21/09/2016 13:33, Pavel Dovgalyuk wrote:
> > +New VM snapshots may be created in replay mode. They can be used later
> > +to recover the desired VM state. All VM states created in replay mode
> > +are associated with the moment of time in the replay scenario.
> > +After recovering the VM state replay will start from that position.
> > +
> > +Default starting snapshot name may be specified with icount field
> > +rrsnapshot as follows:
> > + -icount shift=7,rr=record,rrfile=replay.bin,rrsnapshot=snapshot_name
> > +
> > +This snapshot is created at start of recording and restored at start
> > +of replaying. It also can be loaded while replaying to roll back
> > +the execution.
> 
> Should you mention somewhere that you need -snapshot for raw images?

Do you mean when rrsnapshot is used with raw images?
I'll update the docs.

Pavel Dovgalyuk
Paolo Bonzini Sept. 21, 2016, 3:57 p.m. UTC | #3
On 21/09/2016 17:49, Pavel Dovgalyuk wrote:
>> From: Paolo Bonzini [mailto:pbonzini@redhat.com]
>> On 21/09/2016 13:33, Pavel Dovgalyuk wrote:
>>> +New VM snapshots may be created in replay mode. They can be used later
>>> +to recover the desired VM state. All VM states created in replay mode
>>> +are associated with the moment of time in the replay scenario.
>>> +After recovering the VM state replay will start from that position.
>>> +
>>> +Default starting snapshot name may be specified with icount field
>>> +rrsnapshot as follows:
>>> + -icount shift=7,rr=record,rrfile=replay.bin,rrsnapshot=snapshot_name
>>> +
>>> +This snapshot is created at start of recording and restored at start
>>> +of replaying. It also can be loaded while replaying to roll back
>>> +the execution.
>>
>> Should you mention somewhere that you need -snapshot for raw images?
> 
> Do you mean when rrsnapshot is used with raw images?

I mean that (if I understand correctly) raw images are corrupted if you
don't use -snapshot (the record overwrites them, and the replay reads
overwritten data).

Paolo

> I'll update the docs.
> 
> Pavel Dovgalyuk
>
Pavel Dovgalyuk Sept. 22, 2016, 5:37 a.m. UTC | #4
> From: Paolo Bonzini [mailto:pbonzini@redhat.com]
> On 21/09/2016 17:49, Pavel Dovgalyuk wrote:
> >> From: Paolo Bonzini [mailto:pbonzini@redhat.com]
> >> On 21/09/2016 13:33, Pavel Dovgalyuk wrote:
> >>> +New VM snapshots may be created in replay mode. They can be used later
> >>> +to recover the desired VM state. All VM states created in replay mode
> >>> +are associated with the moment of time in the replay scenario.
> >>> +After recovering the VM state replay will start from that position.
> >>> +
> >>> +Default starting snapshot name may be specified with icount field
> >>> +rrsnapshot as follows:
> >>> + -icount shift=7,rr=record,rrfile=replay.bin,rrsnapshot=snapshot_name
> >>> +
> >>> +This snapshot is created at start of recording and restored at start
> >>> +of replaying. It also can be loaded while replaying to roll back
> >>> +the execution.
> >>
> >> Should you mention somewhere that you need -snapshot for raw images?
> >
> > Do you mean when rrsnapshot is used with raw images?
> 
> I mean that (if I understand correctly) raw images are corrupted if you
> don't use -snapshot (the record overwrites them, and the replay reads
> overwritten data).

I tried running record/replay with raw image. Record finished without an error,
but replay couldn't start, because there was no snapshot to load.
I think the solution is checking savevm return code and exiting if snapshot cannot be created.

Pavel Dovgalyuk
Paolo Bonzini Sept. 22, 2016, 8:51 a.m. UTC | #5
On 22/09/2016 07:37, Pavel Dovgalyuk wrote:
>> > I mean that (if I understand correctly) raw images are corrupted if you
>> > don't use -snapshot (the record overwrites them, and the replay reads
>> > overwritten data).
> I tried running record/replay with raw image. Record finished without an error,
> but replay couldn't start, because there was no snapshot to load.
> I think the solution is checking savevm return code and exiting if snapshot cannot be created.

Yep, good idea.

Paolo
diff mbox

Patch

diff --git a/docs/replay.txt b/docs/replay.txt
index 347b2ff..03e1931 100644
--- a/docs/replay.txt
+++ b/docs/replay.txt
@@ -196,6 +196,22 @@  is recorded to the log. In replay phase the queue is matched with
 events read from the log. Therefore block devices requests are processed
 deterministically.
 
+Snapshotting
+------------
+
+New VM snapshots may be created in replay mode. They can be used later
+to recover the desired VM state. All VM states created in replay mode
+are associated with the moment of time in the replay scenario.
+After recovering the VM state replay will start from that position.
+
+Default starting snapshot name may be specified with icount field
+rrsnapshot as follows:
+ -icount shift=7,rr=record,rrfile=replay.bin,rrsnapshot=snapshot_name
+
+This snapshot is created at start of recording and restored at start
+of replaying. It also can be loaded while replaying to roll back
+the execution.
+
 Network devices
 ---------------
 
diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h
index a408633..95a35ee 100644
--- a/include/sysemu/replay.h
+++ b/include/sysemu/replay.h
@@ -43,6 +43,9 @@  typedef struct ReplayNetState ReplayNetState;
 
 extern ReplayMode replay_mode;
 
+/* Name of the initial VM snapshot */
+extern char *replay_snapshot;
+
 /* Replay process control functions */
 
 /*! Enables recording or saving event log with specified parameters */
@@ -145,4 +148,10 @@  void replay_unregister_net(ReplayNetState *rns);
 void replay_net_packet_event(ReplayNetState *rns, unsigned flags,
                              const struct iovec *iov, int iovcnt);
 
+/* VM state operations */
+
+/*! Called at the start of execution.
+    Loads or saves initial vmstate depending on execution mode. */
+void replay_vmstate_init(void);
+
 #endif
diff --git a/qemu-options.hx b/qemu-options.hx
index 0b621bb..1aa046e 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3367,12 +3367,12 @@  re-inject them.
 ETEXI
 
 DEF("icount", HAS_ARG, QEMU_OPTION_icount, \
-    "-icount [shift=N|auto][,align=on|off][,sleep=on|off,rr=record|replay,rrfile=<filename>]\n" \
+    "-icount [shift=N|auto][,align=on|off][,sleep=on|off,rr=record|replay,rrfile=<filename>,rrsnapshot=<snapshot>]\n" \
     "                enable virtual instruction counter with 2^N clock ticks per\n" \
     "                instruction, enable aligning the host and virtual clocks\n" \
     "                or disable real time cpu sleeping\n", QEMU_ARCH_ALL)
 STEXI
-@item -icount [shift=@var{N}|auto][,rr=record|replay,rrfile=@var{filename}]
+@item -icount [shift=@var{N}|auto][,rr=record|replay,rrfile=@var{filename},rrsnapshot=@var{snapshot}]
 @findex -icount
 Enable virtual instruction counter.  The virtual cpu will execute one
 instruction every 2^@var{N} ns of virtual time.  If @code{auto} is specified
@@ -3405,6 +3405,10 @@  when the shift value is high (how high depends on the host machine).
 When @option{rr} option is specified deterministic record/replay is enabled.
 Replay log is written into @var{filename} file in record mode and
 read from this file in replay mode.
+
+Option rrsnapshot is used to create new vm snapshot named @var{snapshot}
+at the start of execution recording. In replay mode this option is used
+to load the initial VM state.
 ETEXI
 
 DEF("watchdog", HAS_ARG, QEMU_OPTION_watchdog, \
diff --git a/replay/Makefile.objs b/replay/Makefile.objs
index f55a6b5..4600d74 100644
--- a/replay/Makefile.objs
+++ b/replay/Makefile.objs
@@ -5,3 +5,4 @@  common-obj-y += replay-time.o
 common-obj-y += replay-input.o
 common-obj-y += replay-char.o
 common-obj-y += replay-net.o
+common-obj-y += replay-snapshot.o
diff --git a/replay/replay-snapshot.c b/replay/replay-snapshot.c
new file mode 100644
index 0000000..970b893
--- /dev/null
+++ b/replay/replay-snapshot.c
@@ -0,0 +1,37 @@ 
+/*
+ * replay-snapshot.c
+ *
+ * Copyright (c) 2010-2016 Institute for System Programming
+ *                         of the Russian Academy of Sciences.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "sysemu/replay.h"
+#include "replay-internal.h"
+#include "sysemu/sysemu.h"
+#include "monitor/monitor.h"
+#include "qapi/qmp/qstring.h"
+#include "qemu/error-report.h"
+
+void replay_vmstate_init(void)
+{
+    if (replay_snapshot) {
+        if (replay_mode == REPLAY_MODE_RECORD) {
+            QDict *opts = qdict_new();
+            qdict_put(opts, "name", qstring_from_str(replay_snapshot));
+            hmp_savevm(cur_mon, opts);
+            QDECREF(opts);
+        } else if (replay_mode == REPLAY_MODE_PLAY) {
+            if (load_vmstate(replay_snapshot) != 0) {
+                error_report("Could not load snapshot for replay");
+                exit(1);
+            }
+        }
+    }
+}
diff --git a/replay/replay.c b/replay/replay.c
index e040f6f..87b93d7 100644
--- a/replay/replay.c
+++ b/replay/replay.c
@@ -26,6 +26,7 @@ 
 #define HEADER_SIZE                 (sizeof(uint32_t) + sizeof(uint64_t))
 
 ReplayMode replay_mode = REPLAY_MODE_NONE;
+char *replay_snapshot;
 
 /* Name of replay file  */
 static char *replay_filename;
@@ -291,6 +292,8 @@  void replay_configure(QemuOpts *opts)
         exit(1);
     }
 
+    replay_snapshot = g_strdup(qemu_opt_get(opts, "rrsnapshot"));
+
     replay_enable(fname, mode);
 
 out:
@@ -344,6 +347,9 @@  void replay_finish(void)
         replay_filename = NULL;
     }
 
+    g_free(replay_snapshot);
+    replay_snapshot = NULL;
+
     replay_finish_events();
     replay_mutex_destroy();
 }
diff --git a/vl.c b/vl.c
index fd7f17e..c5ceb99 100644
--- a/vl.c
+++ b/vl.c
@@ -460,6 +460,9 @@  static QemuOptsList qemu_icount_opts = {
         }, {
             .name = "rrfile",
             .type = QEMU_OPT_STRING,
+        }, {
+            .name = "rrsnapshot",
+            .type = QEMU_OPT_STRING,
         },
         { /* end of list */ }
     },
@@ -4410,7 +4413,8 @@  int main(int argc, char **argv, char **envp)
     }
 
     /* open the virtual block devices */
-    if (snapshot || replay_mode != REPLAY_MODE_NONE) {
+    if (snapshot
+        || (replay_mode != REPLAY_MODE_NONE && !replay_snapshot)) {
         qemu_opts_foreach(qemu_find_opts("drive"), drive_enable_snapshot,
                           NULL, NULL);
     }
@@ -4590,7 +4594,9 @@  int main(int argc, char **argv, char **envp)
     replay_checkpoint(CHECKPOINT_RESET);
     qemu_system_reset(VMRESET_SILENT);
     register_global_state();
-    if (loadvm) {
+    if (replay_mode != REPLAY_MODE_NONE) {
+        replay_vmstate_init();
+    } else if (loadvm) {
         if (load_vmstate(loadvm) < 0) {
             autostart = 0;
         }