All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v4 0/8] replay additions
@ 2016-09-21 11:33 Pavel Dovgalyuk
  2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 1/8] record/replay: add network support Pavel Dovgalyuk
                   ` (8 more replies)
  0 siblings, 9 replies; 22+ messages in thread
From: Pavel Dovgalyuk @ 2016-09-21 11:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jasowang, quintela, pbonzini, mst

This set of patches includes several fixes for replay and
adds network record/replay for network devices. It also makes possible
saving/restoring vmstate in replay mode.

Record and replay for network interactions is performed with the network filter.
Each backend must have its own instance of the replay filter as follows:
 -netdev user,id=net1 -device rtl8139,netdev=net1
 -object filter-replay,id=replay,netdev=net1

This patches add rrsnapshot option for icount. rrshapshot option creates
start snapshot at record and loads it at replay. It allows preserving
the state of disk images used by virtual machine. This vm state can also
use used to roll back the execution while replaying.

This set of patches includes fixes and additions for icount and
record/replay implementation:
 - VM start/stop in replay mode
 - Network interaction record/replay
 - overlay option for blkreplay filter
 - rrsnapshot option for record/replay
 - vmstate fix for integratorcp ARM platform

v4 changes:
 - Overlay option is removed from blkreplay driver (as suggested by Paolo Bonzini)
 - Minor changes

v3 changes:
 - Added rrsnapshot option for specifying the initial snapshot name (as suggested by Paolo Bonzini)
 - Minor changes

---

Pavel Dovgalyuk (8):
      record/replay: add network support
      replay: save/load initial state
      block: don't make snapshots for filters
      block: implement bdrv_recurse_is_first_non_filter for blkreplay
      replay: move internal data to the structure
      replay: vmstate for replay module
      replay: allow replay stopping and restarting
      integratorcp: adding vmstate for save/restore


 block/blkreplay.c        |   24 ++++++----
 block/snapshot.c         |    3 +
 cpus.c                   |    1 
 docs/replay.txt          |   30 ++++++++++++
 hw/arm/integratorcp.c    |   62 ++++++++++++++++++++++++++
 include/sysemu/replay.h  |   25 ++++++++++
 net/Makefile.objs        |    1 
 net/filter-replay.c      |   92 ++++++++++++++++++++++++++++++++++++++
 qemu-options.hx          |    8 ++-
 replay/Makefile.objs     |    2 +
 replay/replay-events.c   |   21 ++++++++-
 replay/replay-internal.c |   20 ++++----
 replay/replay-internal.h |   33 ++++++++++++--
 replay/replay-net.c      |  111 ++++++++++++++++++++++++++++++++++++++++++++++
 replay/replay-snapshot.c |   78 ++++++++++++++++++++++++++++++++
 replay/replay-time.c     |    2 -
 replay/replay.c          |   24 +++++++---
 stubs/replay.c           |    5 ++
 vl.c                     |   14 +++++-
 19 files changed, 515 insertions(+), 41 deletions(-)
 create mode 100644 net/filter-replay.c
 create mode 100644 replay/replay-net.c
 create mode 100644 replay/replay-snapshot.c

-- 
Pavel Dovgalyuk

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH v4 1/8] record/replay: add network support
  2016-09-21 11:33 [Qemu-devel] [PATCH v4 0/8] replay additions Pavel Dovgalyuk
@ 2016-09-21 11:33 ` Pavel Dovgalyuk
  2016-09-23  6:06   ` Jason Wang
  2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 2/8] replay: save/load initial state Pavel Dovgalyuk
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: Pavel Dovgalyuk @ 2016-09-21 11:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jasowang, quintela, pbonzini, mst

This patch adds support of recording and replaying network packets in
irount rr mode.

Record and replay for network interactions is performed with the network filter.
Each backend must have its own instance of the replay filter as follows:
 -netdev user,id=net1 -device rtl8139,netdev=net1
 -object filter-replay,id=replay,netdev=net1

Replay network filter is used to record and replay network packets. While
recording the virtual machine this filter puts all packets coming from
the outer world into the log. In replay mode packets from the log are
injected into the network device. All interactions with network backend
in replay mode are disabled.

Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
---
 docs/replay.txt          |   14 ++++++
 include/sysemu/replay.h  |   12 +++++
 net/Makefile.objs        |    1 
 net/filter-replay.c      |   92 ++++++++++++++++++++++++++++++++++++++
 replay/Makefile.objs     |    1 
 replay/replay-events.c   |   11 +++++
 replay/replay-internal.h |   10 ++++
 replay/replay-net.c      |  111 ++++++++++++++++++++++++++++++++++++++++++++++
 replay/replay.c          |    2 -
 vl.c                     |    3 +
 10 files changed, 255 insertions(+), 2 deletions(-)
 create mode 100644 net/filter-replay.c
 create mode 100644 replay/replay-net.c

diff --git a/docs/replay.txt b/docs/replay.txt
index 779c6c0..347b2ff 100644
--- a/docs/replay.txt
+++ b/docs/replay.txt
@@ -195,3 +195,17 @@ Queue is flushed at checkpoints and information about processed requests
 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.
+
+Network devices
+---------------
+
+Record and replay for network interactions is performed with the network filter.
+Each backend must have its own instance of the replay filter as follows:
+ -netdev user,id=net1 -device rtl8139,netdev=net1
+ -object filter-replay,id=replay,netdev=net1
+
+Replay network filter is used to record and replay network packets. While
+recording the virtual machine this filter puts all packets coming from
+the outer world into the log. In replay mode packets from the log are
+injected into the network device. All interactions with network backend
+in replay mode are disabled.
diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h
index 0a88393..a408633 100644
--- a/include/sysemu/replay.h
+++ b/include/sysemu/replay.h
@@ -39,6 +39,8 @@ enum ReplayCheckpoint {
 };
 typedef enum ReplayCheckpoint ReplayCheckpoint;
 
+typedef struct ReplayNetState ReplayNetState;
+
 extern ReplayMode replay_mode;
 
 /* Replay process control functions */
@@ -133,4 +135,14 @@ void replay_char_read_all_save_error(int res);
 /*! Writes character read_all execution result into the replay log. */
 void replay_char_read_all_save_buf(uint8_t *buf, int offset);
 
+/* Network */
+
+/*! Registers replay network filter attached to some backend. */
+ReplayNetState *replay_register_net(NetFilterState *nfs);
+/*! Unregisters replay network filter. */
+void replay_unregister_net(ReplayNetState *rns);
+/*! Called to write network packet to the replay log. */
+void replay_net_packet_event(ReplayNetState *rns, unsigned flags,
+                             const struct iovec *iov, int iovcnt);
+
 #endif
diff --git a/net/Makefile.objs b/net/Makefile.objs
index b7c22fd..f787ba4 100644
--- a/net/Makefile.objs
+++ b/net/Makefile.objs
@@ -16,3 +16,4 @@ common-obj-$(CONFIG_NETMAP) += netmap.o
 common-obj-y += filter.o
 common-obj-y += filter-buffer.o
 common-obj-y += filter-mirror.o
+common-obj-y += filter-replay.o
diff --git a/net/filter-replay.c b/net/filter-replay.c
new file mode 100644
index 0000000..cff65f8
--- /dev/null
+++ b/net/filter-replay.c
@@ -0,0 +1,92 @@
+/*
+ * filter-replay.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 "clients.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "qemu/error-report.h"
+#include "qemu/iov.h"
+#include "qemu/log.h"
+#include "qemu/timer.h"
+#include "qapi/visitor.h"
+#include "net/filter.h"
+#include "sysemu/replay.h"
+
+#define TYPE_FILTER_REPLAY "filter-replay"
+
+#define FILTER_REPLAY(obj) \
+    OBJECT_CHECK(NetFilterReplayState, (obj), TYPE_FILTER_REPLAY)
+
+struct NetFilterReplayState {
+    NetFilterState nfs;
+    ReplayNetState *rns;
+};
+typedef struct NetFilterReplayState NetFilterReplayState;
+
+static ssize_t filter_replay_receive_iov(NetFilterState *nf,
+                                         NetClientState *sndr,
+                                         unsigned flags,
+                                         const struct iovec *iov,
+                                         int iovcnt, NetPacketSent *sent_cb)
+{
+    NetFilterReplayState *nfrs = FILTER_REPLAY(nf);
+    switch (replay_mode) {
+    case REPLAY_MODE_RECORD:
+        if (nf->netdev == sndr) {
+            replay_net_packet_event(nfrs->rns, flags, iov, iovcnt);
+            return iov_size(iov, iovcnt);
+        }
+        return 0;
+    case REPLAY_MODE_PLAY:
+        /* Drop all packets in replay mode.
+           Packets from the log will be injected by the replay module. */
+        return iov_size(iov, iovcnt);
+    default:
+        /* Pass all the packets. */
+        return 0;
+    }
+}
+
+static void filter_replay_instance_init(Object *obj)
+{
+    NetFilterReplayState *nfrs = FILTER_REPLAY(obj);
+    nfrs->rns = replay_register_net(&nfrs->nfs);
+}
+
+static void filter_replay_instance_finalize(Object *obj)
+{
+    NetFilterReplayState *nfrs = FILTER_REPLAY(obj);
+    replay_unregister_net(nfrs->rns);
+}
+
+static void filter_replay_class_init(ObjectClass *oc, void *data)
+{
+    NetFilterClass *nfc = NETFILTER_CLASS(oc);
+
+    nfc->receive_iov = filter_replay_receive_iov;
+}
+
+static const TypeInfo filter_replay_info = {
+    .name = TYPE_FILTER_REPLAY,
+    .parent = TYPE_NETFILTER,
+    .class_init = filter_replay_class_init,
+    .instance_init = filter_replay_instance_init,
+    .instance_finalize = filter_replay_instance_finalize,
+    .instance_size = sizeof(NetFilterReplayState),
+};
+
+static void filter_replay_register_types(void)
+{
+    type_register_static(&filter_replay_info);
+}
+
+type_init(filter_replay_register_types);
diff --git a/replay/Makefile.objs b/replay/Makefile.objs
index fcb3f74..f55a6b5 100644
--- a/replay/Makefile.objs
+++ b/replay/Makefile.objs
@@ -4,3 +4,4 @@ common-obj-y += replay-events.o
 common-obj-y += replay-time.o
 common-obj-y += replay-input.o
 common-obj-y += replay-char.o
+common-obj-y += replay-net.o
diff --git a/replay/replay-events.c b/replay/replay-events.c
index 3807245..9ce9e51 100644
--- a/replay/replay-events.c
+++ b/replay/replay-events.c
@@ -54,6 +54,9 @@ static void replay_run_event(Event *event)
     case REPLAY_ASYNC_EVENT_BLOCK:
         aio_bh_call(event->opaque);
         break;
+    case REPLAY_ASYNC_EVENT_NET:
+        replay_event_net_run(event->opaque);
+        break;
     default:
         error_report("Replay: invalid async event ID (%d) in the queue",
                     event->event_kind);
@@ -189,6 +192,9 @@ static void replay_save_event(Event *event, int checkpoint)
         case REPLAY_ASYNC_EVENT_BLOCK:
             replay_put_qword(event->id);
             break;
+        case REPLAY_ASYNC_EVENT_NET:
+            replay_event_net_save(event->opaque);
+            break;
         default:
             error_report("Unknown ID %" PRId64 " of replay event", event->id);
             exit(1);
@@ -252,6 +258,11 @@ static Event *replay_read_event(int checkpoint)
             read_id = replay_get_qword();
         }
         break;
+    case REPLAY_ASYNC_EVENT_NET:
+        event = g_malloc0(sizeof(Event));
+        event->event_kind = read_event_kind;
+        event->opaque = replay_event_net_load();
+        return event;
     default:
         error_report("Unknown ID %d of replay event", read_event_kind);
         exit(1);
diff --git a/replay/replay-internal.h b/replay/replay-internal.h
index efbf14c..d28cfb7 100644
--- a/replay/replay-internal.h
+++ b/replay/replay-internal.h
@@ -50,6 +50,7 @@ enum ReplayAsyncEventKind {
     REPLAY_ASYNC_EVENT_INPUT_SYNC,
     REPLAY_ASYNC_EVENT_CHAR_READ,
     REPLAY_ASYNC_EVENT_BLOCK,
+    REPLAY_ASYNC_EVENT_NET,
     REPLAY_ASYNC_COUNT
 };
 
@@ -155,4 +156,13 @@ void replay_event_char_read_save(void *opaque);
 /*! Reads char event read from the file. */
 void *replay_event_char_read_load(void);
 
+/* Network devices */
+
+/*! Called to run network event. */
+void replay_event_net_run(void *opaque);
+/*! Writes network event to the file. */
+void replay_event_net_save(void *opaque);
+/*! Reads network from the file. */
+void *replay_event_net_load(void);
+
 #endif
diff --git a/replay/replay-net.c b/replay/replay-net.c
new file mode 100644
index 0000000..4f7b995
--- /dev/null
+++ b/replay/replay-net.c
@@ -0,0 +1,111 @@
+/*
+ * replay-net.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 "qemu/error-report.h"
+#include "sysemu/replay.h"
+#include "replay-internal.h"
+#include "sysemu/sysemu.h"
+#include "net/net.h"
+#include "net/filter.h"
+#include "qemu/iov.h"
+
+struct ReplayNetState {
+    NetFilterState *nfs;
+    int id;
+};
+
+typedef struct NetEvent {
+    uint8_t id;
+    uint32_t flags;
+    uint8_t *data;
+    size_t size;
+} NetEvent;
+
+static NetFilterState **network_filters;
+static int network_filters_count;
+
+ReplayNetState *replay_register_net(NetFilterState *nfs)
+{
+    ReplayNetState *rns = g_new0(ReplayNetState, 1);
+    rns->nfs = nfs;
+    rns->id = network_filters_count++;
+    network_filters = g_realloc(network_filters,
+                                network_filters_count
+                                    * sizeof(*network_filters));
+    network_filters[network_filters_count - 1] = nfs;
+    return rns;
+}
+
+void replay_unregister_net(ReplayNetState *rns)
+{
+    network_filters[rns->id] = NULL;
+    g_free(rns);
+}
+
+void replay_net_packet_event(ReplayNetState *rns, unsigned flags,
+                             const struct iovec *iov, int iovcnt)
+{
+    NetEvent *event;
+    int i;
+
+    event = g_new(NetEvent, 1);
+    event->flags = flags;
+    event->data = g_malloc(iov_size(iov, iovcnt));
+    event->size = 0;
+    event->id = rns->id;
+
+    for (i = 0; i < iovcnt; i++) {
+        size_t len = iov[i].iov_len;
+
+        memcpy(event->data + event->size, iov[i].iov_base, len);
+        event->size += len;
+    }
+
+    replay_add_event(REPLAY_ASYNC_EVENT_NET, event, NULL, 0);
+}
+
+void replay_event_net_run(void *opaque)
+{
+    NetEvent *event = opaque;
+    struct iovec iov = {
+        .iov_base = (void *)event->data,
+        .iov_len = event->size
+    };
+
+    assert(event->id < network_filters_count);
+
+    qemu_netfilter_pass_to_next(network_filters[event->id]->netdev,
+        event->flags, &iov, 1, network_filters[event->id]);
+
+    g_free(event->data);
+    g_free(event);
+}
+
+void replay_event_net_save(void *opaque)
+{
+    NetEvent *event = opaque;
+
+    replay_put_byte(event->id);
+    replay_put_dword(event->flags);
+    replay_put_array(event->data, event->size);
+}
+
+void *replay_event_net_load(void)
+{
+    NetEvent *event = g_new(NetEvent, 1);
+
+    event->id = replay_get_byte();
+    event->flags = replay_get_dword();
+    replay_get_array_alloc(&event->data, &event->size);
+
+    return event;
+}
diff --git a/replay/replay.c b/replay/replay.c
index 167fd29..e040f6f 100644
--- a/replay/replay.c
+++ b/replay/replay.c
@@ -21,7 +21,7 @@
 
 /* Current version of the replay mechanism.
    Increase it when file format changes. */
-#define REPLAY_VERSION              0xe02004
+#define REPLAY_VERSION              0xe02005
 /* Size of replay log header */
 #define HEADER_SIZE                 (sizeof(uint32_t) + sizeof(uint64_t))
 
diff --git a/vl.c b/vl.c
index fca0487..fd7f17e 100644
--- a/vl.c
+++ b/vl.c
@@ -2807,7 +2807,8 @@ static bool object_create_initial(const char *type)
     if (g_str_equal(type, "filter-buffer") ||
         g_str_equal(type, "filter-dump") ||
         g_str_equal(type, "filter-mirror") ||
-        g_str_equal(type, "filter-redirector")) {
+        g_str_equal(type, "filter-redirector") ||
+        g_str_equal(type, "filter-replay")) {
         return false;
     }
 

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH v4 2/8] replay: save/load initial state
  2016-09-21 11:33 [Qemu-devel] [PATCH v4 0/8] replay additions Pavel Dovgalyuk
  2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 1/8] record/replay: add network support Pavel Dovgalyuk
@ 2016-09-21 11:33 ` Pavel Dovgalyuk
  2016-09-21 15:39   ` Paolo Bonzini
  2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 3/8] block: don't make snapshots for filters Pavel Dovgalyuk
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: Pavel Dovgalyuk @ 2016-09-21 11:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jasowang, quintela, pbonzini, mst

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

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;
         }

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH v4 3/8] block: don't make snapshots for filters
  2016-09-21 11:33 [Qemu-devel] [PATCH v4 0/8] replay additions Pavel Dovgalyuk
  2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 1/8] record/replay: add network support Pavel Dovgalyuk
  2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 2/8] replay: save/load initial state Pavel Dovgalyuk
@ 2016-09-21 11:33 ` Pavel Dovgalyuk
  2016-09-21 15:37   ` Paolo Bonzini
  2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 4/8] block: implement bdrv_recurse_is_first_non_filter for blkreplay Pavel Dovgalyuk
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: Pavel Dovgalyuk @ 2016-09-21 11:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jasowang, quintela, pbonzini, mst

This patch disables snapshotting for block driver filters.
It is needed, because snapshots should be created
in underlying disk images, not in filters itself.

Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
---
 block/snapshot.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/block/snapshot.c b/block/snapshot.c
index bf5c2ca..8998b8b 100644
--- a/block/snapshot.c
+++ b/block/snapshot.c
@@ -184,6 +184,9 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
     if (!drv) {
         return -ENOMEDIUM;
     }
+    if (drv->is_filter) {
+        return 0;
+    }
     if (drv->bdrv_snapshot_goto) {
         return drv->bdrv_snapshot_goto(bs, snapshot_id);
     }

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH v4 4/8] block: implement bdrv_recurse_is_first_non_filter for blkreplay
  2016-09-21 11:33 [Qemu-devel] [PATCH v4 0/8] replay additions Pavel Dovgalyuk
                   ` (2 preceding siblings ...)
  2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 3/8] block: don't make snapshots for filters Pavel Dovgalyuk
@ 2016-09-21 11:33 ` Pavel Dovgalyuk
  2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 5/8] replay: move internal data to the structure Pavel Dovgalyuk
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 22+ messages in thread
From: Pavel Dovgalyuk @ 2016-09-21 11:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jasowang, quintela, pbonzini, mst

This patch adds bdrv_recurse_is_first_non_filter implementation
for blkreplay driver. It allows creating snapshots when blkreplay
is enabled.

Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
---
 block/blkreplay.c |    9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/block/blkreplay.c b/block/blkreplay.c
index 30f9d5f..ca18906 100644
--- a/block/blkreplay.c
+++ b/block/blkreplay.c
@@ -135,6 +135,12 @@ static int coroutine_fn blkreplay_co_flush(BlockDriverState *bs)
     return ret;
 }
 
+static bool blkreplay_recurse_is_first_non_filter(BlockDriverState *bs,
+                                                  BlockDriverState *candidate)
+{
+    return bdrv_recurse_is_first_non_filter(bs->file->bs, candidate);
+}
+
 static BlockDriver bdrv_blkreplay = {
     .format_name            = "blkreplay",
     .protocol_name          = "blkreplay",
@@ -150,6 +156,9 @@ static BlockDriver bdrv_blkreplay = {
     .bdrv_co_pwrite_zeroes  = blkreplay_co_pwrite_zeroes,
     .bdrv_co_pdiscard       = blkreplay_co_pdiscard,
     .bdrv_co_flush          = blkreplay_co_flush,
+
+    .is_filter              = true,
+    .bdrv_recurse_is_first_non_filter = blkreplay_recurse_is_first_non_filter,
 };
 
 static void bdrv_blkreplay_init(void)

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH v4 5/8] replay: move internal data to the structure
  2016-09-21 11:33 [Qemu-devel] [PATCH v4 0/8] replay additions Pavel Dovgalyuk
                   ` (3 preceding siblings ...)
  2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 4/8] block: implement bdrv_recurse_is_first_non_filter for blkreplay Pavel Dovgalyuk
@ 2016-09-21 11:33 ` Pavel Dovgalyuk
  2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 6/8] replay: vmstate for replay module Pavel Dovgalyuk
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 22+ messages in thread
From: Pavel Dovgalyuk @ 2016-09-21 11:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jasowang, quintela, pbonzini, mst

This patch moves replay static variables into the structure
to allow saving and loading them with savevm/loadvm.

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>

Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
---
 replay/replay-events.c   |    2 +-
 replay/replay-internal.c |   20 +++++++++-----------
 replay/replay-internal.h |    8 +++++---
 replay/replay-time.c     |    2 +-
 replay/replay.c          |   15 ++++++++-------
 5 files changed, 24 insertions(+), 23 deletions(-)

diff --git a/replay/replay-events.c b/replay/replay-events.c
index 9ce9e51..4ee2f5d 100644
--- a/replay/replay-events.c
+++ b/replay/replay-events.c
@@ -290,7 +290,7 @@ static Event *replay_read_event(int checkpoint)
 /* Called with replay mutex locked */
 void replay_read_events(int checkpoint)
 {
-    while (replay_data_kind == EVENT_ASYNC) {
+    while (replay_state.data_kind == EVENT_ASYNC) {
         Event *event = replay_read_event(checkpoint);
         if (!event) {
             break;
diff --git a/replay/replay-internal.c b/replay/replay-internal.c
index 5835e8d..bea7b4a 100644
--- a/replay/replay-internal.c
+++ b/replay/replay-internal.c
@@ -16,11 +16,8 @@
 #include "qemu/error-report.h"
 #include "sysemu/sysemu.h"
 
-unsigned int replay_data_kind = -1;
-static unsigned int replay_has_unread_data;
-
 /* Mutex to protect reading and writing events to the log.
-   replay_data_kind and replay_has_unread_data are also protected
+   data_kind and has_unread_data are also protected
    by this mutex.
    It also protects replay events queue which stores events to be
    written or read to the log. */
@@ -150,15 +147,16 @@ void replay_check_error(void)
 void replay_fetch_data_kind(void)
 {
     if (replay_file) {
-        if (!replay_has_unread_data) {
-            replay_data_kind = replay_get_byte();
-            if (replay_data_kind == EVENT_INSTRUCTION) {
+        if (!replay_state.has_unread_data) {
+            replay_state.data_kind = replay_get_byte();
+            if (replay_state.data_kind == EVENT_INSTRUCTION) {
                 replay_state.instructions_count = replay_get_dword();
             }
             replay_check_error();
-            replay_has_unread_data = 1;
-            if (replay_data_kind >= EVENT_COUNT) {
-                error_report("Replay: unknown event kind %d", replay_data_kind);
+            replay_state.has_unread_data = 1;
+            if (replay_state.data_kind >= EVENT_COUNT) {
+                error_report("Replay: unknown event kind %d",
+                             replay_state.data_kind);
                 exit(1);
             }
         }
@@ -167,7 +165,7 @@ void replay_fetch_data_kind(void)
 
 void replay_finish_event(void)
 {
-    replay_has_unread_data = 0;
+    replay_state.has_unread_data = 0;
     replay_fetch_data_kind();
 }
 
diff --git a/replay/replay-internal.h b/replay/replay-internal.h
index d28cfb7..3147d66 100644
--- a/replay/replay-internal.h
+++ b/replay/replay-internal.h
@@ -63,11 +63,13 @@ typedef struct ReplayState {
     uint64_t current_step;
     /*! Number of instructions to be executed before other events happen. */
     int instructions_count;
+    /*! Type of the currently executed event. */
+    unsigned int data_kind;
+    /*! Flag which indicates that event is not processed yet. */
+    unsigned int has_unread_data;
 } ReplayState;
 extern ReplayState replay_state;
 
-extern unsigned int replay_data_kind;
-
 /* File for replay writing */
 extern FILE *replay_file;
 
@@ -99,7 +101,7 @@ void replay_check_error(void);
     the next event from the log. */
 void replay_finish_event(void);
 /*! Reads data type from the file and stores it in the
-    replay_data_kind variable. */
+    data_kind variable. */
 void replay_fetch_data_kind(void);
 
 /*! Saves queued events (like instructions and sound). */
diff --git a/replay/replay-time.c b/replay/replay-time.c
index fffe072..f70382a 100644
--- a/replay/replay-time.c
+++ b/replay/replay-time.c
@@ -31,7 +31,7 @@ int64_t replay_save_clock(ReplayClockKind kind, int64_t clock)
 
 void replay_read_next_clock(ReplayClockKind kind)
 {
-    unsigned int read_kind = replay_data_kind - EVENT_CLOCK;
+    unsigned int read_kind = replay_state.data_kind - EVENT_CLOCK;
 
     assert(read_kind == kind);
 
diff --git a/replay/replay.c b/replay/replay.c
index 87b93d7..9472d4c 100644
--- a/replay/replay.c
+++ b/replay/replay.c
@@ -39,15 +39,15 @@ bool replay_next_event_is(int event)
 
     /* nothing to skip - not all instructions used */
     if (replay_state.instructions_count != 0) {
-        assert(replay_data_kind == EVENT_INSTRUCTION);
+        assert(replay_state.data_kind == EVENT_INSTRUCTION);
         return event == EVENT_INSTRUCTION;
     }
 
     while (true) {
-        if (event == replay_data_kind) {
+        if (event == replay_state.data_kind) {
             res = true;
         }
-        switch (replay_data_kind) {
+        switch (replay_state.data_kind) {
         case EVENT_SHUTDOWN:
             replay_finish_event();
             qemu_system_shutdown_request();
@@ -86,7 +86,7 @@ void replay_account_executed_instructions(void)
             replay_state.instructions_count -= count;
             replay_state.current_step += count;
             if (replay_state.instructions_count == 0) {
-                assert(replay_data_kind == EVENT_INSTRUCTION);
+                assert(replay_state.data_kind == EVENT_INSTRUCTION);
                 replay_finish_event();
                 /* Wake up iothread. This is required because
                    timers will not expire until clock counters
@@ -189,7 +189,7 @@ bool replay_checkpoint(ReplayCheckpoint checkpoint)
     if (replay_mode == REPLAY_MODE_PLAY) {
         if (replay_next_event_is(EVENT_CHECKPOINT + checkpoint)) {
             replay_finish_event();
-        } else if (replay_data_kind != EVENT_ASYNC) {
+        } else if (replay_state.data_kind != EVENT_ASYNC) {
             res = false;
             goto out;
         }
@@ -197,7 +197,7 @@ bool replay_checkpoint(ReplayCheckpoint checkpoint)
         /* replay_read_events may leave some unread events.
            Return false if not all of the events associated with
            checkpoint were processed */
-        res = replay_data_kind != EVENT_ASYNC;
+        res = replay_state.data_kind != EVENT_ASYNC;
     } else if (replay_mode == REPLAY_MODE_RECORD) {
         replay_put_event(EVENT_CHECKPOINT + checkpoint);
         replay_save_events(checkpoint);
@@ -238,9 +238,10 @@ static void replay_enable(const char *fname, int mode)
     replay_filename = g_strdup(fname);
 
     replay_mode = mode;
-    replay_data_kind = -1;
+    replay_state.data_kind = -1;
     replay_state.instructions_count = 0;
     replay_state.current_step = 0;
+    replay_state.has_unread_data = 0;
 
     /* skip file header for RECORD and check it for PLAY */
     if (replay_mode == REPLAY_MODE_RECORD) {

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH v4 6/8] replay: vmstate for replay module
  2016-09-21 11:33 [Qemu-devel] [PATCH v4 0/8] replay additions Pavel Dovgalyuk
                   ` (4 preceding siblings ...)
  2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 5/8] replay: move internal data to the structure Pavel Dovgalyuk
@ 2016-09-21 11:33 ` Pavel Dovgalyuk
  2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 7/8] replay: allow replay stopping and restarting Pavel Dovgalyuk
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 22+ messages in thread
From: Pavel Dovgalyuk @ 2016-09-21 11:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jasowang, quintela, pbonzini, mst

This patch introduces vmstate for replay data structures.
It allows saving and loading vmstate while replaying.

Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
---
 replay/replay-internal.h |    9 +++++++++
 replay/replay-snapshot.c |   40 ++++++++++++++++++++++++++++++++++++++++
 replay/replay.c          |    1 +
 3 files changed, 50 insertions(+)

diff --git a/replay/replay-internal.h b/replay/replay-internal.h
index 3147d66..6040f4d 100644
--- a/replay/replay-internal.h
+++ b/replay/replay-internal.h
@@ -67,6 +67,8 @@ typedef struct ReplayState {
     unsigned int data_kind;
     /*! Flag which indicates that event is not processed yet. */
     unsigned int has_unread_data;
+    /*! Temporary variable for saving current log offset. */
+    uint64_t file_offset;
 } ReplayState;
 extern ReplayState replay_state;
 
@@ -167,4 +169,11 @@ void replay_event_net_save(void *opaque);
 /*! Reads network from the file. */
 void *replay_event_net_load(void);
 
+/* VMState-related functions */
+
+/* Registers replay VMState.
+   Should be called before virtual devices initialization
+   to make cached timers available for post_load functions. */
+void replay_vmstate_register(void);
+
 #endif
diff --git a/replay/replay-snapshot.c b/replay/replay-snapshot.c
index 970b893..eb3d70a 100644
--- a/replay/replay-snapshot.c
+++ b/replay/replay-snapshot.c
@@ -18,6 +18,46 @@
 #include "monitor/monitor.h"
 #include "qapi/qmp/qstring.h"
 #include "qemu/error-report.h"
+#include "migration/vmstate.h"
+
+static void replay_pre_save(void *opaque)
+{
+    ReplayState *state = opaque;
+    state->file_offset = ftello64(replay_file);
+}
+
+static int replay_post_load(void *opaque, int version_id)
+{
+    ReplayState *state = opaque;
+    fseeko64(replay_file, state->file_offset, SEEK_SET);
+    /* If this was a vmstate, saved in recording mode,
+       we need to initialize replay data fields. */
+    replay_fetch_data_kind();
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_replay = {
+    .name = "replay",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .pre_save = replay_pre_save,
+    .post_load = replay_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_INT64_ARRAY(cached_clock, ReplayState, REPLAY_CLOCK_COUNT),
+        VMSTATE_UINT64(current_step, ReplayState),
+        VMSTATE_INT32(instructions_count, ReplayState),
+        VMSTATE_UINT32(data_kind, ReplayState),
+        VMSTATE_UINT32(has_unread_data, ReplayState),
+        VMSTATE_UINT64(file_offset, ReplayState),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+void replay_vmstate_register(void)
+{
+    vmstate_register(NULL, 0, &vmstate_replay, &replay_state);
+}
 
 void replay_vmstate_init(void)
 {
diff --git a/replay/replay.c b/replay/replay.c
index 9472d4c..46e5729 100644
--- a/replay/replay.c
+++ b/replay/replay.c
@@ -295,6 +295,7 @@ void replay_configure(QemuOpts *opts)
 
     replay_snapshot = g_strdup(qemu_opt_get(opts, "rrsnapshot"));
 
+    replay_vmstate_register();
     replay_enable(fname, mode);
 
 out:

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH v4 7/8] replay: allow replay stopping and restarting
  2016-09-21 11:33 [Qemu-devel] [PATCH v4 0/8] replay additions Pavel Dovgalyuk
                   ` (5 preceding siblings ...)
  2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 6/8] replay: vmstate for replay module Pavel Dovgalyuk
@ 2016-09-21 11:33 ` Pavel Dovgalyuk
  2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 8/8] integratorcp: adding vmstate for save/restore Pavel Dovgalyuk
  2016-09-21 15:40 ` [Qemu-devel] [PATCH v4 0/8] replay additions Paolo Bonzini
  8 siblings, 0 replies; 22+ messages in thread
From: Pavel Dovgalyuk @ 2016-09-21 11:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jasowang, quintela, pbonzini, mst

This patch fixes bug with stopping and restarting replay
through monitor.

Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
---
 block/blkreplay.c        |   15 +++++----------
 cpus.c                   |    1 +
 include/sysemu/replay.h  |    4 ++++
 replay/replay-events.c   |    8 ++++++++
 replay/replay-internal.h |    6 ++++--
 replay/replay-snapshot.c |    1 +
 stubs/replay.c           |    5 +++++
 vl.c                     |    1 +
 8 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/block/blkreplay.c b/block/blkreplay.c
index ca18906..5a13fb3 100644
--- a/block/blkreplay.c
+++ b/block/blkreplay.c
@@ -20,11 +20,6 @@ typedef struct Request {
     QEMUBH *bh;
 } Request;
 
-/* Next request id.
-   This counter is global, because requests from different
-   block devices should not get overlapping ids. */
-static uint64_t request_id;
-
 static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags,
                           Error **errp)
 {
@@ -84,7 +79,7 @@ static void block_request_create(uint64_t reqid, BlockDriverState *bs,
 static int coroutine_fn blkreplay_co_preadv(BlockDriverState *bs,
     uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags)
 {
-    uint64_t reqid = request_id++;
+    uint64_t reqid = blkreplay_next_id();
     int ret = bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
     block_request_create(reqid, bs, qemu_coroutine_self());
     qemu_coroutine_yield();
@@ -95,7 +90,7 @@ static int coroutine_fn blkreplay_co_preadv(BlockDriverState *bs,
 static int coroutine_fn blkreplay_co_pwritev(BlockDriverState *bs,
     uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags)
 {
-    uint64_t reqid = request_id++;
+    uint64_t reqid = blkreplay_next_id();
     int ret = bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
     block_request_create(reqid, bs, qemu_coroutine_self());
     qemu_coroutine_yield();
@@ -106,7 +101,7 @@ static int coroutine_fn blkreplay_co_pwritev(BlockDriverState *bs,
 static int coroutine_fn blkreplay_co_pwrite_zeroes(BlockDriverState *bs,
     int64_t offset, int count, BdrvRequestFlags flags)
 {
-    uint64_t reqid = request_id++;
+    uint64_t reqid = blkreplay_next_id();
     int ret = bdrv_co_pwrite_zeroes(bs->file, offset, count, flags);
     block_request_create(reqid, bs, qemu_coroutine_self());
     qemu_coroutine_yield();
@@ -117,7 +112,7 @@ static int coroutine_fn blkreplay_co_pwrite_zeroes(BlockDriverState *bs,
 static int coroutine_fn blkreplay_co_pdiscard(BlockDriverState *bs,
                                               int64_t offset, int count)
 {
-    uint64_t reqid = request_id++;
+    uint64_t reqid = blkreplay_next_id();
     int ret = bdrv_co_pdiscard(bs->file->bs, offset, count);
     block_request_create(reqid, bs, qemu_coroutine_self());
     qemu_coroutine_yield();
@@ -127,7 +122,7 @@ static int coroutine_fn blkreplay_co_pdiscard(BlockDriverState *bs,
 
 static int coroutine_fn blkreplay_co_flush(BlockDriverState *bs)
 {
-    uint64_t reqid = request_id++;
+    uint64_t reqid = blkreplay_next_id();
     int ret = bdrv_co_flush(bs->file->bs);
     block_request_create(reqid, bs, qemu_coroutine_self());
     qemu_coroutine_yield();
diff --git a/cpus.c b/cpus.c
index e39ccb7..2f5684f 100644
--- a/cpus.c
+++ b/cpus.c
@@ -751,6 +751,7 @@ static int do_vm_stop(RunState state)
     }
 
     bdrv_drain_all();
+    replay_disable_events();
     ret = blk_flush_all();
 
     return ret;
diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h
index 95a35ee..740b425 100644
--- a/include/sysemu/replay.h
+++ b/include/sysemu/replay.h
@@ -110,6 +110,8 @@ bool replay_checkpoint(ReplayCheckpoint checkpoint);
 
 /*! Disables storing events in the queue */
 void replay_disable_events(void);
+/*! Enables storing events in the queue */
+void replay_enable_events(void);
 /*! Returns true when saving events is enabled */
 bool replay_events_enabled(void);
 /*! Adds bottom half event to the queue */
@@ -120,6 +122,8 @@ void replay_input_event(QemuConsole *src, InputEvent *evt);
 void replay_input_sync_event(void);
 /*! Adds block layer event to the queue */
 void replay_block_event(QEMUBH *bh, uint64_t id);
+/*! Returns ID for the next block event */
+uint64_t blkreplay_next_id(void);
 
 /* Character device */
 
diff --git a/replay/replay-events.c b/replay/replay-events.c
index 4ee2f5d..94a6dcc 100644
--- a/replay/replay-events.c
+++ b/replay/replay-events.c
@@ -320,3 +320,11 @@ bool replay_events_enabled(void)
 {
     return events_enabled;
 }
+
+uint64_t blkreplay_next_id(void)
+{
+    if (replay_events_enabled()) {
+        return replay_state.block_request_id++;
+    }
+    return 0;
+}
diff --git a/replay/replay-internal.h b/replay/replay-internal.h
index 6040f4d..c26d079 100644
--- a/replay/replay-internal.h
+++ b/replay/replay-internal.h
@@ -69,6 +69,10 @@ typedef struct ReplayState {
     unsigned int has_unread_data;
     /*! Temporary variable for saving current log offset. */
     uint64_t file_offset;
+    /*! Next block operation id.
+        This counter is global, because requests from different
+        block devices should not get overlapping ids. */
+    uint64_t block_request_id;
 } ReplayState;
 extern ReplayState replay_state;
 
@@ -124,8 +128,6 @@ void replay_read_next_clock(unsigned int kind);
 void replay_init_events(void);
 /*! Clears internal data structures for events handling */
 void replay_finish_events(void);
-/*! Enables storing events in the queue */
-void replay_enable_events(void);
 /*! Flushes events queue */
 void replay_flush_events(void);
 /*! Clears events list before loading new VM state */
diff --git a/replay/replay-snapshot.c b/replay/replay-snapshot.c
index eb3d70a..8007a8c 100644
--- a/replay/replay-snapshot.c
+++ b/replay/replay-snapshot.c
@@ -50,6 +50,7 @@ static const VMStateDescription vmstate_replay = {
         VMSTATE_UINT32(data_kind, ReplayState),
         VMSTATE_UINT32(has_unread_data, ReplayState),
         VMSTATE_UINT64(file_offset, ReplayState),
+        VMSTATE_UINT64(block_request_id, ReplayState),
         VMSTATE_END_OF_LIST()
     },
 };
diff --git a/stubs/replay.c b/stubs/replay.c
index de9fa1e..d9a6da9 100644
--- a/stubs/replay.c
+++ b/stubs/replay.c
@@ -67,3 +67,8 @@ void replay_char_read_all_save_buf(uint8_t *buf, int offset)
 void replay_block_event(QEMUBH *bh, uint64_t id)
 {
 }
+
+uint64_t blkreplay_next_id(void)
+{
+    return 0;
+}
diff --git a/vl.c b/vl.c
index c5ceb99..e1c90ef 100644
--- a/vl.c
+++ b/vl.c
@@ -749,6 +749,7 @@ void vm_start(void)
     if (runstate_is_running()) {
         qapi_event_send_stop(&error_abort);
     } else {
+        replay_enable_events();
         cpu_enable_ticks();
         runstate_set(RUN_STATE_RUNNING);
         vm_state_notify(1, RUN_STATE_RUNNING);

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH v4 8/8] integratorcp: adding vmstate for save/restore
  2016-09-21 11:33 [Qemu-devel] [PATCH v4 0/8] replay additions Pavel Dovgalyuk
                   ` (6 preceding siblings ...)
  2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 7/8] replay: allow replay stopping and restarting Pavel Dovgalyuk
@ 2016-09-21 11:33 ` Pavel Dovgalyuk
  2016-09-21 15:40 ` [Qemu-devel] [PATCH v4 0/8] replay additions Paolo Bonzini
  8 siblings, 0 replies; 22+ messages in thread
From: Pavel Dovgalyuk @ 2016-09-21 11:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jasowang, quintela, pbonzini, mst

From: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>

VMState added by this patch preserves correct
loading of the integratorcp device state.

Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
---
 hw/arm/integratorcp.c |   62 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
index 96dc150..3653df2 100644
--- a/hw/arm/integratorcp.c
+++ b/hw/arm/integratorcp.c
@@ -53,6 +53,27 @@ static uint8_t integrator_spd[128] = {
    0xe, 4, 0x1c, 1, 2, 0x20, 0xc0, 0, 0, 0, 0, 0x30, 0x28, 0x30, 0x28, 0x40
 };
 
+static const VMStateDescription vmstate_integratorcm = {
+    .name = "integratorcm",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(cm_osc, IntegratorCMState),
+        VMSTATE_UINT32(cm_ctrl, IntegratorCMState),
+        VMSTATE_UINT32(cm_lock, IntegratorCMState),
+        VMSTATE_UINT32(cm_auxosc, IntegratorCMState),
+        VMSTATE_UINT32(cm_sdram, IntegratorCMState),
+        VMSTATE_UINT32(cm_init, IntegratorCMState),
+        VMSTATE_UINT32(cm_flags, IntegratorCMState),
+        VMSTATE_UINT32(cm_nvflags, IntegratorCMState),
+        VMSTATE_UINT32(int_level, IntegratorCMState),
+        VMSTATE_UINT32(irq_enabled, IntegratorCMState),
+        VMSTATE_UINT32(fiq_enabled, IntegratorCMState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static uint64_t integratorcm_read(void *opaque, hwaddr offset,
                                   unsigned size)
 {
@@ -303,6 +324,19 @@ typedef struct icp_pic_state {
     qemu_irq parent_fiq;
 } icp_pic_state;
 
+static const VMStateDescription vmstate_icp_pic = {
+    .name = "icp_pic",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(level, icp_pic_state),
+        VMSTATE_UINT32(irq_enabled, icp_pic_state),
+        VMSTATE_UINT32(fiq_enabled, icp_pic_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static void icp_pic_update(icp_pic_state *s)
 {
     uint32_t flags;
@@ -432,6 +466,17 @@ typedef struct ICPCtrlRegsState {
 #define ICP_INTREG_WPROT        (1 << 0)
 #define ICP_INTREG_CARDIN       (1 << 3)
 
+static const VMStateDescription vmstate_icp_control = {
+    .name = "icp_control",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(intreg_state, ICPCtrlRegsState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static uint64_t icp_control_read(void *opaque, hwaddr offset,
                                  unsigned size)
 {
@@ -633,6 +678,21 @@ static void core_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->props = core_properties;
+    dc->vmsd = &vmstate_integratorcm;
+}
+
+static void icp_pic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->vmsd = &vmstate_icp_pic;
+}
+
+static void icp_control_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->vmsd = &vmstate_icp_control;
 }
 
 static const TypeInfo core_info = {
@@ -648,6 +708,7 @@ static const TypeInfo icp_pic_info = {
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(icp_pic_state),
     .instance_init = icp_pic_init,
+    .class_init    = icp_pic_class_init,
 };
 
 static const TypeInfo icp_ctrl_regs_info = {
@@ -655,6 +716,7 @@ static const TypeInfo icp_ctrl_regs_info = {
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(ICPCtrlRegsState),
     .instance_init = icp_control_init,
+    .class_init    = icp_control_class_init,
 };
 
 static void integratorcp_register_types(void)

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v4 3/8] block: don't make snapshots for filters
  2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 3/8] block: don't make snapshots for filters Pavel Dovgalyuk
@ 2016-09-21 15:37   ` Paolo Bonzini
  2016-09-22  5:43     ` Pavel Dovgalyuk
  0 siblings, 1 reply; 22+ messages in thread
From: Paolo Bonzini @ 2016-09-21 15:37 UTC (permalink / raw)
  To: Pavel Dovgalyuk, qemu-devel; +Cc: peter.maydell, jasowang, quintela, mst



On 21/09/2016 13:33, Pavel Dovgalyuk wrote:
> This patch disables snapshotting for block driver filters.
> It is needed, because snapshots should be created
> in underlying disk images, not in filters itself.

I don't understand this patch.  Who would take care of doing the
bdrv_snapshot_goto on the underlying image?

Paolo

> Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
> ---
>  block/snapshot.c |    3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/block/snapshot.c b/block/snapshot.c
> index bf5c2ca..8998b8b 100644
> --- a/block/snapshot.c
> +++ b/block/snapshot.c
> @@ -184,6 +184,9 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
>      if (!drv) {
>          return -ENOMEDIUM;
>      }
> +    if (drv->is_filter) {
> +        return 0;
> +    }
>      if (drv->bdrv_snapshot_goto) {
>          return drv->bdrv_snapshot_goto(bs, snapshot_id);
>      }
> 

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v4 2/8] replay: save/load initial state
  2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 2/8] replay: save/load initial state Pavel Dovgalyuk
@ 2016-09-21 15:39   ` Paolo Bonzini
  2016-09-21 15:49     ` Pavel Dovgalyuk
  0 siblings, 1 reply; 22+ messages in thread
From: Paolo Bonzini @ 2016-09-21 15:39 UTC (permalink / raw)
  To: Pavel Dovgalyuk, qemu-devel; +Cc: peter.maydell, jasowang, quintela, mst



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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v4 0/8] replay additions
  2016-09-21 11:33 [Qemu-devel] [PATCH v4 0/8] replay additions Pavel Dovgalyuk
                   ` (7 preceding siblings ...)
  2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 8/8] integratorcp: adding vmstate for save/restore Pavel Dovgalyuk
@ 2016-09-21 15:40 ` Paolo Bonzini
  2016-09-22  5:41   ` Pavel Dovgalyuk
  8 siblings, 1 reply; 22+ messages in thread
From: Paolo Bonzini @ 2016-09-21 15:40 UTC (permalink / raw)
  To: Pavel Dovgalyuk, qemu-devel; +Cc: peter.maydell, jasowang, quintela, mst



On 21/09/2016 13:33, Pavel Dovgalyuk wrote:
> This set of patches includes several fixes for replay and
> adds network record/replay for network devices. It also makes possible
> saving/restoring vmstate in replay mode.
> 
> Record and replay for network interactions is performed with the network filter.
> Each backend must have its own instance of the replay filter as follows:
>  -netdev user,id=net1 -device rtl8139,netdev=net1
>  -object filter-replay,id=replay,netdev=net1
> 
> This patches add rrsnapshot option for icount. rrshapshot option creates
> start snapshot at record and loads it at replay. It allows preserving
> the state of disk images used by virtual machine. This vm state can also
> use used to roll back the execution while replaying.
> 
> This set of patches includes fixes and additions for icount and
> record/replay implementation:
>  - VM start/stop in replay mode
>  - Network interaction record/replay
>  - overlay option for blkreplay filter
>  - rrsnapshot option for record/replay
>  - vmstate fix for integratorcp ARM platform
> 
> v4 changes:
>  - Overlay option is removed from blkreplay driver (as suggested by Paolo Bonzini)
>  - Minor changes
> 
> v3 changes:
>  - Added rrsnapshot option for specifying the initial snapshot name (as suggested by Paolo Bonzini)
>  - Minor changes

When you post v5, I suspect it's best if you move patches 5-7 first,
because those are the ones I'm going to merge myself.

Thanks!

Paolo

> ---
> 
> Pavel Dovgalyuk (8):
>       record/replay: add network support
>       replay: save/load initial state
>       block: don't make snapshots for filters
>       block: implement bdrv_recurse_is_first_non_filter for blkreplay
>       replay: move internal data to the structure
>       replay: vmstate for replay module
>       replay: allow replay stopping and restarting
>       integratorcp: adding vmstate for save/restore
> 
> 
>  block/blkreplay.c        |   24 ++++++----
>  block/snapshot.c         |    3 +
>  cpus.c                   |    1 
>  docs/replay.txt          |   30 ++++++++++++
>  hw/arm/integratorcp.c    |   62 ++++++++++++++++++++++++++
>  include/sysemu/replay.h  |   25 ++++++++++
>  net/Makefile.objs        |    1 
>  net/filter-replay.c      |   92 ++++++++++++++++++++++++++++++++++++++
>  qemu-options.hx          |    8 ++-
>  replay/Makefile.objs     |    2 +
>  replay/replay-events.c   |   21 ++++++++-
>  replay/replay-internal.c |   20 ++++----
>  replay/replay-internal.h |   33 ++++++++++++--
>  replay/replay-net.c      |  111 ++++++++++++++++++++++++++++++++++++++++++++++
>  replay/replay-snapshot.c |   78 ++++++++++++++++++++++++++++++++
>  replay/replay-time.c     |    2 -
>  replay/replay.c          |   24 +++++++---
>  stubs/replay.c           |    5 ++
>  vl.c                     |   14 +++++-
>  19 files changed, 515 insertions(+), 41 deletions(-)
>  create mode 100644 net/filter-replay.c
>  create mode 100644 replay/replay-net.c
>  create mode 100644 replay/replay-snapshot.c
> 

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v4 2/8] replay: save/load initial state
  2016-09-21 15:39   ` Paolo Bonzini
@ 2016-09-21 15:49     ` Pavel Dovgalyuk
  2016-09-21 15:57       ` Paolo Bonzini
  0 siblings, 1 reply; 22+ messages in thread
From: Pavel Dovgalyuk @ 2016-09-21 15:49 UTC (permalink / raw)
  To: 'Paolo Bonzini', 'Pavel Dovgalyuk', qemu-devel
  Cc: peter.maydell, jasowang, quintela, mst

> 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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v4 2/8] replay: save/load initial state
  2016-09-21 15:49     ` Pavel Dovgalyuk
@ 2016-09-21 15:57       ` Paolo Bonzini
  2016-09-22  5:37         ` Pavel Dovgalyuk
  0 siblings, 1 reply; 22+ messages in thread
From: Paolo Bonzini @ 2016-09-21 15:57 UTC (permalink / raw)
  To: Pavel Dovgalyuk, 'Pavel Dovgalyuk', qemu-devel
  Cc: peter.maydell, jasowang, quintela, mst



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
> 

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v4 2/8] replay: save/load initial state
  2016-09-21 15:57       ` Paolo Bonzini
@ 2016-09-22  5:37         ` Pavel Dovgalyuk
  2016-09-22  8:51           ` Paolo Bonzini
  0 siblings, 1 reply; 22+ messages in thread
From: Pavel Dovgalyuk @ 2016-09-22  5:37 UTC (permalink / raw)
  To: 'Paolo Bonzini', 'Pavel Dovgalyuk', qemu-devel
  Cc: peter.maydell, jasowang, quintela, mst

> 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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v4 0/8] replay additions
  2016-09-21 15:40 ` [Qemu-devel] [PATCH v4 0/8] replay additions Paolo Bonzini
@ 2016-09-22  5:41   ` Pavel Dovgalyuk
  2016-09-22  8:51     ` Paolo Bonzini
  0 siblings, 1 reply; 22+ messages in thread
From: Pavel Dovgalyuk @ 2016-09-22  5:41 UTC (permalink / raw)
  To: 'Paolo Bonzini', 'Pavel Dovgalyuk', qemu-devel
  Cc: peter.maydell, jasowang, quintela, mst

> From: Paolo Bonzini [mailto:pbonzini@redhat.com]
> On 21/09/2016 13:33, Pavel Dovgalyuk wrote:
> > This set of patches includes several fixes for replay and
> > adds network record/replay for network devices. It also makes possible
> > saving/restoring vmstate in replay mode.
> >
> > Record and replay for network interactions is performed with the network filter.
> > Each backend must have its own instance of the replay filter as follows:
> >  -netdev user,id=net1 -device rtl8139,netdev=net1
> >  -object filter-replay,id=replay,netdev=net1
> >
> > This patches add rrsnapshot option for icount. rrshapshot option creates
> > start snapshot at record and loads it at replay. It allows preserving
> > the state of disk images used by virtual machine. This vm state can also
> > use used to roll back the execution while replaying.
> >
> > This set of patches includes fixes and additions for icount and
> > record/replay implementation:
> >  - VM start/stop in replay mode
> >  - Network interaction record/replay
> >  - overlay option for blkreplay filter
> >  - rrsnapshot option for record/replay
> >  - vmstate fix for integratorcp ARM platform
> >
> > v4 changes:
> >  - Overlay option is removed from blkreplay driver (as suggested by Paolo Bonzini)
> >  - Minor changes
> >
> > v3 changes:
> >  - Added rrsnapshot option for specifying the initial snapshot name (as suggested by Paolo
> Bonzini)
> >  - Minor changes
> 
> When you post v5, I suspect it's best if you move patches 5-7 first,
> because those are the ones I'm going to merge myself.

And what about network support (patch 1)?
Nobody has commented it in any of the iterations.

Pavel Dovgalyuk

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v4 3/8] block: don't make snapshots for filters
  2016-09-21 15:37   ` Paolo Bonzini
@ 2016-09-22  5:43     ` Pavel Dovgalyuk
  0 siblings, 0 replies; 22+ messages in thread
From: Pavel Dovgalyuk @ 2016-09-22  5:43 UTC (permalink / raw)
  To: 'Paolo Bonzini', 'Pavel Dovgalyuk', qemu-devel
  Cc: peter.maydell, jasowang, quintela, mst



> -----Original Message-----
> From: Paolo Bonzini [mailto:pbonzini@redhat.com]
> Sent: Wednesday, September 21, 2016 6:37 PM
> To: Pavel Dovgalyuk; qemu-devel@nongnu.org
> Cc: peter.maydell@linaro.org; jasowang@redhat.com; quintela@redhat.com; mst@redhat.com
> Subject: Re: [PATCH v4 3/8] block: don't make snapshots for filters
> 
> 
> 
> On 21/09/2016 13:33, Pavel Dovgalyuk wrote:
> > This patch disables snapshotting for block driver filters.
> > It is needed, because snapshots should be created
> > in underlying disk images, not in filters itself.
> 
> I don't understand this patch.  Who would take care of doing the
> bdrv_snapshot_goto on the underlying image?

loadvm needs to make bdrv_snapshot_goto. It discovers top-level replay driver and
tries to perform bdrv_snapshot_goto for it.

Patches 3 and 4 fix that. They allow passing through the replay driver and
make saving/restoring of the actual image.

Pavel Dovgalyuk

> 
> > Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
> > ---
> >  block/snapshot.c |    3 +++
> >  1 file changed, 3 insertions(+)
> >
> > diff --git a/block/snapshot.c b/block/snapshot.c
> > index bf5c2ca..8998b8b 100644
> > --- a/block/snapshot.c
> > +++ b/block/snapshot.c
> > @@ -184,6 +184,9 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
> >      if (!drv) {
> >          return -ENOMEDIUM;
> >      }
> > +    if (drv->is_filter) {
> > +        return 0;
> > +    }
> >      if (drv->bdrv_snapshot_goto) {
> >          return drv->bdrv_snapshot_goto(bs, snapshot_id);
> >      }
> >

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v4 2/8] replay: save/load initial state
  2016-09-22  5:37         ` Pavel Dovgalyuk
@ 2016-09-22  8:51           ` Paolo Bonzini
  0 siblings, 0 replies; 22+ messages in thread
From: Paolo Bonzini @ 2016-09-22  8:51 UTC (permalink / raw)
  To: Pavel Dovgalyuk, 'Pavel Dovgalyuk', qemu-devel
  Cc: peter.maydell, jasowang, quintela, mst



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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v4 0/8] replay additions
  2016-09-22  5:41   ` Pavel Dovgalyuk
@ 2016-09-22  8:51     ` Paolo Bonzini
  0 siblings, 0 replies; 22+ messages in thread
From: Paolo Bonzini @ 2016-09-22  8:51 UTC (permalink / raw)
  To: Pavel Dovgalyuk, 'Pavel Dovgalyuk', qemu-devel
  Cc: peter.maydell, jasowang, quintela, mst



On 22/09/2016 07:41, Pavel Dovgalyuk wrote:
>> From: Paolo Bonzini [mailto:pbonzini@redhat.com]
>> On 21/09/2016 13:33, Pavel Dovgalyuk wrote:
>>> This set of patches includes several fixes for replay and
>>> adds network record/replay for network devices. It also makes possible
>>> saving/restoring vmstate in replay mode.
>>>
>>> Record and replay for network interactions is performed with the network filter.
>>> Each backend must have its own instance of the replay filter as follows:
>>>  -netdev user,id=net1 -device rtl8139,netdev=net1
>>>  -object filter-replay,id=replay,netdev=net1
>>>
>>> This patches add rrsnapshot option for icount. rrshapshot option creates
>>> start snapshot at record and loads it at replay. It allows preserving
>>> the state of disk images used by virtual machine. This vm state can also
>>> use used to roll back the execution while replaying.
>>>
>>> This set of patches includes fixes and additions for icount and
>>> record/replay implementation:
>>>  - VM start/stop in replay mode
>>>  - Network interaction record/replay
>>>  - overlay option for blkreplay filter
>>>  - rrsnapshot option for record/replay
>>>  - vmstate fix for integratorcp ARM platform
>>>
>>> v4 changes:
>>>  - Overlay option is removed from blkreplay driver (as suggested by Paolo Bonzini)
>>>  - Minor changes
>>>
>>> v3 changes:
>>>  - Added rrsnapshot option for specifying the initial snapshot name (as suggested by Paolo
>> Bonzini)
>>>  - Minor changes
>>
>> When you post v5, I suspect it's best if you move patches 5-7 first,
>> because those are the ones I'm going to merge myself.
> 
> And what about network support (patch 1)?

It's not my area and I hardly know anything about net/; Jason Wang would
merge it.

Paolo

> Nobody has commented it in any of the iterations.
> 
> Pavel Dovgalyuk
> 

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v4 1/8] record/replay: add network support
  2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 1/8] record/replay: add network support Pavel Dovgalyuk
@ 2016-09-23  6:06   ` Jason Wang
  2016-09-23  7:52     ` Pavel Dovgalyuk
  2016-10-13  8:01     ` Pavel Dovgalyuk
  0 siblings, 2 replies; 22+ messages in thread
From: Jason Wang @ 2016-09-23  6:06 UTC (permalink / raw)
  To: Pavel Dovgalyuk, qemu-devel; +Cc: peter.maydell, quintela, pbonzini, mst



On 2016年09月21日 19:33, Pavel Dovgalyuk wrote:
> This patch adds support of recording and replaying network packets in
> irount rr mode.
>
> Record and replay for network interactions is performed with the network filter.
> Each backend must have its own instance of the replay filter as follows:
>   -netdev user,id=net1 -device rtl8139,netdev=net1
>   -object filter-replay,id=replay,netdev=net1
>
> Replay network filter is used to record and replay network packets. While
> recording the virtual machine this filter puts all packets coming from
> the outer world into the log. In replay mode packets from the log are
> injected into the network device. All interactions with network backend
> in replay mode are disabled.
>
> Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>

Looks good, just few nits, see below.

Thanks

> ---
>   docs/replay.txt          |   14 ++++++
>   include/sysemu/replay.h  |   12 +++++
>   net/Makefile.objs        |    1
>   net/filter-replay.c      |   92 ++++++++++++++++++++++++++++++++++++++
>   replay/Makefile.objs     |    1
>   replay/replay-events.c   |   11 +++++
>   replay/replay-internal.h |   10 ++++
>   replay/replay-net.c      |  111 ++++++++++++++++++++++++++++++++++++++++++++++
>   replay/replay.c          |    2 -
>   vl.c                     |    3 +
>   10 files changed, 255 insertions(+), 2 deletions(-)
>   create mode 100644 net/filter-replay.c
>   create mode 100644 replay/replay-net.c
>
> diff --git a/docs/replay.txt b/docs/replay.txt
> index 779c6c0..347b2ff 100644
> --- a/docs/replay.txt
> +++ b/docs/replay.txt
> @@ -195,3 +195,17 @@ Queue is flushed at checkpoints and information about processed requests
>   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.
> +
> +Network devices
> +---------------
> +
> +Record and replay for network interactions is performed with the network filter.
> +Each backend must have its own instance of the replay filter as follows:
> + -netdev user,id=net1 -device rtl8139,netdev=net1
> + -object filter-replay,id=replay,netdev=net1
> +
> +Replay network filter is used to record and replay network packets. While
> +recording the virtual machine this filter puts all packets coming from
> +the outer world into the log. In replay mode packets from the log are
> +injected into the network device. All interactions with network backend
> +in replay mode are disabled.
> diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h
> index 0a88393..a408633 100644
> --- a/include/sysemu/replay.h
> +++ b/include/sysemu/replay.h
> @@ -39,6 +39,8 @@ enum ReplayCheckpoint {
>   };
>   typedef enum ReplayCheckpoint ReplayCheckpoint;
>   
> +typedef struct ReplayNetState ReplayNetState;
> +
>   extern ReplayMode replay_mode;
>   
>   /* Replay process control functions */
> @@ -133,4 +135,14 @@ void replay_char_read_all_save_error(int res);
>   /*! Writes character read_all execution result into the replay log. */
>   void replay_char_read_all_save_buf(uint8_t *buf, int offset);
>   
> +/* Network */
> +
> +/*! Registers replay network filter attached to some backend. */
> +ReplayNetState *replay_register_net(NetFilterState *nfs);
> +/*! Unregisters replay network filter. */
> +void replay_unregister_net(ReplayNetState *rns);
> +/*! Called to write network packet to the replay log. */
> +void replay_net_packet_event(ReplayNetState *rns, unsigned flags,
> +                             const struct iovec *iov, int iovcnt);
> +
>   #endif
> diff --git a/net/Makefile.objs b/net/Makefile.objs
> index b7c22fd..f787ba4 100644
> --- a/net/Makefile.objs
> +++ b/net/Makefile.objs
> @@ -16,3 +16,4 @@ common-obj-$(CONFIG_NETMAP) += netmap.o
>   common-obj-y += filter.o
>   common-obj-y += filter-buffer.o
>   common-obj-y += filter-mirror.o
> +common-obj-y += filter-replay.o
> diff --git a/net/filter-replay.c b/net/filter-replay.c
> new file mode 100644
> index 0000000..cff65f8
> --- /dev/null
> +++ b/net/filter-replay.c
> @@ -0,0 +1,92 @@
> +/*
> + * filter-replay.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 "clients.h"
> +#include "qapi/error.h"
> +#include "qemu-common.h"
> +#include "qemu/error-report.h"
> +#include "qemu/iov.h"
> +#include "qemu/log.h"
> +#include "qemu/timer.h"
> +#include "qapi/visitor.h"
> +#include "net/filter.h"
> +#include "sysemu/replay.h"
> +
> +#define TYPE_FILTER_REPLAY "filter-replay"
> +
> +#define FILTER_REPLAY(obj) \
> +    OBJECT_CHECK(NetFilterReplayState, (obj), TYPE_FILTER_REPLAY)
> +
> +struct NetFilterReplayState {
> +    NetFilterState nfs;
> +    ReplayNetState *rns;
> +};
> +typedef struct NetFilterReplayState NetFilterReplayState;
> +
> +static ssize_t filter_replay_receive_iov(NetFilterState *nf,
> +                                         NetClientState *sndr,
> +                                         unsigned flags,
> +                                         const struct iovec *iov,
> +                                         int iovcnt, NetPacketSent *sent_cb)
> +{
> +    NetFilterReplayState *nfrs = FILTER_REPLAY(nf);
> +    switch (replay_mode) {
> +    case REPLAY_MODE_RECORD:
> +        if (nf->netdev == sndr) {
> +            replay_net_packet_event(nfrs->rns, flags, iov, iovcnt);
> +            return iov_size(iov, iovcnt);
> +        }
> +        return 0;
> +    case REPLAY_MODE_PLAY:
> +        /* Drop all packets in replay mode.
> +           Packets from the log will be injected by the replay module. */
> +        return iov_size(iov, iovcnt);
> +    default:
> +        /* Pass all the packets. */
> +        return 0;
> +    }
> +}
> +
> +static void filter_replay_instance_init(Object *obj)
> +{
> +    NetFilterReplayState *nfrs = FILTER_REPLAY(obj);
> +    nfrs->rns = replay_register_net(&nfrs->nfs);
> +}
> +
> +static void filter_replay_instance_finalize(Object *obj)
> +{
> +    NetFilterReplayState *nfrs = FILTER_REPLAY(obj);
> +    replay_unregister_net(nfrs->rns);
> +}
> +
> +static void filter_replay_class_init(ObjectClass *oc, void *data)
> +{
> +    NetFilterClass *nfc = NETFILTER_CLASS(oc);
> +
> +    nfc->receive_iov = filter_replay_receive_iov;
> +}
> +
> +static const TypeInfo filter_replay_info = {
> +    .name = TYPE_FILTER_REPLAY,
> +    .parent = TYPE_NETFILTER,
> +    .class_init = filter_replay_class_init,
> +    .instance_init = filter_replay_instance_init,
> +    .instance_finalize = filter_replay_instance_finalize,
> +    .instance_size = sizeof(NetFilterReplayState),
> +};
> +
> +static void filter_replay_register_types(void)
> +{
> +    type_register_static(&filter_replay_info);
> +}
> +
> +type_init(filter_replay_register_types);
> diff --git a/replay/Makefile.objs b/replay/Makefile.objs
> index fcb3f74..f55a6b5 100644
> --- a/replay/Makefile.objs
> +++ b/replay/Makefile.objs
> @@ -4,3 +4,4 @@ common-obj-y += replay-events.o
>   common-obj-y += replay-time.o
>   common-obj-y += replay-input.o
>   common-obj-y += replay-char.o
> +common-obj-y += replay-net.o
> diff --git a/replay/replay-events.c b/replay/replay-events.c
> index 3807245..9ce9e51 100644
> --- a/replay/replay-events.c
> +++ b/replay/replay-events.c
> @@ -54,6 +54,9 @@ static void replay_run_event(Event *event)
>       case REPLAY_ASYNC_EVENT_BLOCK:
>           aio_bh_call(event->opaque);
>           break;
> +    case REPLAY_ASYNC_EVENT_NET:
> +        replay_event_net_run(event->opaque);
> +        break;
>       default:
>           error_report("Replay: invalid async event ID (%d) in the queue",
>                       event->event_kind);
> @@ -189,6 +192,9 @@ static void replay_save_event(Event *event, int checkpoint)
>           case REPLAY_ASYNC_EVENT_BLOCK:
>               replay_put_qword(event->id);
>               break;
> +        case REPLAY_ASYNC_EVENT_NET:
> +            replay_event_net_save(event->opaque);
> +            break;
>           default:
>               error_report("Unknown ID %" PRId64 " of replay event", event->id);
>               exit(1);
> @@ -252,6 +258,11 @@ static Event *replay_read_event(int checkpoint)
>               read_id = replay_get_qword();
>           }
>           break;
> +    case REPLAY_ASYNC_EVENT_NET:
> +        event = g_malloc0(sizeof(Event));
> +        event->event_kind = read_event_kind;
> +        event->opaque = replay_event_net_load();
> +        return event;
>       default:
>           error_report("Unknown ID %d of replay event", read_event_kind);
>           exit(1);
> diff --git a/replay/replay-internal.h b/replay/replay-internal.h
> index efbf14c..d28cfb7 100644
> --- a/replay/replay-internal.h
> +++ b/replay/replay-internal.h
> @@ -50,6 +50,7 @@ enum ReplayAsyncEventKind {
>       REPLAY_ASYNC_EVENT_INPUT_SYNC,
>       REPLAY_ASYNC_EVENT_CHAR_READ,
>       REPLAY_ASYNC_EVENT_BLOCK,
> +    REPLAY_ASYNC_EVENT_NET,
>       REPLAY_ASYNC_COUNT
>   };
>   
> @@ -155,4 +156,13 @@ void replay_event_char_read_save(void *opaque);
>   /*! Reads char event read from the file. */
>   void *replay_event_char_read_load(void);
>   
> +/* Network devices */
> +
> +/*! Called to run network event. */
> +void replay_event_net_run(void *opaque);
> +/*! Writes network event to the file. */
> +void replay_event_net_save(void *opaque);
> +/*! Reads network from the file. */
> +void *replay_event_net_load(void);
> +
>   #endif
> diff --git a/replay/replay-net.c b/replay/replay-net.c
> new file mode 100644
> index 0000000..4f7b995
> --- /dev/null
> +++ b/replay/replay-net.c
> @@ -0,0 +1,111 @@
> +/*
> + * replay-net.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 "qemu/error-report.h"
> +#include "sysemu/replay.h"
> +#include "replay-internal.h"
> +#include "sysemu/sysemu.h"
> +#include "net/net.h"
> +#include "net/filter.h"
> +#include "qemu/iov.h"
> +
> +struct ReplayNetState {
> +    NetFilterState *nfs;
> +    int id;
> +};
> +
> +typedef struct NetEvent {
> +    uint8_t id;
> +    uint32_t flags;
> +    uint8_t *data;
> +    size_t size;
> +} NetEvent;
> +
> +static NetFilterState **network_filters;
> +static int network_filters_count;
> +
> +ReplayNetState *replay_register_net(NetFilterState *nfs)
> +{
> +    ReplayNetState *rns = g_new0(ReplayNetState, 1);
> +    rns->nfs = nfs;
> +    rns->id = network_filters_count++;
> +    network_filters = g_realloc(network_filters,
> +                                network_filters_count
> +                                    * sizeof(*network_filters));

Any chance to avoid maintaining such array? E.g by having a pointer to 
NetFilterState in each NetEvent?

> +    network_filters[network_filters_count - 1] = nfs;
> +    return rns;
> +}
> +
> +void replay_unregister_net(ReplayNetState *rns)
> +{
> +    network_filters[rns->id] = NULL;
> +    g_free(rns);
> +}
> +
> +void replay_net_packet_event(ReplayNetState *rns, unsigned flags,
> +                             const struct iovec *iov, int iovcnt)
> +{
> +    NetEvent *event;
> +    int i;
> +
> +    event = g_new(NetEvent, 1);
> +    event->flags = flags;
> +    event->data = g_malloc(iov_size(iov, iovcnt));
> +    event->size = 0;
> +    event->id = rns->id;
> +
> +    for (i = 0; i < iovcnt; i++) {
> +        size_t len = iov[i].iov_len;
> +
> +        memcpy(event->data + event->size, iov[i].iov_base, len);
> +        event->size += len;
> +    }

You can use iov_to_buf() instead.

> +
> +    replay_add_event(REPLAY_ASYNC_EVENT_NET, event, NULL, 0);
> +}
> +
> +void replay_event_net_run(void *opaque)
> +{
> +    NetEvent *event = opaque;
> +    struct iovec iov = {
> +        .iov_base = (void *)event->data,
> +        .iov_len = event->size
> +    };
> +
> +    assert(event->id < network_filters_count);
> +
> +    qemu_netfilter_pass_to_next(network_filters[event->id]->netdev,
> +        event->flags, &iov, 1, network_filters[event->id]);
> +
> +    g_free(event->data);
> +    g_free(event);
> +}
> +
> +void replay_event_net_save(void *opaque)
> +{
> +    NetEvent *event = opaque;
> +
> +    replay_put_byte(event->id);
> +    replay_put_dword(event->flags);
> +    replay_put_array(event->data, event->size);
> +}
> +
> +void *replay_event_net_load(void)
> +{
> +    NetEvent *event = g_new(NetEvent, 1);
> +
> +    event->id = replay_get_byte();
> +    event->flags = replay_get_dword();
> +    replay_get_array_alloc(&event->data, &event->size);
> +
> +    return event;
> +}
> diff --git a/replay/replay.c b/replay/replay.c
> index 167fd29..e040f6f 100644
> --- a/replay/replay.c
> +++ b/replay/replay.c
> @@ -21,7 +21,7 @@
>   
>   /* Current version of the replay mechanism.
>      Increase it when file format changes. */
> -#define REPLAY_VERSION              0xe02004
> +#define REPLAY_VERSION              0xe02005
>   /* Size of replay log header */
>   #define HEADER_SIZE                 (sizeof(uint32_t) + sizeof(uint64_t))
>   
> diff --git a/vl.c b/vl.c
> index fca0487..fd7f17e 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -2807,7 +2807,8 @@ static bool object_create_initial(const char *type)
>       if (g_str_equal(type, "filter-buffer") ||
>           g_str_equal(type, "filter-dump") ||
>           g_str_equal(type, "filter-mirror") ||
> -        g_str_equal(type, "filter-redirector")) {
> +        g_str_equal(type, "filter-redirector") ||
> +        g_str_equal(type, "filter-replay")) {
>           return false;
>       }
>   
>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v4 1/8] record/replay: add network support
  2016-09-23  6:06   ` Jason Wang
@ 2016-09-23  7:52     ` Pavel Dovgalyuk
  2016-10-13  8:01     ` Pavel Dovgalyuk
  1 sibling, 0 replies; 22+ messages in thread
From: Pavel Dovgalyuk @ 2016-09-23  7:52 UTC (permalink / raw)
  To: 'Jason Wang', 'Pavel Dovgalyuk', qemu-devel
  Cc: peter.maydell, quintela, pbonzini, mst

> From: Jason Wang [mailto:jasowang@redhat.com]
> On 2016年09月21日 19:33, Pavel Dovgalyuk wrote:
> > This patch adds support of recording and replaying network packets in
> > irount rr mode.
> >
> > Record and replay for network interactions is performed with the network filter.
> > Each backend must have its own instance of the replay filter as follows:
> >   -netdev user,id=net1 -device rtl8139,netdev=net1
> >   -object filter-replay,id=replay,netdev=net1
> >
> > Replay network filter is used to record and replay network packets. While
> > recording the virtual machine this filter puts all packets coming from
> > the outer world into the log. In replay mode packets from the log are
> > injected into the network device. All interactions with network backend
> > in replay mode are disabled.
> >
> > Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
> 
> Looks good, just few nits, see below.
> 
> Thanks
> 
> > ---
> >   docs/replay.txt          |   14 ++++++
> >   include/sysemu/replay.h  |   12 +++++
> >   net/Makefile.objs        |    1
> >   net/filter-replay.c      |   92 ++++++++++++++++++++++++++++++++++++++
> >   replay/Makefile.objs     |    1
> >   replay/replay-events.c   |   11 +++++
> >   replay/replay-internal.h |   10 ++++
> >   replay/replay-net.c      |  111 ++++++++++++++++++++++++++++++++++++++++++++++
> >   replay/replay.c          |    2 -
> >   vl.c                     |    3 +
> >   10 files changed, 255 insertions(+), 2 deletions(-)
> >   create mode 100644 net/filter-replay.c
> >   create mode 100644 replay/replay-net.c
> >
> > diff --git a/docs/replay.txt b/docs/replay.txt
> > index 779c6c0..347b2ff 100644
> > --- a/docs/replay.txt
> > +++ b/docs/replay.txt
> > @@ -195,3 +195,17 @@ Queue is flushed at checkpoints and information about processed
> requests
> >   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.
> > +
> > +Network devices
> > +---------------
> > +
> > +Record and replay for network interactions is performed with the network filter.
> > +Each backend must have its own instance of the replay filter as follows:
> > + -netdev user,id=net1 -device rtl8139,netdev=net1
> > + -object filter-replay,id=replay,netdev=net1
> > +
> > +Replay network filter is used to record and replay network packets. While
> > +recording the virtual machine this filter puts all packets coming from
> > +the outer world into the log. In replay mode packets from the log are
> > +injected into the network device. All interactions with network backend
> > +in replay mode are disabled.
> > diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h
> > index 0a88393..a408633 100644
> > --- a/include/sysemu/replay.h
> > +++ b/include/sysemu/replay.h
> > @@ -39,6 +39,8 @@ enum ReplayCheckpoint {
> >   };
> >   typedef enum ReplayCheckpoint ReplayCheckpoint;
> >
> > +typedef struct ReplayNetState ReplayNetState;
> > +
> >   extern ReplayMode replay_mode;
> >
> >   /* Replay process control functions */
> > @@ -133,4 +135,14 @@ void replay_char_read_all_save_error(int res);
> >   /*! Writes character read_all execution result into the replay log. */
> >   void replay_char_read_all_save_buf(uint8_t *buf, int offset);
> >
> > +/* Network */
> > +
> > +/*! Registers replay network filter attached to some backend. */
> > +ReplayNetState *replay_register_net(NetFilterState *nfs);
> > +/*! Unregisters replay network filter. */
> > +void replay_unregister_net(ReplayNetState *rns);
> > +/*! Called to write network packet to the replay log. */
> > +void replay_net_packet_event(ReplayNetState *rns, unsigned flags,
> > +                             const struct iovec *iov, int iovcnt);
> > +
> >   #endif
> > diff --git a/net/Makefile.objs b/net/Makefile.objs
> > index b7c22fd..f787ba4 100644
> > --- a/net/Makefile.objs
> > +++ b/net/Makefile.objs
> > @@ -16,3 +16,4 @@ common-obj-$(CONFIG_NETMAP) += netmap.o
> >   common-obj-y += filter.o
> >   common-obj-y += filter-buffer.o
> >   common-obj-y += filter-mirror.o
> > +common-obj-y += filter-replay.o
> > diff --git a/net/filter-replay.c b/net/filter-replay.c
> > new file mode 100644
> > index 0000000..cff65f8
> > --- /dev/null
> > +++ b/net/filter-replay.c
> > @@ -0,0 +1,92 @@
> > +/*
> > + * filter-replay.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 "clients.h"
> > +#include "qapi/error.h"
> > +#include "qemu-common.h"
> > +#include "qemu/error-report.h"
> > +#include "qemu/iov.h"
> > +#include "qemu/log.h"
> > +#include "qemu/timer.h"
> > +#include "qapi/visitor.h"
> > +#include "net/filter.h"
> > +#include "sysemu/replay.h"
> > +
> > +#define TYPE_FILTER_REPLAY "filter-replay"
> > +
> > +#define FILTER_REPLAY(obj) \
> > +    OBJECT_CHECK(NetFilterReplayState, (obj), TYPE_FILTER_REPLAY)
> > +
> > +struct NetFilterReplayState {
> > +    NetFilterState nfs;
> > +    ReplayNetState *rns;
> > +};
> > +typedef struct NetFilterReplayState NetFilterReplayState;
> > +
> > +static ssize_t filter_replay_receive_iov(NetFilterState *nf,
> > +                                         NetClientState *sndr,
> > +                                         unsigned flags,
> > +                                         const struct iovec *iov,
> > +                                         int iovcnt, NetPacketSent *sent_cb)
> > +{
> > +    NetFilterReplayState *nfrs = FILTER_REPLAY(nf);
> > +    switch (replay_mode) {
> > +    case REPLAY_MODE_RECORD:
> > +        if (nf->netdev == sndr) {
> > +            replay_net_packet_event(nfrs->rns, flags, iov, iovcnt);
> > +            return iov_size(iov, iovcnt);
> > +        }
> > +        return 0;
> > +    case REPLAY_MODE_PLAY:
> > +        /* Drop all packets in replay mode.
> > +           Packets from the log will be injected by the replay module. */
> > +        return iov_size(iov, iovcnt);
> > +    default:
> > +        /* Pass all the packets. */
> > +        return 0;
> > +    }
> > +}
> > +
> > +static void filter_replay_instance_init(Object *obj)
> > +{
> > +    NetFilterReplayState *nfrs = FILTER_REPLAY(obj);
> > +    nfrs->rns = replay_register_net(&nfrs->nfs);
> > +}
> > +
> > +static void filter_replay_instance_finalize(Object *obj)
> > +{
> > +    NetFilterReplayState *nfrs = FILTER_REPLAY(obj);
> > +    replay_unregister_net(nfrs->rns);
> > +}
> > +
> > +static void filter_replay_class_init(ObjectClass *oc, void *data)
> > +{
> > +    NetFilterClass *nfc = NETFILTER_CLASS(oc);
> > +
> > +    nfc->receive_iov = filter_replay_receive_iov;
> > +}
> > +
> > +static const TypeInfo filter_replay_info = {
> > +    .name = TYPE_FILTER_REPLAY,
> > +    .parent = TYPE_NETFILTER,
> > +    .class_init = filter_replay_class_init,
> > +    .instance_init = filter_replay_instance_init,
> > +    .instance_finalize = filter_replay_instance_finalize,
> > +    .instance_size = sizeof(NetFilterReplayState),
> > +};
> > +
> > +static void filter_replay_register_types(void)
> > +{
> > +    type_register_static(&filter_replay_info);
> > +}
> > +
> > +type_init(filter_replay_register_types);
> > diff --git a/replay/Makefile.objs b/replay/Makefile.objs
> > index fcb3f74..f55a6b5 100644
> > --- a/replay/Makefile.objs
> > +++ b/replay/Makefile.objs
> > @@ -4,3 +4,4 @@ common-obj-y += replay-events.o
> >   common-obj-y += replay-time.o
> >   common-obj-y += replay-input.o
> >   common-obj-y += replay-char.o
> > +common-obj-y += replay-net.o
> > diff --git a/replay/replay-events.c b/replay/replay-events.c
> > index 3807245..9ce9e51 100644
> > --- a/replay/replay-events.c
> > +++ b/replay/replay-events.c
> > @@ -54,6 +54,9 @@ static void replay_run_event(Event *event)
> >       case REPLAY_ASYNC_EVENT_BLOCK:
> >           aio_bh_call(event->opaque);
> >           break;
> > +    case REPLAY_ASYNC_EVENT_NET:
> > +        replay_event_net_run(event->opaque);
> > +        break;
> >       default:
> >           error_report("Replay: invalid async event ID (%d) in the queue",
> >                       event->event_kind);
> > @@ -189,6 +192,9 @@ static void replay_save_event(Event *event, int checkpoint)
> >           case REPLAY_ASYNC_EVENT_BLOCK:
> >               replay_put_qword(event->id);
> >               break;
> > +        case REPLAY_ASYNC_EVENT_NET:
> > +            replay_event_net_save(event->opaque);
> > +            break;
> >           default:
> >               error_report("Unknown ID %" PRId64 " of replay event", event->id);
> >               exit(1);
> > @@ -252,6 +258,11 @@ static Event *replay_read_event(int checkpoint)
> >               read_id = replay_get_qword();
> >           }
> >           break;
> > +    case REPLAY_ASYNC_EVENT_NET:
> > +        event = g_malloc0(sizeof(Event));
> > +        event->event_kind = read_event_kind;
> > +        event->opaque = replay_event_net_load();
> > +        return event;
> >       default:
> >           error_report("Unknown ID %d of replay event", read_event_kind);
> >           exit(1);
> > diff --git a/replay/replay-internal.h b/replay/replay-internal.h
> > index efbf14c..d28cfb7 100644
> > --- a/replay/replay-internal.h
> > +++ b/replay/replay-internal.h
> > @@ -50,6 +50,7 @@ enum ReplayAsyncEventKind {
> >       REPLAY_ASYNC_EVENT_INPUT_SYNC,
> >       REPLAY_ASYNC_EVENT_CHAR_READ,
> >       REPLAY_ASYNC_EVENT_BLOCK,
> > +    REPLAY_ASYNC_EVENT_NET,
> >       REPLAY_ASYNC_COUNT
> >   };
> >
> > @@ -155,4 +156,13 @@ void replay_event_char_read_save(void *opaque);
> >   /*! Reads char event read from the file. */
> >   void *replay_event_char_read_load(void);
> >
> > +/* Network devices */
> > +
> > +/*! Called to run network event. */
> > +void replay_event_net_run(void *opaque);
> > +/*! Writes network event to the file. */
> > +void replay_event_net_save(void *opaque);
> > +/*! Reads network from the file. */
> > +void *replay_event_net_load(void);
> > +
> >   #endif
> > diff --git a/replay/replay-net.c b/replay/replay-net.c
> > new file mode 100644
> > index 0000000..4f7b995
> > --- /dev/null
> > +++ b/replay/replay-net.c
> > @@ -0,0 +1,111 @@
> > +/*
> > + * replay-net.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 "qemu/error-report.h"
> > +#include "sysemu/replay.h"
> > +#include "replay-internal.h"
> > +#include "sysemu/sysemu.h"
> > +#include "net/net.h"
> > +#include "net/filter.h"
> > +#include "qemu/iov.h"
> > +
> > +struct ReplayNetState {
> > +    NetFilterState *nfs;
> > +    int id;
> > +};
> > +
> > +typedef struct NetEvent {
> > +    uint8_t id;
> > +    uint32_t flags;
> > +    uint8_t *data;
> > +    size_t size;
> > +} NetEvent;
> > +
> > +static NetFilterState **network_filters;
> > +static int network_filters_count;
> > +
> > +ReplayNetState *replay_register_net(NetFilterState *nfs)
> > +{
> > +    ReplayNetState *rns = g_new0(ReplayNetState, 1);
> > +    rns->nfs = nfs;
> > +    rns->id = network_filters_count++;
> > +    network_filters = g_realloc(network_filters,
> > +                                network_filters_count
> > +                                    * sizeof(*network_filters));
> 
> Any chance to avoid maintaining such array? E.g by having a pointer to
> NetFilterState in each NetEvent?

This array is needed for replay mode.
There is no information about NetFilterState in the event which was read from the log file.
Log provides only NFS id, which we use to recover the pointer.

> 
> > +    network_filters[network_filters_count - 1] = nfs;
> > +    return rns;
> > +}
> > +
> > +void replay_unregister_net(ReplayNetState *rns)
> > +{
> > +    network_filters[rns->id] = NULL;
> > +    g_free(rns);
> > +}
> > +
> > +void replay_net_packet_event(ReplayNetState *rns, unsigned flags,
> > +                             const struct iovec *iov, int iovcnt)
> > +{
> > +    NetEvent *event;
> > +    int i;
> > +
> > +    event = g_new(NetEvent, 1);
> > +    event->flags = flags;
> > +    event->data = g_malloc(iov_size(iov, iovcnt));
> > +    event->size = 0;
> > +    event->id = rns->id;
> > +
> > +    for (i = 0; i < iovcnt; i++) {
> > +        size_t len = iov[i].iov_len;
> > +
> > +        memcpy(event->data + event->size, iov[i].iov_base, len);
> > +        event->size += len;
> > +    }
> 
> You can use iov_to_buf() instead.

Thanks.

Pavel Dovgalyuk

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v4 1/8] record/replay: add network support
  2016-09-23  6:06   ` Jason Wang
  2016-09-23  7:52     ` Pavel Dovgalyuk
@ 2016-10-13  8:01     ` Pavel Dovgalyuk
  1 sibling, 0 replies; 22+ messages in thread
From: Pavel Dovgalyuk @ 2016-10-13  8:01 UTC (permalink / raw)
  To: 'Jason Wang', 'Pavel Dovgalyuk', qemu-devel
  Cc: peter.maydell, quintela, pbonzini, mst

Jason, what about v5 of this patch?

Pavel Dovgalyuk

> -----Original Message-----
> From: Jason Wang [mailto:jasowang@redhat.com]
> Sent: Friday, September 23, 2016 9:07 AM
> To: Pavel Dovgalyuk; qemu-devel@nongnu.org
> Cc: peter.maydell@linaro.org; quintela@redhat.com; pbonzini@redhat.com; mst@redhat.com
> Subject: Re: [PATCH v4 1/8] record/replay: add network support
> 
> 
> 
> On 2016年09月21日 19:33, Pavel Dovgalyuk wrote:
> > This patch adds support of recording and replaying network packets in
> > irount rr mode.
> >
> > Record and replay for network interactions is performed with the network filter.
> > Each backend must have its own instance of the replay filter as follows:
> >   -netdev user,id=net1 -device rtl8139,netdev=net1
> >   -object filter-replay,id=replay,netdev=net1
> >
> > Replay network filter is used to record and replay network packets. While
> > recording the virtual machine this filter puts all packets coming from
> > the outer world into the log. In replay mode packets from the log are
> > injected into the network device. All interactions with network backend
> > in replay mode are disabled.
> >
> > Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
> 
> Looks good, just few nits, see below.
> 
> Thanks
> 
> > ---
> >   docs/replay.txt          |   14 ++++++
> >   include/sysemu/replay.h  |   12 +++++
> >   net/Makefile.objs        |    1
> >   net/filter-replay.c      |   92 ++++++++++++++++++++++++++++++++++++++
> >   replay/Makefile.objs     |    1
> >   replay/replay-events.c   |   11 +++++
> >   replay/replay-internal.h |   10 ++++
> >   replay/replay-net.c      |  111 ++++++++++++++++++++++++++++++++++++++++++++++
> >   replay/replay.c          |    2 -
> >   vl.c                     |    3 +
> >   10 files changed, 255 insertions(+), 2 deletions(-)
> >   create mode 100644 net/filter-replay.c
> >   create mode 100644 replay/replay-net.c
> >
> > diff --git a/docs/replay.txt b/docs/replay.txt
> > index 779c6c0..347b2ff 100644
> > --- a/docs/replay.txt
> > +++ b/docs/replay.txt
> > @@ -195,3 +195,17 @@ Queue is flushed at checkpoints and information about processed
> requests
> >   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.
> > +
> > +Network devices
> > +---------------
> > +
> > +Record and replay for network interactions is performed with the network filter.
> > +Each backend must have its own instance of the replay filter as follows:
> > + -netdev user,id=net1 -device rtl8139,netdev=net1
> > + -object filter-replay,id=replay,netdev=net1
> > +
> > +Replay network filter is used to record and replay network packets. While
> > +recording the virtual machine this filter puts all packets coming from
> > +the outer world into the log. In replay mode packets from the log are
> > +injected into the network device. All interactions with network backend
> > +in replay mode are disabled.
> > diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h
> > index 0a88393..a408633 100644
> > --- a/include/sysemu/replay.h
> > +++ b/include/sysemu/replay.h
> > @@ -39,6 +39,8 @@ enum ReplayCheckpoint {
> >   };
> >   typedef enum ReplayCheckpoint ReplayCheckpoint;
> >
> > +typedef struct ReplayNetState ReplayNetState;
> > +
> >   extern ReplayMode replay_mode;
> >
> >   /* Replay process control functions */
> > @@ -133,4 +135,14 @@ void replay_char_read_all_save_error(int res);
> >   /*! Writes character read_all execution result into the replay log. */
> >   void replay_char_read_all_save_buf(uint8_t *buf, int offset);
> >
> > +/* Network */
> > +
> > +/*! Registers replay network filter attached to some backend. */
> > +ReplayNetState *replay_register_net(NetFilterState *nfs);
> > +/*! Unregisters replay network filter. */
> > +void replay_unregister_net(ReplayNetState *rns);
> > +/*! Called to write network packet to the replay log. */
> > +void replay_net_packet_event(ReplayNetState *rns, unsigned flags,
> > +                             const struct iovec *iov, int iovcnt);
> > +
> >   #endif
> > diff --git a/net/Makefile.objs b/net/Makefile.objs
> > index b7c22fd..f787ba4 100644
> > --- a/net/Makefile.objs
> > +++ b/net/Makefile.objs
> > @@ -16,3 +16,4 @@ common-obj-$(CONFIG_NETMAP) += netmap.o
> >   common-obj-y += filter.o
> >   common-obj-y += filter-buffer.o
> >   common-obj-y += filter-mirror.o
> > +common-obj-y += filter-replay.o
> > diff --git a/net/filter-replay.c b/net/filter-replay.c
> > new file mode 100644
> > index 0000000..cff65f8
> > --- /dev/null
> > +++ b/net/filter-replay.c
> > @@ -0,0 +1,92 @@
> > +/*
> > + * filter-replay.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 "clients.h"
> > +#include "qapi/error.h"
> > +#include "qemu-common.h"
> > +#include "qemu/error-report.h"
> > +#include "qemu/iov.h"
> > +#include "qemu/log.h"
> > +#include "qemu/timer.h"
> > +#include "qapi/visitor.h"
> > +#include "net/filter.h"
> > +#include "sysemu/replay.h"
> > +
> > +#define TYPE_FILTER_REPLAY "filter-replay"
> > +
> > +#define FILTER_REPLAY(obj) \
> > +    OBJECT_CHECK(NetFilterReplayState, (obj), TYPE_FILTER_REPLAY)
> > +
> > +struct NetFilterReplayState {
> > +    NetFilterState nfs;
> > +    ReplayNetState *rns;
> > +};
> > +typedef struct NetFilterReplayState NetFilterReplayState;
> > +
> > +static ssize_t filter_replay_receive_iov(NetFilterState *nf,
> > +                                         NetClientState *sndr,
> > +                                         unsigned flags,
> > +                                         const struct iovec *iov,
> > +                                         int iovcnt, NetPacketSent *sent_cb)
> > +{
> > +    NetFilterReplayState *nfrs = FILTER_REPLAY(nf);
> > +    switch (replay_mode) {
> > +    case REPLAY_MODE_RECORD:
> > +        if (nf->netdev == sndr) {
> > +            replay_net_packet_event(nfrs->rns, flags, iov, iovcnt);
> > +            return iov_size(iov, iovcnt);
> > +        }
> > +        return 0;
> > +    case REPLAY_MODE_PLAY:
> > +        /* Drop all packets in replay mode.
> > +           Packets from the log will be injected by the replay module. */
> > +        return iov_size(iov, iovcnt);
> > +    default:
> > +        /* Pass all the packets. */
> > +        return 0;
> > +    }
> > +}
> > +
> > +static void filter_replay_instance_init(Object *obj)
> > +{
> > +    NetFilterReplayState *nfrs = FILTER_REPLAY(obj);
> > +    nfrs->rns = replay_register_net(&nfrs->nfs);
> > +}
> > +
> > +static void filter_replay_instance_finalize(Object *obj)
> > +{
> > +    NetFilterReplayState *nfrs = FILTER_REPLAY(obj);
> > +    replay_unregister_net(nfrs->rns);
> > +}
> > +
> > +static void filter_replay_class_init(ObjectClass *oc, void *data)
> > +{
> > +    NetFilterClass *nfc = NETFILTER_CLASS(oc);
> > +
> > +    nfc->receive_iov = filter_replay_receive_iov;
> > +}
> > +
> > +static const TypeInfo filter_replay_info = {
> > +    .name = TYPE_FILTER_REPLAY,
> > +    .parent = TYPE_NETFILTER,
> > +    .class_init = filter_replay_class_init,
> > +    .instance_init = filter_replay_instance_init,
> > +    .instance_finalize = filter_replay_instance_finalize,
> > +    .instance_size = sizeof(NetFilterReplayState),
> > +};
> > +
> > +static void filter_replay_register_types(void)
> > +{
> > +    type_register_static(&filter_replay_info);
> > +}
> > +
> > +type_init(filter_replay_register_types);
> > diff --git a/replay/Makefile.objs b/replay/Makefile.objs
> > index fcb3f74..f55a6b5 100644
> > --- a/replay/Makefile.objs
> > +++ b/replay/Makefile.objs
> > @@ -4,3 +4,4 @@ common-obj-y += replay-events.o
> >   common-obj-y += replay-time.o
> >   common-obj-y += replay-input.o
> >   common-obj-y += replay-char.o
> > +common-obj-y += replay-net.o
> > diff --git a/replay/replay-events.c b/replay/replay-events.c
> > index 3807245..9ce9e51 100644
> > --- a/replay/replay-events.c
> > +++ b/replay/replay-events.c
> > @@ -54,6 +54,9 @@ static void replay_run_event(Event *event)
> >       case REPLAY_ASYNC_EVENT_BLOCK:
> >           aio_bh_call(event->opaque);
> >           break;
> > +    case REPLAY_ASYNC_EVENT_NET:
> > +        replay_event_net_run(event->opaque);
> > +        break;
> >       default:
> >           error_report("Replay: invalid async event ID (%d) in the queue",
> >                       event->event_kind);
> > @@ -189,6 +192,9 @@ static void replay_save_event(Event *event, int checkpoint)
> >           case REPLAY_ASYNC_EVENT_BLOCK:
> >               replay_put_qword(event->id);
> >               break;
> > +        case REPLAY_ASYNC_EVENT_NET:
> > +            replay_event_net_save(event->opaque);
> > +            break;
> >           default:
> >               error_report("Unknown ID %" PRId64 " of replay event", event->id);
> >               exit(1);
> > @@ -252,6 +258,11 @@ static Event *replay_read_event(int checkpoint)
> >               read_id = replay_get_qword();
> >           }
> >           break;
> > +    case REPLAY_ASYNC_EVENT_NET:
> > +        event = g_malloc0(sizeof(Event));
> > +        event->event_kind = read_event_kind;
> > +        event->opaque = replay_event_net_load();
> > +        return event;
> >       default:
> >           error_report("Unknown ID %d of replay event", read_event_kind);
> >           exit(1);
> > diff --git a/replay/replay-internal.h b/replay/replay-internal.h
> > index efbf14c..d28cfb7 100644
> > --- a/replay/replay-internal.h
> > +++ b/replay/replay-internal.h
> > @@ -50,6 +50,7 @@ enum ReplayAsyncEventKind {
> >       REPLAY_ASYNC_EVENT_INPUT_SYNC,
> >       REPLAY_ASYNC_EVENT_CHAR_READ,
> >       REPLAY_ASYNC_EVENT_BLOCK,
> > +    REPLAY_ASYNC_EVENT_NET,
> >       REPLAY_ASYNC_COUNT
> >   };
> >
> > @@ -155,4 +156,13 @@ void replay_event_char_read_save(void *opaque);
> >   /*! Reads char event read from the file. */
> >   void *replay_event_char_read_load(void);
> >
> > +/* Network devices */
> > +
> > +/*! Called to run network event. */
> > +void replay_event_net_run(void *opaque);
> > +/*! Writes network event to the file. */
> > +void replay_event_net_save(void *opaque);
> > +/*! Reads network from the file. */
> > +void *replay_event_net_load(void);
> > +
> >   #endif
> > diff --git a/replay/replay-net.c b/replay/replay-net.c
> > new file mode 100644
> > index 0000000..4f7b995
> > --- /dev/null
> > +++ b/replay/replay-net.c
> > @@ -0,0 +1,111 @@
> > +/*
> > + * replay-net.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 "qemu/error-report.h"
> > +#include "sysemu/replay.h"
> > +#include "replay-internal.h"
> > +#include "sysemu/sysemu.h"
> > +#include "net/net.h"
> > +#include "net/filter.h"
> > +#include "qemu/iov.h"
> > +
> > +struct ReplayNetState {
> > +    NetFilterState *nfs;
> > +    int id;
> > +};
> > +
> > +typedef struct NetEvent {
> > +    uint8_t id;
> > +    uint32_t flags;
> > +    uint8_t *data;
> > +    size_t size;
> > +} NetEvent;
> > +
> > +static NetFilterState **network_filters;
> > +static int network_filters_count;
> > +
> > +ReplayNetState *replay_register_net(NetFilterState *nfs)
> > +{
> > +    ReplayNetState *rns = g_new0(ReplayNetState, 1);
> > +    rns->nfs = nfs;
> > +    rns->id = network_filters_count++;
> > +    network_filters = g_realloc(network_filters,
> > +                                network_filters_count
> > +                                    * sizeof(*network_filters));
> 
> Any chance to avoid maintaining such array? E.g by having a pointer to
> NetFilterState in each NetEvent?
> 
> > +    network_filters[network_filters_count - 1] = nfs;
> > +    return rns;
> > +}
> > +
> > +void replay_unregister_net(ReplayNetState *rns)
> > +{
> > +    network_filters[rns->id] = NULL;
> > +    g_free(rns);
> > +}
> > +
> > +void replay_net_packet_event(ReplayNetState *rns, unsigned flags,
> > +                             const struct iovec *iov, int iovcnt)
> > +{
> > +    NetEvent *event;
> > +    int i;
> > +
> > +    event = g_new(NetEvent, 1);
> > +    event->flags = flags;
> > +    event->data = g_malloc(iov_size(iov, iovcnt));
> > +    event->size = 0;
> > +    event->id = rns->id;
> > +
> > +    for (i = 0; i < iovcnt; i++) {
> > +        size_t len = iov[i].iov_len;
> > +
> > +        memcpy(event->data + event->size, iov[i].iov_base, len);
> > +        event->size += len;
> > +    }
> 
> You can use iov_to_buf() instead.
> 
> > +
> > +    replay_add_event(REPLAY_ASYNC_EVENT_NET, event, NULL, 0);
> > +}
> > +
> > +void replay_event_net_run(void *opaque)
> > +{
> > +    NetEvent *event = opaque;
> > +    struct iovec iov = {
> > +        .iov_base = (void *)event->data,
> > +        .iov_len = event->size
> > +    };
> > +
> > +    assert(event->id < network_filters_count);
> > +
> > +    qemu_netfilter_pass_to_next(network_filters[event->id]->netdev,
> > +        event->flags, &iov, 1, network_filters[event->id]);
> > +
> > +    g_free(event->data);
> > +    g_free(event);
> > +}
> > +
> > +void replay_event_net_save(void *opaque)
> > +{
> > +    NetEvent *event = opaque;
> > +
> > +    replay_put_byte(event->id);
> > +    replay_put_dword(event->flags);
> > +    replay_put_array(event->data, event->size);
> > +}
> > +
> > +void *replay_event_net_load(void)
> > +{
> > +    NetEvent *event = g_new(NetEvent, 1);
> > +
> > +    event->id = replay_get_byte();
> > +    event->flags = replay_get_dword();
> > +    replay_get_array_alloc(&event->data, &event->size);
> > +
> > +    return event;
> > +}
> > diff --git a/replay/replay.c b/replay/replay.c
> > index 167fd29..e040f6f 100644
> > --- a/replay/replay.c
> > +++ b/replay/replay.c
> > @@ -21,7 +21,7 @@
> >
> >   /* Current version of the replay mechanism.
> >      Increase it when file format changes. */
> > -#define REPLAY_VERSION              0xe02004
> > +#define REPLAY_VERSION              0xe02005
> >   /* Size of replay log header */
> >   #define HEADER_SIZE                 (sizeof(uint32_t) + sizeof(uint64_t))
> >
> > diff --git a/vl.c b/vl.c
> > index fca0487..fd7f17e 100644
> > --- a/vl.c
> > +++ b/vl.c
> > @@ -2807,7 +2807,8 @@ static bool object_create_initial(const char *type)
> >       if (g_str_equal(type, "filter-buffer") ||
> >           g_str_equal(type, "filter-dump") ||
> >           g_str_equal(type, "filter-mirror") ||
> > -        g_str_equal(type, "filter-redirector")) {
> > +        g_str_equal(type, "filter-redirector") ||
> > +        g_str_equal(type, "filter-replay")) {
> >           return false;
> >       }
> >
> >

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2016-10-13  8:01 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-21 11:33 [Qemu-devel] [PATCH v4 0/8] replay additions Pavel Dovgalyuk
2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 1/8] record/replay: add network support Pavel Dovgalyuk
2016-09-23  6:06   ` Jason Wang
2016-09-23  7:52     ` Pavel Dovgalyuk
2016-10-13  8:01     ` Pavel Dovgalyuk
2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 2/8] replay: save/load initial state Pavel Dovgalyuk
2016-09-21 15:39   ` Paolo Bonzini
2016-09-21 15:49     ` Pavel Dovgalyuk
2016-09-21 15:57       ` Paolo Bonzini
2016-09-22  5:37         ` Pavel Dovgalyuk
2016-09-22  8:51           ` Paolo Bonzini
2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 3/8] block: don't make snapshots for filters Pavel Dovgalyuk
2016-09-21 15:37   ` Paolo Bonzini
2016-09-22  5:43     ` Pavel Dovgalyuk
2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 4/8] block: implement bdrv_recurse_is_first_non_filter for blkreplay Pavel Dovgalyuk
2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 5/8] replay: move internal data to the structure Pavel Dovgalyuk
2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 6/8] replay: vmstate for replay module Pavel Dovgalyuk
2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 7/8] replay: allow replay stopping and restarting Pavel Dovgalyuk
2016-09-21 11:33 ` [Qemu-devel] [PATCH v4 8/8] integratorcp: adding vmstate for save/restore Pavel Dovgalyuk
2016-09-21 15:40 ` [Qemu-devel] [PATCH v4 0/8] replay additions Paolo Bonzini
2016-09-22  5:41   ` Pavel Dovgalyuk
2016-09-22  8:51     ` Paolo Bonzini

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.