diff mbox

[RFC,13/22] Vmstate changes for replay

Message ID 008101cf951f$63281610$29784230$@Dovgaluk@ispras.ru
State New
Headers show

Commit Message

Pavel Dovgalyuk July 1, 2014, 11:27 a.m. UTC
These patches introduce new field types for vmstate and disables system
reset while loading the machine in replay mode. The machine should not be
reset, because it breaks timers of the hardware devices by reading vmclock
before completely restoring system's state.

Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@gmail.com>
---
diff mbox

Patch

diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 9a001bd..2f7207b 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -143,6 +143,7 @@  extern const VMStateDescription vmstate_dummy;
 #endif
 
 extern const VMStateInfo vmstate_info_bool;
+extern const VMStateInfo vmstate_info_char;
 
 extern const VMStateInfo vmstate_info_int8;
 extern const VMStateInfo vmstate_info_int16;
@@ -694,6 +695,18 @@  extern const VMStateInfo vmstate_info_bitmap;
 #define VMSTATE_UINT64_ARRAY(_f, _s, _n)                              \
     VMSTATE_UINT64_ARRAY_V(_f, _s, _n, 0)
 
+#define VMSTATE_INT8_ARRAY_V(_f, _s, _n, _v)                          \
+    VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_int8, int8_t)
+
+#define VMSTATE_INT8_ARRAY(_f, _s, _n)                                \
+    VMSTATE_INT8_ARRAY_V(_f, _s, _n, 0)
+
+#define VMSTATE_CHAR_ARRAY_V(_f, _s, _n, _v)                          \
+    VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_char, char)
+
+#define VMSTATE_CHAR_ARRAY(_f, _s, _n)                                \
+    VMSTATE_CHAR_ARRAY_V(_f, _s, _n, 0)
+
 #define VMSTATE_INT16_ARRAY_V(_f, _s, _n, _v)                         \
     VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_int16, int16_t)
 
diff --git a/savevm.c b/savevm.c
index e19ae0a..aad9188
--- a/savevm.c
+++ b/savevm.c
@@ -1039,7 +1039,7 @@  static int del_existing_snapshots(Monitor *mon, const char *name)
     return 0;
 }
 
-void do_savevm(Monitor *mon, const QDict *qdict)
+int save_vmstate(Monitor *mon, const char *name)
 {
     BlockDriverState *bs, *bs1;
     QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
@@ -1049,7 +1049,7 @@  void do_savevm(Monitor *mon, const QDict *qdict)
     uint64_t vm_state_size;
     qemu_timeval tv;
     struct tm tm;
-    const char *name = qdict_get_try_str(qdict, "name");
+    int success = 0;
 
     /* Verify if there is a device that doesn't support snapshots and is writable */
     bs = NULL;
@@ -1062,14 +1062,19 @@  void do_savevm(Monitor *mon, const QDict *qdict)
         if (!bdrv_can_snapshot(bs)) {
             monitor_printf(mon, "Device '%s' is writable but does not support snapshots.\n",
                                bdrv_get_device_name(bs));
-            return;
+            return success;
         }
     }
 
     bs = find_vmstate_bs();
     if (!bs) {
         monitor_printf(mon, "No block device can accept snapshots\n");
-        return;
+        if (replay_mode != REPLAY_NONE)
+        {
+            fprintf(stderr, "At least one hdd should be attached to QEMU for replay\n");
+            exit(1);
+        }
+        return success;
     }
 
     saved_vm_running = runstate_is_running();
@@ -1118,6 +1123,7 @@  void do_savevm(Monitor *mon, const QDict *qdict)
 
     /* create the snapshots */
 
+    success = 1;
     bs1 = NULL;
     while ((bs1 = bdrv_next(bs1))) {
         if (bdrv_can_snapshot(bs1)) {
@@ -1127,6 +1133,7 @@  void do_savevm(Monitor *mon, const QDict *qdict)
             if (ret < 0) {
                 monitor_printf(mon, "Error while creating snapshot on '%s'\n",
                                bdrv_get_device_name(bs1));
+                success = 0;
             }
         }
     }
@@ -1135,6 +1142,14 @@  void do_savevm(Monitor *mon, const QDict *qdict)
     if (saved_vm_running) {
         vm_start();
     }
+
+    return success;
+}
+
+void do_savevm(Monitor *mon, const QDict *qdict)
+{
+    const char *name = qdict_get_try_str(qdict, "name");
+    save_vmstate(mon, name);
 }
 
 void qmp_xen_save_devices_state(const char *filename, Error **errp)
@@ -1231,7 +1246,13 @@  int load_vmstate(const char *name)
         return -EINVAL;
     }
 
-    qemu_system_reset(VMRESET_SILENT);
+    // Do not reset in replay mode.
+    // 1. Reset will alter the behavior in play mode compared to save one
+    // 2. Timers read by reset handlers are not correct, because
+    //    replay reads them from the unknown part of the log
+    if (replay_mode == REPLAY_NONE) {
+        qemu_system_reset(VMRESET_SILENT);
+    }
     ret = qemu_loadvm_state(f);
 
     qemu_fclose(f);

diff --git a/vmstate.c b/vmstate.c
index ef2f87b..6a7f7c2 100644
--- a/vmstate.c
+++ b/vmstate.c
@@ -286,6 +286,12 @@  const VMStateInfo vmstate_info_int8 = {
     .put  = put_int8,
 };
 
+const VMStateInfo vmstate_info_char = {
+    .name = "char",
+    .get  = get_int8,
+    .put  = put_int8,
+};
+
 /* 16 bit int */
 
 static int get_int16(QEMUFile *f, void *pv, size_t size)