qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/5] ahci: enable migration
@ 2015-02-24 17:38 John Snow
  2015-02-24 17:38 ` [Qemu-devel] [PATCH 1/5] libqos: Add migration helpers John Snow
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: John Snow @ 2015-02-24 17:38 UTC (permalink / raw)
  To: qemu-devel
  Cc: kwolf, marc.mari.barcelo, mst, armbru, stefanha, pbonzini,
	John Snow

The day we all feared is here, and I am proposing we allow the
migration of the AHCI device. The series that precedes this
which fixes AHCI migration has improved the stability of the
device and as this test series proves, is stable.

I am justifying this checkin based on a series of ping-pong
migration tests I ran under heavy load (using google's stressapptest)
and saw over 300 successful migrations without a single failure.

This series does a few things:
(1) Add migration facilities to libqos
(2) Enable AHCI and ICH9 migration
(3) Add a series of migration tests to ahci-test

This patch has several dependencies:

(1) stefanha/block
(2) [PATCH v4 00/17] ide: rerror/werror migration fixes for IDE/ISA and AHCI
(3) [PATCH 0/8] ahci: add more IO tests
(4) [PATCH 0/6] ahci: rerror/werror=stop resume tests

1, 3 and 4 are ahci-test framework dependencies, but 2 actually allows the
AHCI migration to become stable.

John Snow (5):
  libqos: Add migration helpers
  ich9/ahci: Enable Migration
  qtest/ahci: Add migration test
  qtest/ahci: add migrate dma test
  qtest/ahci: add flush migrate test

 hw/ide/ahci.c         |   1 -
 hw/ide/ich.c          |   1 -
 tests/ahci-test.c     | 184 +++++++++++++++++++++++++++++++++++++++++++++++++-
 tests/libqos/ahci.c   |   1 +
 tests/libqos/libqos.c |  75 ++++++++++++++++++++
 tests/libqos/libqos.h |   2 +
 tests/libqos/malloc.c |  74 +++++++++++++++-----
 tests/libqos/malloc.h |   1 +
 8 files changed, 319 insertions(+), 20 deletions(-)

-- 
1.9.3

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

* [Qemu-devel] [PATCH 1/5] libqos: Add migration helpers
  2015-02-24 17:38 [Qemu-devel] [PATCH 0/5] ahci: enable migration John Snow
@ 2015-02-24 17:38 ` John Snow
  2015-02-24 17:38 ` [Qemu-devel] [PATCH 2/5] ich9/ahci: Enable Migration John Snow
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: John Snow @ 2015-02-24 17:38 UTC (permalink / raw)
  To: qemu-devel
  Cc: kwolf, marc.mari.barcelo, mst, armbru, stefanha, pbonzini,
	John Snow

libqos.c:
    -set_context for addressing which commands go where
    -migrate performs the actual migration

malloc.c:
    - Structure of the allocator is adjusted slightly with
      a second-tier malloc to make swapping around the allocators
      easy when we "migrate" the lists from the source to the destination.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 tests/libqos/libqos.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/libqos/libqos.h |  2 ++
 tests/libqos/malloc.c | 74 ++++++++++++++++++++++++++++++++++++++------------
 tests/libqos/malloc.h |  1 +
 4 files changed, 135 insertions(+), 17 deletions(-)

diff --git a/tests/libqos/libqos.c b/tests/libqos/libqos.c
index 1a54a32..4602032 100644
--- a/tests/libqos/libqos.c
+++ b/tests/libqos/libqos.c
@@ -1,5 +1,6 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <glib.h>
 #include <unistd.h>
 #include <fcntl.h>
@@ -62,6 +63,80 @@ void qtest_shutdown(QOSState *qs)
     g_free(qs);
 }
 
+void set_context(QOSState *s)
+{
+    global_qtest = s->qts;
+}
+
+static QDict *qmp_execute(const char *command)
+{
+    char *fmt;
+    QDict *rsp;
+
+    fmt = g_strdup_printf("{ 'execute': '%s' }", command);
+    rsp = qmp(fmt);
+    g_free(fmt);
+
+    return rsp;
+}
+
+void migrate(QOSState *from, QOSState *to)
+{
+    const char *s, *st;
+    QDict *rsp, *sub;
+    bool running;
+
+    set_context(from);
+
+    /* Is the machine currently running? */
+    rsp = qmp_execute("query-status");
+    g_assert(qdict_haskey(rsp, "return"));
+    sub = qdict_get_qdict(rsp, "return");
+    g_assert(qdict_haskey(sub, "running"));
+    running = qdict_get_bool(sub, "running");
+    QDECREF(rsp);
+
+    /* Issue the migrate command. */
+    s = "{ 'execute': 'migrate', 'arguments': { 'uri': 'tcp:127.0.0.1:1234' } }";
+    rsp = qmp(s);
+    g_assert(qdict_haskey(rsp, "return"));
+    QDECREF(rsp);
+
+    /* Wait for STOP event, but only if we were running: */
+    if (running) {
+        qmp_eventwait("STOP");
+    }
+
+    /* Poll until migration is completed. */
+    while (1) {
+        rsp = qmp_execute("query-migrate");
+        g_assert(qdict_haskey(rsp, "return"));
+        sub = qdict_get_qdict(rsp, "return");
+        g_assert(qdict_haskey(sub, "status"));
+        st = qdict_get_str(sub, "status");
+
+        /* "setup", "active", "completed", "failed", "cancelled" */
+        if (strcmp(st, "completed") == 0) {
+            QDECREF(rsp);
+            break;
+        }
+
+        if ((strcmp(st, "setup") == 0) || (strcmp(st, "active") == 0)) {
+            QDECREF(rsp);
+            continue;
+        }
+
+        fprintf(stderr, "Migration did not complete, status: %s\n", st);
+        g_assert_not_reached();
+    }
+
+    migrate_allocator(from->alloc, to->alloc);
+    set_context(to);
+
+    /* BUG? VM will emit a RESUME event regardless of running status. */
+    qmp_eventwait("RESUME");
+}
+
 int mkqcow2(const char *file, unsigned size_mb)
 {
     pid_t pid;
diff --git a/tests/libqos/libqos.h b/tests/libqos/libqos.h
index f459783..42eca5e 100644
--- a/tests/libqos/libqos.h
+++ b/tests/libqos/libqos.h
@@ -19,6 +19,8 @@ typedef struct QOSState {
 QOSState *qtest_vboot(QOSOps *ops, const char *cmdline_fmt, va_list ap);
 QOSState *qtest_boot(QOSOps *ops, const char *cmdline_fmt, ...);
 void qtest_shutdown(QOSState *qs);
+void set_context(QOSState *s);
+void migrate(QOSState *from, QOSState *to);
 int mkqcow2(const char *file, unsigned size_mb);
 void prepare_blkdebug_script(const char *debug_fn, const char *event);
 
diff --git a/tests/libqos/malloc.c b/tests/libqos/malloc.c
index ad283f6..e200919 100644
--- a/tests/libqos/malloc.c
+++ b/tests/libqos/malloc.c
@@ -30,8 +30,8 @@ typedef struct QGuestAllocator {
     uint64_t end;
     uint32_t page_size;
 
-    MemList used;
-    MemList free;
+    MemList *used;
+    MemList *free;
 } QGuestAllocator;
 
 #define DEFAULT_PAGE_SIZE 4096
@@ -150,7 +150,7 @@ static uint64_t mlist_fulfill(QGuestAllocator *s, MemBlock *freenode,
     addr = freenode->addr;
     if (freenode->size == size) {
         /* re-use this freenode as our used node */
-        QTAILQ_REMOVE(&s->free, freenode, MLIST_ENTNAME);
+        QTAILQ_REMOVE(s->free, freenode, MLIST_ENTNAME);
         usednode = freenode;
     } else {
         /* adjust the free node and create a new used node */
@@ -159,7 +159,7 @@ static uint64_t mlist_fulfill(QGuestAllocator *s, MemBlock *freenode,
         usednode = mlist_new(addr, size);
     }
 
-    mlist_sort_insert(&s->used, usednode);
+    mlist_sort_insert(s->used, usednode);
     return addr;
 }
 
@@ -171,7 +171,7 @@ static void mlist_check(QGuestAllocator *s)
     uint64_t addr = s->start > 0 ? s->start - 1 : 0;
     uint64_t next = s->start;
 
-    QTAILQ_FOREACH(node, &s->free, MLIST_ENTNAME) {
+    QTAILQ_FOREACH(node, s->free, MLIST_ENTNAME) {
         g_assert_cmpint(node->addr, >, addr);
         g_assert_cmpint(node->addr, >=, next);
         addr = node->addr;
@@ -180,7 +180,7 @@ static void mlist_check(QGuestAllocator *s)
 
     addr = s->start > 0 ? s->start - 1 : 0;
     next = s->start;
-    QTAILQ_FOREACH(node, &s->used, MLIST_ENTNAME) {
+    QTAILQ_FOREACH(node, s->used, MLIST_ENTNAME) {
         g_assert_cmpint(node->addr, >, addr);
         g_assert_cmpint(node->addr, >=, next);
         addr = node->addr;
@@ -192,7 +192,7 @@ static uint64_t mlist_alloc(QGuestAllocator *s, uint64_t size)
 {
     MemBlock *node;
 
-    node = mlist_find_space(&s->free, size);
+    node = mlist_find_space(s->free, size);
     if (!node) {
         fprintf(stderr, "Out of guest memory.\n");
         g_assert_not_reached();
@@ -208,7 +208,7 @@ static void mlist_free(QGuestAllocator *s, uint64_t addr)
         return;
     }
 
-    node = mlist_find_key(&s->used, addr);
+    node = mlist_find_key(s->used, addr);
     if (!node) {
         fprintf(stderr, "Error: no record found for an allocation at "
                 "0x%016" PRIx64 ".\n",
@@ -217,9 +217,9 @@ static void mlist_free(QGuestAllocator *s, uint64_t addr)
     }
 
     /* Rip it out of the used list and re-insert back into the free list. */
-    QTAILQ_REMOVE(&s->used, node, MLIST_ENTNAME);
-    mlist_sort_insert(&s->free, node);
-    mlist_coalesce(&s->free, node);
+    QTAILQ_REMOVE(s->used, node, MLIST_ENTNAME);
+    mlist_sort_insert(s->free, node);
+    mlist_coalesce(s->free, node);
 }
 
 /*
@@ -233,7 +233,7 @@ void alloc_uninit(QGuestAllocator *allocator)
     QAllocOpts mask;
 
     /* Check for guest leaks, and destroy the list. */
-    QTAILQ_FOREACH_SAFE(node, &allocator->used, MLIST_ENTNAME, tmp) {
+    QTAILQ_FOREACH_SAFE(node, allocator->used, MLIST_ENTNAME, tmp) {
         if (allocator->opts & (ALLOC_LEAK_WARN | ALLOC_LEAK_ASSERT)) {
             fprintf(stderr, "guest malloc leak @ 0x%016" PRIx64 "; "
                     "size 0x%016" PRIx64 ".\n",
@@ -248,7 +248,7 @@ void alloc_uninit(QGuestAllocator *allocator)
     /* If we have previously asserted that there are no leaks, then there
      * should be only one node here with a specific address and size. */
     mask = ALLOC_LEAK_ASSERT | ALLOC_PARANOID;
-    QTAILQ_FOREACH_SAFE(node, &allocator->free, MLIST_ENTNAME, tmp) {
+    QTAILQ_FOREACH_SAFE(node, allocator->free, MLIST_ENTNAME, tmp) {
         if ((allocator->opts & mask) == mask) {
             if ((node->addr != allocator->start) ||
                 (node->size != allocator->end - allocator->start)) {
@@ -260,6 +260,8 @@ void alloc_uninit(QGuestAllocator *allocator)
         g_free(node);
     }
 
+    g_free(allocator->used);
+    g_free(allocator->free);
     g_free(allocator);
 }
 
@@ -297,11 +299,13 @@ QGuestAllocator *alloc_init(uint64_t start, uint64_t end)
     s->start = start;
     s->end = end;
 
-    QTAILQ_INIT(&s->used);
-    QTAILQ_INIT(&s->free);
+    s->used = g_malloc(sizeof(MemList));
+    s->free = g_malloc(sizeof(MemList));
+    QTAILQ_INIT(s->used);
+    QTAILQ_INIT(s->free);
 
     node = mlist_new(s->start, s->end - s->start);
-    QTAILQ_INSERT_HEAD(&s->free, node, MLIST_ENTNAME);
+    QTAILQ_INSERT_HEAD(s->free, node, MLIST_ENTNAME);
 
     s->page_size = DEFAULT_PAGE_SIZE;
 
@@ -319,7 +323,7 @@ QGuestAllocator *alloc_init_flags(QAllocOpts opts,
 void alloc_set_page_size(QGuestAllocator *allocator, size_t page_size)
 {
     /* Can't alter the page_size for an allocator in-use */
-    g_assert(QTAILQ_EMPTY(&allocator->used));
+    g_assert(QTAILQ_EMPTY(allocator->used));
 
     g_assert(is_power_of_2(page_size));
     allocator->page_size = page_size;
@@ -329,3 +333,39 @@ void alloc_set_flags(QGuestAllocator *allocator, QAllocOpts opts)
 {
     allocator->opts |= opts;
 }
+
+void migrate_allocator(QGuestAllocator *src,
+                       QGuestAllocator *dst)
+{
+    MemBlock *node, *tmp;
+    MemList *tmpused, *tmpfree;
+
+    /* The general memory layout should be equivalent,
+     * though opts can differ. */
+    g_assert_cmphex(src->start, ==, dst->start);
+    g_assert_cmphex(src->end, ==, dst->end);
+
+    /* Destroy (silently, regardless of options) the dest-list: */
+    QTAILQ_FOREACH_SAFE(node, dst->used, MLIST_ENTNAME, tmp) {
+        g_free(node);
+    }
+    QTAILQ_FOREACH_SAFE(node, dst->free, MLIST_ENTNAME, tmp) {
+        g_free(node);
+    }
+
+    tmpused = dst->used;
+    tmpfree = dst->free;
+
+    /* Inherit the lists of the source allocator: */
+    dst->used = src->used;
+    dst->free = src->free;
+
+    /* Source is now re-initialized, the source memory is 'invalid' now: */
+    src->used = tmpused;
+    src->free = tmpfree;
+    QTAILQ_INIT(src->used);
+    QTAILQ_INIT(src->free);
+    node = mlist_new(src->start, src->end - src->start);
+    QTAILQ_INSERT_HEAD(src->free, node, MLIST_ENTNAME);
+    return;
+}
diff --git a/tests/libqos/malloc.h b/tests/libqos/malloc.h
index 71ac407..0c6c9b7 100644
--- a/tests/libqos/malloc.h
+++ b/tests/libqos/malloc.h
@@ -31,6 +31,7 @@ void alloc_uninit(QGuestAllocator *allocator);
 /* Always returns page aligned values */
 uint64_t guest_alloc(QGuestAllocator *allocator, size_t size);
 void guest_free(QGuestAllocator *allocator, uint64_t addr);
+void migrate_allocator(QGuestAllocator *src, QGuestAllocator *dst);
 
 QGuestAllocator *alloc_init(uint64_t start, uint64_t end);
 QGuestAllocator *alloc_init_flags(QAllocOpts flags,
-- 
1.9.3

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

* [Qemu-devel] [PATCH 2/5] ich9/ahci: Enable Migration
  2015-02-24 17:38 [Qemu-devel] [PATCH 0/5] ahci: enable migration John Snow
  2015-02-24 17:38 ` [Qemu-devel] [PATCH 1/5] libqos: Add migration helpers John Snow
@ 2015-02-24 17:38 ` John Snow
  2015-02-24 17:38 ` [Qemu-devel] [PATCH 3/5] qtest/ahci: Add migration test John Snow
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: John Snow @ 2015-02-24 17:38 UTC (permalink / raw)
  To: qemu-devel
  Cc: kwolf, marc.mari.barcelo, mst, armbru, stefanha, pbonzini,
	John Snow

Lift the flag preventing the migration of the ICH9/AHCI devices.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 hw/ide/ahci.c | 1 -
 hw/ide/ich.c  | 1 -
 2 files changed, 2 deletions(-)

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index e1ae36f..66f47f2 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -1421,7 +1421,6 @@ typedef struct SysbusAHCIState {
 
 static const VMStateDescription vmstate_sysbus_ahci = {
     .name = "sysbus-ahci",
-    .unmigratable = 1, /* Still buggy under I/O load */
     .fields = (VMStateField[]) {
         VMSTATE_AHCI(ahci, SysbusAHCIState),
         VMSTATE_END_OF_LIST()
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index fb1d095..97c7af2 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -82,7 +82,6 @@
 
 static const VMStateDescription vmstate_ich9_ahci = {
     .name = "ich9_ahci",
-    .unmigratable = 1, /* Still buggy under I/O load */
     .version_id = 1,
     .fields = (VMStateField[]) {
         VMSTATE_PCI_DEVICE(parent_obj, AHCIPCIState),
-- 
1.9.3

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

* [Qemu-devel] [PATCH 3/5] qtest/ahci: Add migration test
  2015-02-24 17:38 [Qemu-devel] [PATCH 0/5] ahci: enable migration John Snow
  2015-02-24 17:38 ` [Qemu-devel] [PATCH 1/5] libqos: Add migration helpers John Snow
  2015-02-24 17:38 ` [Qemu-devel] [PATCH 2/5] ich9/ahci: Enable Migration John Snow
@ 2015-02-24 17:38 ` John Snow
  2015-02-24 17:38 ` [Qemu-devel] [PATCH 4/5] qtest/ahci: add migrate dma test John Snow
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: John Snow @ 2015-02-24 17:38 UTC (permalink / raw)
  To: qemu-devel
  Cc: kwolf, marc.mari.barcelo, mst, armbru, stefanha, pbonzini,
	John Snow

Notes:

 * The migration is performed on QOSState objects.

 * The migration is performed in such a way that it does not assume
   consistency between the allocators attached to each. That is to say,
   you can use each QOSState object completely independently and then at
   an arbitrary point decide to migrate, and the destination object will
   now be consistent with the memory within the source guest. The source
   object that was migrated from will have a completely blank allocator.

ahci-test.c:
 - verify_state is added
 - ahci_migrate is added as a frontend to migrate
 - test_migrate_sanity test case is added.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 tests/ahci-test.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 85 insertions(+)

diff --git a/tests/ahci-test.c b/tests/ahci-test.c
index f194cbc..4bd81fa 100644
--- a/tests/ahci-test.c
+++ b/tests/ahci-test.c
@@ -71,6 +71,66 @@ static void string_bswap16(uint16_t *s, size_t bytes)
     }
 }
 
+/**
+ * Verify that the transfer did not corrupt our state at all.
+ */
+static void verify_state(AHCIQState *ahci)
+{
+    int i,j;
+    uint32_t ahci_fingerprint;
+    uint64_t hba_base;
+    AHCICommandHeader cmd;
+
+    ahci_fingerprint = qpci_config_readl(ahci->dev, PCI_VENDOR_ID);
+    g_assert_cmphex(ahci_fingerprint, ==, ahci->fingerprint);
+
+    /* If we haven't initialized, this is as much as can be validated. */
+    if (!ahci->hba_base) {
+        return;
+    }
+
+    hba_base = qpci_config_readl(ahci->dev, PCI_BASE_ADDRESS_5);
+    g_assert_cmphex(hba_base, ==, (uint64_t)ahci->hba_base);
+
+    g_assert_cmphex(ahci_rreg(ahci, AHCI_CAP), ==, ahci->cap);
+    g_assert_cmphex(ahci_rreg(ahci, AHCI_CAP2), ==, ahci->cap2);
+
+    for (i = 0; i < 32; i++) {
+        g_assert_cmphex(ahci_px_rreg(ahci, i, AHCI_PX_FB), ==,
+                        ahci->port[i].fb);
+        g_assert_cmphex(ahci_px_rreg(ahci, i, AHCI_PX_CLB), ==,
+                        ahci->port[i].clb);
+        for (j = 0; j < 32; j++) {
+            ahci_get_command_header(ahci, i, j, &cmd);
+            g_assert_cmphex(cmd.prdtl, ==, ahci->port[i].prdtl[j]);
+            g_assert_cmphex(cmd.ctba, ==, ahci->port[i].ctba[j]);
+        }
+    }
+}
+
+static void ahci_migrate(AHCIQState *from, AHCIQState *to)
+{
+    QOSState *tmp = to->parent;
+    QPCIDevice *dev = to->dev;
+
+    migrate(from->parent, to->parent);
+
+    /* We'd like for the AHCIState objects to still point
+     * to information specific to its specific parent
+     * instance, but otherwise just inherit the new data. */
+    memcpy(to, from, sizeof(AHCIQState));
+    to->parent = tmp;
+    to->dev = dev;
+
+    tmp = from->parent;
+    dev = from->dev;
+    memset(from, 0x00, sizeof(AHCIQState));
+    from->parent = tmp;
+    from->dev = dev;
+
+    verify_state(to);
+}
+
 /*** Test Setup & Teardown ***/
 
 /**
@@ -1002,6 +1062,29 @@ static void test_flush_retry(void)
     ahci_shutdown(ahci);
 }
 
+/**
+ * Basic sanity test to boot a machine, find an AHCI device, and shutdown.
+ */
+static void test_migrate_sanity(void)
+{
+    AHCIQState *src, *dst;
+
+    src = ahci_boot("-m 1024 -M q35 "
+                    "-hda %s ", tmp_path);
+    dst = ahci_boot("-m 1024 -M q35 "
+                    "-hda %s "
+                    "-incoming tcp:127.0.0.1:1234", tmp_path);
+
+    ahci_migrate(src, dst);
+    /* context is now implicitly 'dst' */
+
+    set_context(src->parent);
+    ahci_shutdown(src);
+
+    set_context(dst->parent);
+    ahci_shutdown(dst);
+}
+
 /******************************************************************************/
 /* AHCI I/O Test Matrix Definitions                                           */
 
@@ -1250,6 +1333,8 @@ int main(int argc, char **argv)
     qtest_add_func("/ahci/flush/simple", test_flush);
     qtest_add_func("/ahci/flush/retry", test_flush_retry);
 
+    qtest_add_func("/ahci/migrate/sanity", test_migrate_sanity);
+
     ret = g_test_run();
 
     /* Cleanup */
-- 
1.9.3

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

* [Qemu-devel] [PATCH 4/5] qtest/ahci: add migrate dma test
  2015-02-24 17:38 [Qemu-devel] [PATCH 0/5] ahci: enable migration John Snow
                   ` (2 preceding siblings ...)
  2015-02-24 17:38 ` [Qemu-devel] [PATCH 3/5] qtest/ahci: Add migration test John Snow
@ 2015-02-24 17:38 ` John Snow
  2015-02-24 17:38 ` [Qemu-devel] [PATCH 5/5] qtest/ahci: add flush migrate test John Snow
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: John Snow @ 2015-02-24 17:38 UTC (permalink / raw)
  To: qemu-devel
  Cc: kwolf, marc.mari.barcelo, mst, armbru, stefanha, pbonzini,
	John Snow

Write to one guest, migrate, and then read from the other.
adjust ahci_io to clear any buffers it creates, so that we
can use ahci_io safely on both guests knowing we are using
empty buffers and not accidentally re-using data.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 tests/ahci-test.c   | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/libqos/ahci.c |  1 +
 2 files changed, 47 insertions(+)

diff --git a/tests/ahci-test.c b/tests/ahci-test.c
index 4bd81fa..ec3e49e 100644
--- a/tests/ahci-test.c
+++ b/tests/ahci-test.c
@@ -1085,6 +1085,51 @@ static void test_migrate_sanity(void)
     ahci_shutdown(dst);
 }
 
+/**
+ * DMA Migration test: Write a pattern, migrate, then read.
+ */
+static void test_migrate_dma(void)
+{
+    AHCIQState *src, *dst;
+    uint8_t px;
+    size_t bufsize = 4096;
+    unsigned char *tx = g_malloc(bufsize);
+    unsigned char *rx = g_malloc0(bufsize);
+    unsigned i;
+
+    src = ahci_boot_and_enable("-m 1024 -M q35 "
+                               "-hda %s ", tmp_path);
+    dst = ahci_boot("-m 1024 -M q35 "
+                    "-hda %s "
+                    "-incoming tcp:127.0.0.1:1234", tmp_path);
+
+    set_context(src->parent);
+
+    /* initialize */
+    px = ahci_port_select(src);
+    ahci_port_clear(src, px);
+
+    /* create pattern */
+    for (i = 0; i < bufsize; i++) {
+        tx[i] = (bufsize - i);
+    }
+
+    /* Write, migrate, then read. */
+    ahci_io(src, px, CMD_WRITE_DMA, tx, bufsize, 0);
+    ahci_migrate(src, dst);
+    ahci_io(dst, px, CMD_READ_DMA, rx, bufsize, 0);
+
+    /* Verify pattern */
+    g_assert_cmphex(memcmp(tx, rx, bufsize), ==, 0);
+
+    set_context(src->parent);
+    ahci_shutdown(src);
+    set_context(dst->parent);
+    ahci_shutdown(dst);
+    g_free(rx);
+    g_free(tx);
+}
+
 /******************************************************************************/
 /* AHCI I/O Test Matrix Definitions                                           */
 
@@ -1334,6 +1379,7 @@ int main(int argc, char **argv)
     qtest_add_func("/ahci/flush/retry", test_flush_retry);
 
     qtest_add_func("/ahci/migrate/sanity", test_migrate_sanity);
+    qtest_add_func("/ahci/migrate/dma", test_migrate_dma);
 
     ret = g_test_run();
 
diff --git a/tests/libqos/ahci.c b/tests/libqos/ahci.c
index 8bb9e3e..4091fdd 100644
--- a/tests/libqos/ahci.c
+++ b/tests/libqos/ahci.c
@@ -623,6 +623,7 @@ void ahci_io(AHCIQState *ahci, uint8_t port, uint8_t ide_cmd,
     g_assert(props);
     ptr = ahci_alloc(ahci, bufsize);
     g_assert(ptr);
+    qmemset(ptr, 0x00, bufsize);
 
     if (props->write) {
         memwrite(ptr, buffer, bufsize);
-- 
1.9.3

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

* [Qemu-devel] [PATCH 5/5] qtest/ahci: add flush migrate test
  2015-02-24 17:38 [Qemu-devel] [PATCH 0/5] ahci: enable migration John Snow
                   ` (3 preceding siblings ...)
  2015-02-24 17:38 ` [Qemu-devel] [PATCH 4/5] qtest/ahci: add migrate dma test John Snow
@ 2015-02-24 17:38 ` John Snow
  2015-02-24 17:55 ` [Qemu-devel] [PATCH 0/5] ahci: enable migration John Snow
  2015-02-26 13:23 ` Paolo Bonzini
  6 siblings, 0 replies; 9+ messages in thread
From: John Snow @ 2015-02-24 17:38 UTC (permalink / raw)
  To: qemu-devel
  Cc: kwolf, marc.mari.barcelo, mst, armbru, stefanha, pbonzini,
	John Snow

Use blkdebug to inject an error on first flush, then attempt to flush
on the first guest. When the error halts the VM, migrate to the
second VM, and attempt to resume the command.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 tests/ahci-test.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 52 insertions(+), 1 deletion(-)

diff --git a/tests/ahci-test.c b/tests/ahci-test.c
index ec3e49e..1e568f5 100644
--- a/tests/ahci-test.c
+++ b/tests/ahci-test.c
@@ -1043,7 +1043,7 @@ static void test_flush_retry(void)
                                 debug_path,
                                 tmp_path);
 
-    /* Issue Flush Command */
+    /* Issue Flush Command and wait for error */
     port = ahci_port_select(ahci);
     ahci_port_clear(ahci, port);
     cmd = ahci_command_create(CMD_FLUSH_CACHE);
@@ -1130,6 +1130,56 @@ static void test_migrate_dma(void)
     g_free(tx);
 }
 
+/**
+ * Migration test: Try to flush, migrate, then resume.
+ */
+static void test_flush_migrate(void)
+{
+    AHCIQState *src, *dst;
+    AHCICommand *cmd;
+    uint8_t px;
+    const char *s;
+
+    prepare_blkdebug_script(debug_path, "flush_to_disk");
+
+    src = ahci_boot_and_enable("-drive file=blkdebug:%s:%s,if=none,id=drive0,"
+                               "cache=writeback,rerror=stop,werror=stop "
+                               "-M q35 "
+                               "-device ide-hd,drive=drive0 ",
+                               debug_path, tmp_path);
+    dst = ahci_boot("-drive file=blkdebug:%s:%s,if=none,id=drive0,"
+                    "cache=writeback,rerror=stop,werror=stop "
+                    "-M q35 "
+                    "-device ide-hd,drive=drive0 "
+                    "-incoming tcp:127.0.0.1:1234", debug_path, tmp_path);
+
+    set_context(src->parent);
+
+    /* Issue Flush Command */
+    px = ahci_port_select(src);
+    ahci_port_clear(src, px);
+    cmd = ahci_command_create(CMD_FLUSH_CACHE);
+    ahci_command_commit(src, cmd, px);
+    ahci_command_issue_async(src, cmd);
+    qmp_eventwait("STOP");
+
+    /* Migrate over */
+    ahci_migrate(src, dst);
+    set_context(dst->parent);
+    verify_state(dst);
+
+    /* Complete the command */
+    s = "{'execute':'cont' }";
+    qmp_async(s);
+    qmp_eventwait("RESUME");
+    ahci_command_wait(dst, cmd);
+    ahci_command_verify(dst, cmd);
+
+    ahci_command_free(cmd);
+    ahci_shutdown(src);
+    ahci_shutdown(dst);
+}
+
 /******************************************************************************/
 /* AHCI I/O Test Matrix Definitions                                           */
 
@@ -1377,6 +1427,7 @@ int main(int argc, char **argv)
 
     qtest_add_func("/ahci/flush/simple", test_flush);
     qtest_add_func("/ahci/flush/retry", test_flush_retry);
+    qtest_add_func("/ahci/flush/migrate", test_flush_migrate);
 
     qtest_add_func("/ahci/migrate/sanity", test_migrate_sanity);
     qtest_add_func("/ahci/migrate/dma", test_migrate_dma);
-- 
1.9.3

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

* Re: [Qemu-devel] [PATCH 0/5] ahci: enable migration
  2015-02-24 17:38 [Qemu-devel] [PATCH 0/5] ahci: enable migration John Snow
                   ` (4 preceding siblings ...)
  2015-02-24 17:38 ` [Qemu-devel] [PATCH 5/5] qtest/ahci: add flush migrate test John Snow
@ 2015-02-24 17:55 ` John Snow
  2015-02-26 13:23 ` Paolo Bonzini
  6 siblings, 0 replies; 9+ messages in thread
From: John Snow @ 2015-02-24 17:55 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, marc.mari.barcelo, mst, armbru, stefanha, pbonzini



On 02/24/2015 12:38 PM, John Snow wrote:
> The day we all feared is here, and I am proposing we allow the
> migration of the AHCI device. The series that precedes this
> which fixes AHCI migration has improved the stability of the
> device and as this test series proves, is stable.
>
> I am justifying this checkin based on a series of ping-pong
> migration tests I ran under heavy load (using google's stressapptest)
> and saw over 300 successful migrations without a single failure.
>
> This series does a few things:
> (1) Add migration facilities to libqos
> (2) Enable AHCI and ICH9 migration
> (3) Add a series of migration tests to ahci-test
>
> This patch has several dependencies:
>
> (1) stefanha/block

Update 2015-02-24: you can just base off of master now.

> (2) [PATCH v4 00/17] ide: rerror/werror migration fixes for IDE/ISA and AHCI
> (3) [PATCH 0/8] ahci: add more IO tests
> (4) [PATCH 0/6] ahci: rerror/werror=stop resume tests
>
> 1, 3 and 4 are ahci-test framework dependencies, but 2 actually allows the
> AHCI migration to become stable.
>
> John Snow (5):
>    libqos: Add migration helpers
>    ich9/ahci: Enable Migration
>    qtest/ahci: Add migration test
>    qtest/ahci: add migrate dma test
>    qtest/ahci: add flush migrate test
>
>   hw/ide/ahci.c         |   1 -
>   hw/ide/ich.c          |   1 -
>   tests/ahci-test.c     | 184 +++++++++++++++++++++++++++++++++++++++++++++++++-
>   tests/libqos/ahci.c   |   1 +
>   tests/libqos/libqos.c |  75 ++++++++++++++++++++
>   tests/libqos/libqos.h |   2 +
>   tests/libqos/malloc.c |  74 +++++++++++++++-----
>   tests/libqos/malloc.h |   1 +
>   8 files changed, 319 insertions(+), 20 deletions(-)
>

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

* Re: [Qemu-devel] [PATCH 0/5] ahci: enable migration
  2015-02-24 17:38 [Qemu-devel] [PATCH 0/5] ahci: enable migration John Snow
                   ` (5 preceding siblings ...)
  2015-02-24 17:55 ` [Qemu-devel] [PATCH 0/5] ahci: enable migration John Snow
@ 2015-02-26 13:23 ` Paolo Bonzini
  2015-02-26 18:20   ` John Snow
  6 siblings, 1 reply; 9+ messages in thread
From: Paolo Bonzini @ 2015-02-26 13:23 UTC (permalink / raw)
  To: John Snow, qemu-devel; +Cc: kwolf, marc.mari.barcelo, armbru, stefanha, mst



On 24/02/2015 18:38, John Snow wrote:
> The day we all feared is here, and I am proposing we allow the
> migration of the AHCI device. The series that precedes this
> which fixes AHCI migration has improved the stability of the
> device and as this test series proves, is stable.
> 
> I am justifying this checkin based on a series of ping-pong
> migration tests I ran under heavy load (using google's stressapptest)
> and saw over 300 successful migrations without a single failure.
> 
> This series does a few things:
> (1) Add migration facilities to libqos
> (2) Enable AHCI and ICH9 migration
> (3) Add a series of migration tests to ahci-test
> 
> This patch has several dependencies:
> 
> (1) stefanha/block
> (2) [PATCH v4 00/17] ide: rerror/werror migration fixes for IDE/ISA and AHCI
> (3) [PATCH 0/8] ahci: add more IO tests
> (4) [PATCH 0/6] ahci: rerror/werror=stop resume tests
> 
> 1, 3 and 4 are ahci-test framework dependencies, but 2 actually allows the
> AHCI migration to become stable.

Does rerror/werror=stop work even for queued DMA reads/writes (I didn't
try doing that, but I never even checked whether it just worked)?

Paolo

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

* Re: [Qemu-devel] [PATCH 0/5] ahci: enable migration
  2015-02-26 13:23 ` Paolo Bonzini
@ 2015-02-26 18:20   ` John Snow
  0 siblings, 0 replies; 9+ messages in thread
From: John Snow @ 2015-02-26 18:20 UTC (permalink / raw)
  To: Paolo Bonzini, qemu-devel; +Cc: kwolf, marc.mari.barcelo, armbru, stefanha, mst



On 02/26/2015 08:23 AM, Paolo Bonzini wrote:
>
>
> On 24/02/2015 18:38, John Snow wrote:
>> The day we all feared is here, and I am proposing we allow the
>> migration of the AHCI device. The series that precedes this
>> which fixes AHCI migration has improved the stability of the
>> device and as this test series proves, is stable.
>>
>> I am justifying this checkin based on a series of ping-pong
>> migration tests I ran under heavy load (using google's stressapptest)
>> and saw over 300 successful migrations without a single failure.
>>
>> This series does a few things:
>> (1) Add migration facilities to libqos
>> (2) Enable AHCI and ICH9 migration
>> (3) Add a series of migration tests to ahci-test
>>
>> This patch has several dependencies:
>>
>> (1) stefanha/block
>> (2) [PATCH v4 00/17] ide: rerror/werror migration fixes for IDE/ISA and AHCI
>> (3) [PATCH 0/8] ahci: add more IO tests
>> (4) [PATCH 0/6] ahci: rerror/werror=stop resume tests
>>
>> 1, 3 and 4 are ahci-test framework dependencies, but 2 actually allows the
>> AHCI migration to become stable.
>
> Does rerror/werror=stop work even for queued DMA reads/writes (I didn't
> try doing that, but I never even checked whether it just worked)?
>
> Paolo
>

One more test case, coming up!

--js

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

end of thread, other threads:[~2015-02-26 18:20 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-02-24 17:38 [Qemu-devel] [PATCH 0/5] ahci: enable migration John Snow
2015-02-24 17:38 ` [Qemu-devel] [PATCH 1/5] libqos: Add migration helpers John Snow
2015-02-24 17:38 ` [Qemu-devel] [PATCH 2/5] ich9/ahci: Enable Migration John Snow
2015-02-24 17:38 ` [Qemu-devel] [PATCH 3/5] qtest/ahci: Add migration test John Snow
2015-02-24 17:38 ` [Qemu-devel] [PATCH 4/5] qtest/ahci: add migrate dma test John Snow
2015-02-24 17:38 ` [Qemu-devel] [PATCH 5/5] qtest/ahci: add flush migrate test John Snow
2015-02-24 17:55 ` [Qemu-devel] [PATCH 0/5] ahci: enable migration John Snow
2015-02-26 13:23 ` Paolo Bonzini
2015-02-26 18:20   ` John Snow

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).