qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Sanidhya Kashyap <sanidhya.iiith@gmail.com>
To: qemu list <qemu-devel@nongnu.org>
Cc: Sanidhya Kashyap <sanidhya.iiith@gmail.com>,
	"Dr. David Alan Gilbert" <dgilbert@redhat.com>,
	Juan Quintela <quintela@redhat.com>
Subject: [Qemu-devel] [RFC PATCH v1 2/5] VMState test: basic vmstate testing mechanism
Date: Mon,  7 Jul 2014 22:48:01 +0530	[thread overview]
Message-ID: <1404753484-26693-3-git-send-email-sanidhya.iiith@gmail.com> (raw)
In-Reply-To: <1404753484-26693-1-git-send-email-sanidhya.iiith@gmail.com>

This patch introduces the mechanism to test the devices state by storing
and dumping in in the QEMUFile pointer.

The testing is done as follows:
1) The VM is halted.
2) guest state is synchronized.
3) Then the device state is dumped to a temporary memory.
4) The guest state is reset.
5) Then the device state is loaded from the temporary memory.
6) The guest is resumed.

If the guest resumes, then there is no issue with the vmstates.

Currently, in this patch, I am directly using the qemu_system_reset()
function to reset all the states of the guest. But, what I have found
is that there is a difference in the registration of devices' reset
function in QEMUResetEntry and in SaveStateEntry. Since, we dump and
load all the devices information using the SaveStateEntry, but the reseting
of the devices takes place with the help of QEMUResetEntry. Thus, in
future, I will try to use the qdevified device tree to reset the functions.


As of now, I am providing DPRINTF to know about the amount of time spend in
saving and loading the data from the buffer. If there is any other way that
should be used to print the stats, then please do let me know.

Signed-off-by: Sanidhya Kashyap <sanidhya.iiith@gmail.com>
---
 qapi-schema.json |  12 +++++
 qmp-commands.hx  |  28 +++++++++++
 savevm.c         | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 188 insertions(+)

diff --git a/qapi-schema.json b/qapi-schema.json
index b11aad2..92acf91 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3480,3 +3480,15 @@
 # Since: 2.1
 ##
 { 'command': 'rtc-reset-reinjection' }
+
+## @test-vmstates
+#
+# tests the vmstates' value by dumping and loading in memory
+# @times: total iterations
+# @sinterval: sleep interval between iteration
+#
+# Since 2.1
+##
+{ 'command': 'test-vmstates',
+  'data': {'*times'     : 'int',
+           '*sinterval' : 'int' } }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 4be4765..ccddabb 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -3755,3 +3755,31 @@ Example:
 <- { "return": {} }
 
 EQMP
+
+    {
+        .name       = "test-vmstates",
+        .args_type  = "times:i?,sinterval:i?",
+        .mhandler.cmd_new = qmp_marshal_input_test_vmstates,
+    },
+
+SQMP
+test-vmstates
+--------------------
+
+Tests the vmstates' entry by dumping and loading in/from memory
+
+Arguments:
+
+- "times" :    the total iterations for vmstates testing. The default
+               value is 10.
+- "sinterval": the sleep interval between the iterations. The default
+               value is 100 milliseconds.
+
+Example:
+
+-> { "execute": "test-vmstates",
+     "arguments": {
+        "times": 10
+        "sinterval": 100 } }
+<- { "return": {} }
+EQMP
diff --git a/savevm.c b/savevm.c
index e19ae0a..3713a56 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1137,6 +1137,154 @@ void do_savevm(Monitor *mon, const QDict *qdict)
     }
 }
 
+#ifdef DEBUG_TEST_VMSTATES
+#define DPRINTF(fmt, ...) \
+    do { printf("vmstate_test: " fmt, ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) \
+    do { } while (0)
+#endif
+
+#define TEST_VMSTATE_MIN_TIMES 10
+#define TEST_VMSTATE_MAX_TIMES 1000
+
+#define TEST_VMSTATE_MIN_INTERVAL_MS 1
+#define TEST_VMSTATE_DEFAULT_INTERVAL_MS 100
+#define TEST_VMSTATE_MAX_INTERVAL_MS 10000
+
+typedef struct VMStateLogState VMStateLogState;
+
+struct VMStateLogState {
+    int64_t times;
+    int64_t sleep_interval;
+    int64_t save_vmstates_duration;
+    int64_t load_vmstates_duration;
+    bool active_state;
+    QEMUTimer *timer;
+};
+
+static VMStateLogState *vmstate_current_state(void)
+{
+    static VMStateLogState current_state = {
+        .active_state = false,
+    };
+
+    return &current_state;
+}
+
+static void vmstate_test_cb(void *opaque)
+{
+    VMStateLogState *v = opaque;
+    int saved_vm_running = runstate_is_running();
+    const QEMUSizedBuffer *qsb;
+    QEMUFile *f;
+    int ret;
+    int64_t start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
+
+    /* executing the steps for a single time with the help of timer */
+    if (--(v->times) > 0) {
+        saved_vm_running = runstate_is_running();
+
+        /* stopping the VM before dumping the vmstates */
+        vm_stop(RUN_STATE_SAVE_VM);
+
+        f = qemu_bufopen("w", NULL);
+        if (!f) {
+            goto testing_end;
+        }
+
+        cpu_synchronize_all_states();
+
+        /* saving the vmsates to memory buffer */
+        ret = qemu_save_device_state(f);
+        if (ret < 0) {
+            goto testing_end;
+        }
+        v->save_vmstates_duration = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) -
+                                    start_time;
+        DPRINTF("iteration: %ld, save time: %ld(ms)\n",
+                v->times, v->save_vmstates_duration);
+
+        /* clearing the states of the guest */
+        qemu_system_reset(VMRESET_SILENT);
+
+        start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
+        qsb = qemu_buf_get(f);
+        f = qemu_bufopen("r", (QEMUSizedBuffer *)qsb);
+        if (!f) {
+            goto testing_end;
+        }
+
+        /* loading the device states from the saved buffer */
+        ret = qemu_loadvm_state(f);
+        qemu_fclose(f);
+        if (ret < 0) {
+            goto testing_end;
+        }
+        v->load_vmstates_duration = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) -
+                                    start_time;
+        DPRINTF("iteration: %ld, load time: %ld(ms)\n",
+                v->times, v->load_vmstates_duration);
+
+        if (saved_vm_running) {
+            vm_start();
+        }
+        timer_mod(v->timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) +
+                                              v->sleep_interval);
+        return;
+    }
+
+ testing_end:
+    if (saved_vm_running) {
+        vm_start();
+    }
+    timer_del(v->timer);
+    timer_free(v->timer);
+    v->active_state = false;
+    return;
+}
+
+void qmp_test_vmstates(bool has_times, int64_t times,
+                       bool has_sinterval, int64_t sinterval,
+                       Error **errp)
+{
+    VMStateLogState *v = vmstate_current_state();
+
+    if (v->active_state) {
+        error_setg(errp, "VMState testing already in progress\n");
+        return;
+    }
+
+    /* checking the value of times to be in the defined range */
+    if (!has_times) {
+        v->times = TEST_VMSTATE_MIN_TIMES;
+    } else if (times >= TEST_VMSTATE_MIN_TIMES &&
+               times <= TEST_VMSTATE_MAX_TIMES) {
+        v->times = times;
+    } else {
+        error_setg(errp, "epoch value must be in the range [%d, %d]\n",
+                   TEST_VMSTATE_MIN_TIMES, TEST_VMSTATE_MAX_TIMES);
+        return;
+    }
+
+    /* checking for the value of sleep_interval to be in the defined range */
+    if (!has_sinterval) {
+        v->sleep_interval = TEST_VMSTATE_DEFAULT_INTERVAL_MS;
+    } else if (sinterval >= TEST_VMSTATE_MIN_INTERVAL_MS &&
+               sinterval <= TEST_VMSTATE_MAX_INTERVAL_MS) {
+        v->sleep_interval = sinterval;
+    } else {
+        error_setg(errp, "sleep interval value must be "
+                   "in the defined range [%d, %d](ms)\n",
+                   TEST_VMSTATE_MIN_INTERVAL_MS, TEST_VMSTATE_MAX_INTERVAL_MS);
+        return;
+    }
+
+    v->active_state = true;
+    v->timer = timer_new_ms(QEMU_CLOCK_REALTIME, vmstate_test_cb, v);
+    timer_mod(v->timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
+}
+
 void qmp_xen_save_devices_state(const char *filename, Error **errp)
 {
     QEMUFile *f;
-- 
1.9.3

  parent reply	other threads:[~2014-07-07 17:19 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-07-07 17:17 [Qemu-devel] [RFC PATCH v1 0/5] VMState testing Sanidhya Kashyap
2014-07-07 17:18 ` [Qemu-devel] [RFC PATCH v1 1/5] QEMUSizedBuffer/QEMUFile Sanidhya Kashyap
2014-07-07 18:28   ` Eric Blake
2014-07-08  7:48     ` Dr. David Alan Gilbert
2014-07-07 17:18 ` Sanidhya Kashyap [this message]
2014-07-07 17:33   ` [Qemu-devel] [RFC PATCH v1 2/5] VMState test: basic vmstate testing mechanism Eric Blake
2014-07-07 17:18 ` [Qemu-devel] [RFC PATCH v1 3/5] VMState test: hmp interface for vmstate testing Sanidhya Kashyap
2014-07-07 17:18 ` [Qemu-devel] [RFC PATCH v1 4/5] VMState test: set the frequency of the vmstate testing process Sanidhya Kashyap
2014-07-07 18:25   ` Eric Blake
2014-07-18 18:59     ` Sanidhya Kashyap
2014-07-07 17:18 ` [Qemu-devel] [RFC PATCH v1 5/5] VMState test: cancel mechanism for an already running " Sanidhya Kashyap

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=1404753484-26693-3-git-send-email-sanidhya.iiith@gmail.com \
    --to=sanidhya.iiith@gmail.com \
    --cc=dgilbert@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=quintela@redhat.com \
    /path/to/YOUR_REPLY

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

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