[Qemu-devel] [PATCH 18/71] tests/libqos: embed allocators instead of malloc-ing them

Paolo Bonzini posted 71 patches 7 years, 2 months ago
[Qemu-devel] [PATCH 18/71] tests/libqos: embed allocators instead of malloc-ing them
Posted by Paolo Bonzini 7 years, 2 months ago
qgraph will embed these objects instead of allocating them in a separate
object.  Expose a new API "generic_alloc_init" and "generic_alloc_destroy"
for that, and rename the existing API with s/init/new/ and s/uninit/free/.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 tests/ahci-test.c             |  6 ++--
 tests/e1000e-test.c           | 22 +++++++-------
 tests/ide-test.c              | 17 +++++------
 tests/libqos/libqos-pc.c      |  3 +-
 tests/libqos/libqos-spapr.c   |  3 +-
 tests/libqos/libqos.c         | 13 ++++----
 tests/libqos/libqos.h         | 11 ++++---
 tests/libqos/malloc-generic.c | 21 ++-----------
 tests/libqos/malloc-generic.h |  7 ++---
 tests/libqos/malloc-pc.c      | 18 ++---------
 tests/libqos/malloc-pc.h      |  4 +--
 tests/libqos/malloc-spapr.c   | 19 ++----------
 tests/libqos/malloc-spapr.h   |  4 +--
 tests/libqos/malloc.c         | 41 ++++---------------------
 tests/libqos/malloc.h         | 21 +++++++++----
 tests/rtas-test.c             |  2 +-
 tests/vhost-user-test.c       | 10 +++----
 tests/virtio-9p-test.c        | 12 ++++----
 tests/virtio-blk-test.c       | 69 ++++++++++++++++++++++---------------------
 tests/virtio-net-test.c       | 10 +++----
 tests/virtio-scsi-test.c      | 14 ++++-----
 21 files changed, 123 insertions(+), 204 deletions(-)

diff --git a/tests/ahci-test.c b/tests/ahci-test.c
index 5dd380e..9f07e6f 100644
--- a/tests/ahci-test.c
+++ b/tests/ahci-test.c
@@ -162,7 +162,7 @@ static AHCIQState *ahci_vboot(const char *cli, va_list ap)
     s = g_new0(AHCIQState, 1);
     s->parent = qtest_pc_vboot(cli, ap);
     global_qtest = s->parent->qts;
-    alloc_set_flags(s->parent->alloc, ALLOC_LEAK_ASSERT);
+    alloc_set_flags(&s->parent->alloc, ALLOC_LEAK_ASSERT);
 
     /* Verify that we have an AHCI device present. */
     s->dev = get_ahci_device(s->parent->qts, &s->fingerprint);
@@ -1039,7 +1039,7 @@ static void test_dma_fragmented(void)
     generate_pattern(tx, bufsize, AHCI_SECTOR_SIZE);
 
     /* Create a DMA buffer in guest memory, and write our pattern to it. */
-    ptr = guest_alloc(ahci->parent->alloc, bufsize);
+    ptr = guest_alloc(&ahci->parent->alloc, bufsize);
     g_assert(ptr);
     bufwrite(ptr, tx, bufsize);
 
@@ -1059,7 +1059,7 @@ static void test_dma_fragmented(void)
 
     /* Read back the guest's receive buffer into local memory */
     bufread(ptr, rx, bufsize);
-    guest_free(ahci->parent->alloc, ptr);
+    guest_free(&ahci->parent->alloc, ptr);
 
     g_assert_cmphex(memcmp(tx, rx, bufsize), ==, 0);
 
diff --git a/tests/e1000e-test.c b/tests/e1000e-test.c
index 5525589..17a12b8 100644
--- a/tests/e1000e-test.c
+++ b/tests/e1000e-test.c
@@ -94,7 +94,7 @@ typedef struct e1000e_device {
 } e1000e_device;
 
 static int test_sockets[2];
-static QGuestAllocator *test_alloc;
+static QGuestAllocator test_alloc;
 static QPCIBus *test_bus;
 
 static void e1000e_pci_foreach_callback(QPCIDevice *dev, int devfn, void *data)
@@ -165,7 +165,7 @@ static void e1000e_device_init(QPCIBus *bus, e1000e_device *d)
         val | E1000E_CTRL_EXT_DRV_LOAD | E1000E_CTRL_EXT_TXLSFLOW);
 
     /* Allocate and setup TX ring */
-    d->tx_ring = guest_alloc(test_alloc, E1000E_RING_LEN);
+    d->tx_ring = guest_alloc(&test_alloc, E1000E_RING_LEN);
     g_assert(d->tx_ring != 0);
 
     e1000e_macreg_write(d, E1000E_TDBAL, (uint32_t) d->tx_ring);
@@ -178,7 +178,7 @@ static void e1000e_device_init(QPCIBus *bus, e1000e_device *d)
     e1000e_macreg_write(d, E1000E_TCTL, E1000E_TCTL_EN);
 
     /* Allocate and setup RX ring */
-    d->rx_ring = guest_alloc(test_alloc, E1000E_RING_LEN);
+    d->rx_ring = guest_alloc(&test_alloc, E1000E_RING_LEN);
     g_assert(d->rx_ring != 0);
 
     e1000e_macreg_write(d, E1000E_RDBAL, (uint32_t)d->rx_ring);
@@ -268,7 +268,7 @@ static void e1000e_send_verify(e1000e_device *d)
     uint32_t recv_len;
 
     /* Prepare test data buffer */
-    uint64_t data = guest_alloc(test_alloc, data_len);
+    uint64_t data = guest_alloc(&test_alloc, data_len);
     memwrite(data, "TEST", 5);
 
     /* Prepare TX descriptor */
@@ -296,7 +296,7 @@ static void e1000e_send_verify(e1000e_device *d)
     g_assert_cmpstr(buffer, == , "TEST");
 
     /* Free test data buffer */
-    guest_free(test_alloc, data);
+    guest_free(&test_alloc, data);
 }
 
 static void e1000e_receive_verify(e1000e_device *d)
@@ -348,7 +348,7 @@ static void e1000e_receive_verify(e1000e_device *d)
     g_assert_cmpint(ret, == , sizeof(test) + sizeof(len));
 
     /* Prepare test data buffer */
-    uint64_t data = guest_alloc(test_alloc, data_len);
+    uint64_t data = guest_alloc(&test_alloc, data_len);
 
     /* Prepare RX descriptor */
     memset(&descr, 0, sizeof(descr));
@@ -369,7 +369,7 @@ static void e1000e_receive_verify(e1000e_device *d)
     g_assert_cmpstr(buffer, == , "TEST");
 
     /* Free test data buffer */
-    guest_free(test_alloc, data);
+    guest_free(&test_alloc, data);
 }
 
 static void e1000e_device_clear(QPCIBus *bus, e1000e_device *d)
@@ -392,10 +392,8 @@ static void data_test_init(e1000e_device *d)
     qtest_start(cmdline);
     g_free(cmdline);
 
-    test_alloc = pc_alloc_init(global_qtest);
-    g_assert_nonnull(test_alloc);
-
-    test_bus = qpci_new_pc(global_qtest, test_alloc);
+    pc_alloc_init(&test_alloc, global_qtest, 0);
+    test_bus = qpci_new_pc(global_qtest, &test_alloc);
     g_assert_nonnull(test_bus);
 
     e1000e_device_init(test_bus, d);
@@ -405,7 +403,7 @@ static void data_test_clear(e1000e_device *d)
 {
     e1000e_device_clear(test_bus, d);
     close(test_sockets[0]);
-    pc_alloc_uninit(test_alloc);
+    alloc_destroy(&test_alloc);
     g_free(d->pci_dev);
     qpci_free_pc(test_bus);
     qtest_end();
diff --git a/tests/ide-test.c b/tests/ide-test.c
index 8f5adae..ef776fc 100644
--- a/tests/ide-test.c
+++ b/tests/ide-test.c
@@ -120,7 +120,7 @@ enum {
 #define assert_bit_clear(data, mask) g_assert_cmphex((data) & (mask), ==, 0)
 
 static QPCIBus *pcibus = NULL;
-static QGuestAllocator *guest_malloc;
+static QGuestAllocator guest_malloc;
 
 static char tmp_path[] = "/tmp/qtest.XXXXXX";
 static char debug_path[] = "/tmp/qtest-blkdebug.XXXXXX";
@@ -135,7 +135,7 @@ static void ide_test_start(const char *cmdline_fmt, ...)
     va_end(ap);
 
     qtest_start(cmdline);
-    guest_malloc = pc_alloc_init(global_qtest);
+    pc_alloc_init(&guest_malloc, global_qtest, 0);
 
     g_free(cmdline);
 }
@@ -146,8 +146,7 @@ static void ide_test_quit(void)
         qpci_free_pc(pcibus);
         pcibus = NULL;
     }
-    pc_alloc_uninit(guest_malloc);
-    guest_malloc = NULL;
+    alloc_destroy(&guest_malloc);
     qtest_end();
 }
 
@@ -246,7 +245,7 @@ static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,
 
     /* Setup PRDT */
     len = sizeof(*prdt) * prdt_entries;
-    guest_prdt = guest_alloc(guest_malloc, len);
+    guest_prdt = guest_alloc(&guest_malloc, len);
     memwrite(guest_prdt, prdt, len);
     qpci_io_writel(dev, bmdma_bar, bmreg_prdt, guest_prdt);
 
@@ -311,7 +310,7 @@ static void test_bmdma_simple_rw(void)
     uint8_t *buf;
     uint8_t *cmpbuf;
     size_t len = 512;
-    uintptr_t guest_buf = guest_alloc(guest_malloc, len);
+    uintptr_t guest_buf = guest_alloc(&guest_malloc, len);
 
     PrdtEntry prdt[] = {
         {
@@ -381,7 +380,7 @@ static void test_bmdma_trim(void)
     const uint64_t bad_range = trim_range_le(TEST_IMAGE_SIZE / 512 - 1, 2);
     size_t len = 512;
     uint8_t *buf;
-    uintptr_t guest_buf = guest_alloc(guest_malloc, len);
+    uintptr_t guest_buf = guest_alloc(&guest_malloc, len);
 
     PrdtEntry prdt[] = {
         {
@@ -625,7 +624,7 @@ static void make_dirty(uint8_t device)
 
     dev = get_pci_device(&bmdma_bar, &ide_bar);
 
-    guest_buf = guest_alloc(guest_malloc, len);
+    guest_buf = guest_alloc(&guest_malloc, len);
     buf = g_malloc(len);
     memset(buf, rand() % 255 + 1, len);
     g_assert(guest_buf);
@@ -986,7 +985,7 @@ static void test_cdrom_dma(void)
                    "-device ide-cd,drive=sr0,bus=ide.0", tmp_path);
     qtest_irq_intercept_in(global_qtest, "ioapic");
 
-    guest_buf = guest_alloc(guest_malloc, len);
+    guest_buf = guest_alloc(&guest_malloc, len);
     prdt[0].addr = cpu_to_le32(guest_buf);
     prdt[0].size = cpu_to_le32(len | PRDT_EOT);
 
diff --git a/tests/libqos/libqos-pc.c b/tests/libqos/libqos-pc.c
index 293f9b6..d04abc5 100644
--- a/tests/libqos/libqos-pc.c
+++ b/tests/libqos/libqos-pc.c
@@ -4,8 +4,7 @@
 #include "libqos/pci-pc.h"
 
 static QOSOps qos_ops = {
-    .init_allocator = pc_alloc_init_flags,
-    .uninit_allocator = pc_alloc_uninit,
+    .alloc_init = pc_alloc_init,
     .qpci_new = qpci_new_pc,
     .qpci_free = qpci_free_pc,
     .shutdown = qtest_pc_shutdown,
diff --git a/tests/libqos/libqos-spapr.c b/tests/libqos/libqos-spapr.c
index 64addfe..8766d54 100644
--- a/tests/libqos/libqos-spapr.c
+++ b/tests/libqos/libqos-spapr.c
@@ -4,8 +4,7 @@
 #include "libqos/pci-spapr.h"
 
 static QOSOps qos_ops = {
-    .init_allocator = spapr_alloc_init_flags,
-    .uninit_allocator = spapr_alloc_uninit,
+    .alloc_init = spapr_alloc_init,
     .qpci_new = qpci_new_spapr,
     .qpci_free = qpci_free_spapr,
     .shutdown = qtest_spapr_shutdown,
diff --git a/tests/libqos/libqos.c b/tests/libqos/libqos.c
index 6c91371..636a111 100644
--- a/tests/libqos/libqos.c
+++ b/tests/libqos/libqos.c
@@ -24,8 +24,8 @@ QOSState *qtest_vboot(QOSOps *ops, const char *cmdline_fmt, va_list ap)
     qs->qts = qtest_init(cmdline);
     qs->ops = ops;
     if (ops) {
-        qs->alloc = ops->init_allocator(qs->qts, ALLOC_NO_FLAGS);
-        qs->pcibus = ops->qpci_new(qs->qts, qs->alloc);
+        ops->alloc_init(&qs->alloc, qs->qts, ALLOC_NO_FLAGS);
+        qs->pcibus = ops->qpci_new(qs->qts, &qs->alloc);
     }
 
     g_free(cmdline);
@@ -58,11 +58,8 @@ void qtest_common_shutdown(QOSState *qs)
             qs->ops->qpci_free(qs->pcibus);
             qs->pcibus = NULL;
         }
-        if (qs->alloc && qs->ops->uninit_allocator) {
-            qs->ops->uninit_allocator(qs->alloc);
-            qs->alloc = NULL;
-        }
     }
+    alloc_destroy(&qs->alloc);
     qtest_quit(qs->qts);
     g_free(qs);
 }
@@ -116,7 +113,7 @@ void migrate(QOSState *from, QOSState *to, const char *uri)
 
     /* If we were running, we can wait for an event. */
     if (running) {
-        migrate_allocator(from->alloc, to->alloc);
+        migrate_allocator(&from->alloc, &to->alloc);
         set_context(to);
         qtest_qmp_eventwait(to->qts, "RESUME");
         return;
@@ -146,7 +143,7 @@ void migrate(QOSState *from, QOSState *to, const char *uri)
         g_assert_not_reached();
     }
 
-    migrate_allocator(from->alloc, to->alloc);
+    migrate_allocator(&from->alloc, &to->alloc);
     set_context(to);
 }
 
diff --git a/tests/libqos/libqos.h b/tests/libqos/libqos.h
index 1af6035..149b0be 100644
--- a/tests/libqos/libqos.h
+++ b/tests/libqos/libqos.h
@@ -3,13 +3,12 @@
 
 #include "libqtest.h"
 #include "libqos/pci.h"
-#include "libqos/malloc-pc.h"
+#include "libqos/malloc.h"
 
 typedef struct QOSState QOSState;
 
 typedef struct QOSOps {
-    QGuestAllocator *(*init_allocator)(QTestState *qts, QAllocOpts);
-    void (*uninit_allocator)(QGuestAllocator *);
+    void (*alloc_init)(QGuestAllocator *, QTestState *, QAllocOpts);
     QPCIBus *(*qpci_new)(QTestState *qts, QGuestAllocator *alloc);
     void (*qpci_free)(QPCIBus *bus);
     void (*shutdown)(QOSState *);
@@ -17,7 +16,7 @@ typedef struct QOSOps {
 
 struct QOSState {
     QTestState *qts;
-    QGuestAllocator *alloc;
+    QGuestAllocator alloc;
     QPCIBus *pcibus;
     QOSOps *ops;
 };
@@ -36,12 +35,12 @@ void generate_pattern(void *buffer, size_t len, size_t cycle_len);
 
 static inline uint64_t qmalloc(QOSState *q, size_t bytes)
 {
-    return guest_alloc(q->alloc, bytes);
+    return guest_alloc(&q->alloc, bytes);
 }
 
 static inline void qfree(QOSState *q, uint64_t addr)
 {
-    guest_free(q->alloc, addr);
+    guest_free(&q->alloc, addr);
 }
 
 #endif
diff --git a/tests/libqos/malloc-generic.c b/tests/libqos/malloc-generic.c
index 33ce90b..2873c67 100644
--- a/tests/libqos/malloc-generic.c
+++ b/tests/libqos/malloc-generic.c
@@ -15,25 +15,10 @@
  * Mostly for valgrind happiness, but it does offer
  * a chokepoint for debugging guest memory leaks, too.
  */
-void generic_alloc_uninit(QGuestAllocator *allocator)
+void generic_alloc_init(QGuestAllocator *s, uint64_t base_addr,
+			uint64_t size, uint32_t page_size)
 {
-    alloc_uninit(allocator);
-}
-
-QGuestAllocator *generic_alloc_init_flags(uint64_t base_addr, uint64_t size,
-                                        uint32_t page_size, QAllocOpts flags)
-{
-    QGuestAllocator *s;
     uint64_t start = base_addr + (1 << 20); /* Start at 1MB */
 
-    s = alloc_init_flags(flags, start, start + size);
-    alloc_set_page_size(s, page_size);
-
-    return s;
-}
-
-inline QGuestAllocator *generic_alloc_init(uint64_t base_addr, uint64_t size,
-                                                            uint32_t page_size)
-{
-    return generic_alloc_init_flags(base_addr, size, page_size, ALLOC_NO_FLAGS);
+    alloc_init(s, 0, start, start + size, page_size);
 }
diff --git a/tests/libqos/malloc-generic.h b/tests/libqos/malloc-generic.h
index 90104ec..40ea058 100644
--- a/tests/libqos/malloc-generic.h
+++ b/tests/libqos/malloc-generic.h
@@ -12,10 +12,7 @@
 
 #include "libqos/malloc.h"
 
-QGuestAllocator *generic_alloc_init(uint64_t base_addr, uint64_t size,
-                                                            uint32_t page_size);
-QGuestAllocator *generic_alloc_init_flags(uint64_t base_addr, uint64_t size,
-                                        uint32_t page_size, QAllocOpts flags);
-void generic_alloc_uninit(QGuestAllocator *allocator);
+void generic_alloc_init(QGuestAllocator *s, uint64_t base_addr, uint64_t size,
+                        uint32_t page_size);
 
 #endif
diff --git a/tests/libqos/malloc-pc.c b/tests/libqos/malloc-pc.c
index b83cb8f..9aff807 100644
--- a/tests/libqos/malloc-pc.c
+++ b/tests/libqos/malloc-pc.c
@@ -24,28 +24,14 @@
  * Mostly for valgrind happiness, but it does offer
  * a chokepoint for debugging guest memory leaks, too.
  */
-void pc_alloc_uninit(QGuestAllocator *allocator)
+void pc_alloc_init(QGuestAllocator *s, QTestState *qts, QAllocOpts flags)
 {
-    alloc_uninit(allocator);
-}
-
-QGuestAllocator *pc_alloc_init_flags(QTestState *qts, QAllocOpts flags)
-{
-    QGuestAllocator *s;
     uint64_t ram_size;
     QFWCFG *fw_cfg = pc_fw_cfg_init(qts);
 
     ram_size = qfw_cfg_get_u64(fw_cfg, FW_CFG_RAM_SIZE);
-    s = alloc_init_flags(flags, 1 << 20, MIN(ram_size, 0xE0000000));
-    alloc_set_page_size(s, PAGE_SIZE);
+    alloc_init(s, flags, 1 << 20, MIN(ram_size, 0xE0000000), PAGE_SIZE);
 
     /* clean-up */
     g_free(fw_cfg);
-
-    return s;
-}
-
-inline QGuestAllocator *pc_alloc_init(QTestState *qts)
-{
-    return pc_alloc_init_flags(qts, ALLOC_NO_FLAGS);
 }
diff --git a/tests/libqos/malloc-pc.h b/tests/libqos/malloc-pc.h
index 10f3da6..21e75ae 100644
--- a/tests/libqos/malloc-pc.h
+++ b/tests/libqos/malloc-pc.h
@@ -15,8 +15,6 @@
 
 #include "libqos/malloc.h"
 
-QGuestAllocator *pc_alloc_init(QTestState *qts);
-QGuestAllocator *pc_alloc_init_flags(QTestState *qts, QAllocOpts flags);
-void pc_alloc_uninit(QGuestAllocator *allocator);
+void pc_alloc_init(QGuestAllocator *s, QTestState *qts, QAllocOpts flags);
 
 #endif
diff --git a/tests/libqos/malloc-spapr.c b/tests/libqos/malloc-spapr.c
index 1c359ce..2a6b7e3 100644
--- a/tests/libqos/malloc-spapr.c
+++ b/tests/libqos/malloc-spapr.c
@@ -17,22 +17,7 @@
  */
 #define SPAPR_MIN_SIZE 0x10000000
 
-void spapr_alloc_uninit(QGuestAllocator *allocator)
+void spapr_alloc_init(QGuestAllocator *s, QTestState *qts, QAllocOpts flags)
 {
-    alloc_uninit(allocator);
-}
-
-QGuestAllocator *spapr_alloc_init_flags(QTestState *qts, QAllocOpts flags)
-{
-    QGuestAllocator *s;
-
-    s = alloc_init_flags(flags, 1 << 20, SPAPR_MIN_SIZE);
-    alloc_set_page_size(s, PAGE_SIZE);
-
-    return s;
-}
-
-QGuestAllocator *spapr_alloc_init(void)
-{
-    return spapr_alloc_init_flags(NULL, ALLOC_NO_FLAGS);
+    alloc_init(s, flags, 1 << 20, SPAPR_MIN_SIZE, PAGE_SIZE);
 }
diff --git a/tests/libqos/malloc-spapr.h b/tests/libqos/malloc-spapr.h
index 52a9346..e5fe9bf 100644
--- a/tests/libqos/malloc-spapr.h
+++ b/tests/libqos/malloc-spapr.h
@@ -10,8 +10,6 @@
 
 #include "libqos/malloc.h"
 
-QGuestAllocator *spapr_alloc_init(void);
-QGuestAllocator *spapr_alloc_init_flags(QTestState *qts, QAllocOpts flags);
-void spapr_alloc_uninit(QGuestAllocator *allocator);
+void spapr_alloc_init(QGuestAllocator *s, QTestState *qts, QAllocOpts flags);
 
 #endif
diff --git a/tests/libqos/malloc.c b/tests/libqos/malloc.c
index ac05874..f1412cf 100644
--- a/tests/libqos/malloc.c
+++ b/tests/libqos/malloc.c
@@ -15,24 +15,12 @@
 #include "qemu-common.h"
 #include "qemu/host-utils.h"
 
-typedef QTAILQ_HEAD(MemList, MemBlock) MemList;
-
 typedef struct MemBlock {
     QTAILQ_ENTRY(MemBlock) MLIST_ENTNAME;
     uint64_t size;
     uint64_t addr;
 } MemBlock;
 
-struct QGuestAllocator {
-    QAllocOpts opts;
-    uint64_t start;
-    uint64_t end;
-    uint32_t page_size;
-
-    MemList *used;
-    MemList *free;
-};
-
 #define DEFAULT_PAGE_SIZE 4096
 
 static void mlist_delete(MemList *list, MemBlock *node)
@@ -225,7 +213,7 @@ static void mlist_free(QGuestAllocator *s, uint64_t addr)
  * Mostly for valgrind happiness, but it does offer
  * a chokepoint for debugging guest memory leaks, too.
  */
-void alloc_uninit(QGuestAllocator *allocator)
+void alloc_destroy(QGuestAllocator *allocator)
 {
     MemBlock *node;
     MemBlock *tmp;
@@ -261,7 +249,6 @@ void alloc_uninit(QGuestAllocator *allocator)
 
     g_free(allocator->used);
     g_free(allocator->free);
-    g_free(allocator);
 }
 
 uint64_t guest_alloc(QGuestAllocator *allocator, size_t size)
@@ -297,9 +284,10 @@ void guest_free(QGuestAllocator *allocator, uint64_t addr)
     }
 }
 
-QGuestAllocator *alloc_init(uint64_t start, uint64_t end)
+void alloc_init(QGuestAllocator *s, QAllocOpts opts,
+                uint64_t start, uint64_t end,
+                size_t page_size)
 {
-    QGuestAllocator *s = g_malloc0(sizeof(*s));
     MemBlock *node;
 
     s->start = start;
@@ -313,26 +301,7 @@ QGuestAllocator *alloc_init(uint64_t start, uint64_t end)
     node = mlist_new(s->start, s->end - s->start);
     QTAILQ_INSERT_HEAD(s->free, node, MLIST_ENTNAME);
 
-    s->page_size = DEFAULT_PAGE_SIZE;
-
-    return s;
-}
-
-QGuestAllocator *alloc_init_flags(QAllocOpts opts,
-                                  uint64_t start, uint64_t end)
-{
-    QGuestAllocator *s = alloc_init(start, end);
-    s->opts = opts;
-    return s;
-}
-
-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(is_power_of_2(page_size));
-    allocator->page_size = page_size;
+    s->page_size = page_size;
 }
 
 void alloc_set_flags(QGuestAllocator *allocator, QAllocOpts opts)
diff --git a/tests/libqos/malloc.h b/tests/libqos/malloc.h
index 828fdda..4d1a2e2 100644
--- a/tests/libqos/malloc.h
+++ b/tests/libqos/malloc.h
@@ -23,19 +23,28 @@ typedef enum {
     ALLOC_PARANOID    = 0x04
 } QAllocOpts;
 
-typedef struct QGuestAllocator QGuestAllocator;
+typedef QTAILQ_HEAD(MemList, MemBlock) MemList;
 
-void alloc_uninit(QGuestAllocator *allocator);
+typedef struct QGuestAllocator {
+    QAllocOpts opts;
+    uint64_t start;
+    uint64_t end;
+    uint32_t page_size;
+
+    MemList *used;
+    MemList *free;
+} QGuestAllocator;
 
 /* 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,
-                                  uint64_t start, uint64_t end);
-void alloc_set_page_size(QGuestAllocator *allocator, size_t page_size);
 void alloc_set_flags(QGuestAllocator *allocator, QAllocOpts opts);
 
+void alloc_init(QGuestAllocator *alloc, QAllocOpts flags,
+                uint64_t start, uint64_t end,
+                size_t page_size);
+void alloc_destroy(QGuestAllocator *allocator);
+
 #endif
diff --git a/tests/rtas-test.c b/tests/rtas-test.c
index 009bda6..ee88867 100644
--- a/tests/rtas-test.c
+++ b/tests/rtas-test.c
@@ -17,7 +17,7 @@ static void test_rtas_get_time_of_day(void)
     global_qtest = qs->qts;
 
     t1 = time(NULL);
-    ret = qrtas_get_time_of_day(qs->qts, qs->alloc, &tm, &ns);
+    ret = qrtas_get_time_of_day(qs->qts, &qs->alloc, &tm, &ns);
     g_assert_cmpint(ret, ==, 0);
     t2 = mktimegm(&tm);
     g_assert(t2 - t1 < 5); /* 5 sec max to run the test */
diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index 3414075..0c9a79a 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -154,7 +154,7 @@ typedef struct TestServer {
     bool test_fail;
     int test_flags;
     int queues;
-    QGuestAllocator *alloc;
+    QGuestAllocator alloc;
 } TestServer;
 
 static TestServer *test_server_new(const gchar *name);
@@ -202,10 +202,10 @@ static void init_virtio_dev(QTestState *qts, TestServer *s, uint32_t features_ma
     qvirtio_pci_device_enable(s->dev);
     qvirtio_start_device(&s->dev->vdev);
 
-    s->alloc = pc_alloc_init(qts);
+    pc_alloc_init(&s->alloc, qts, 0);
 
     for (i = 0; i < s->queues * 2; i++) {
-        s->vq[i] = qvirtqueue_setup(&s->dev->vdev, s->alloc, i);
+        s->vq[i] = qvirtqueue_setup(&s->dev->vdev, &s->alloc, i);
     }
 
     features = qvirtio_get_features(&s->dev->vdev);
@@ -220,9 +220,9 @@ static void uninit_virtio_dev(TestServer *s)
     int i;
 
     for (i = 0; i < s->queues * 2; i++) {
-        qvirtqueue_cleanup(s->dev->vdev.bus, s->vq[i], s->alloc);
+        qvirtqueue_cleanup(s->dev->vdev.bus, s->vq[i], &s->alloc);
     }
-    pc_alloc_uninit(s->alloc);
+    alloc_destroy(&s->alloc);
 
     qvirtio_pci_device_free(s->dev);
 }
diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
index d275c74..8fd74f6 100644
--- a/tests/virtio-9p-test.c
+++ b/tests/virtio-9p-test.c
@@ -67,7 +67,7 @@ static QVirtIO9P *qvirtio_9p_pci_start(void)
     qvirtio_pci_device_enable(dev);
     qvirtio_start_device(v9p->dev);
 
-    v9p->vq = qvirtqueue_setup(v9p->dev, v9p->qs->alloc, 0);
+    v9p->vq = qvirtqueue_setup(v9p->dev, &v9p->qs->alloc, 0);
 
     qvirtio_set_driver_ok(v9p->dev);
 
@@ -76,7 +76,7 @@ static QVirtIO9P *qvirtio_9p_pci_start(void)
 
 static void qvirtio_9p_pci_stop(QVirtIO9P *v9p)
 {
-    qvirtqueue_cleanup(v9p->dev->bus, v9p->vq, v9p->qs->alloc);
+    qvirtqueue_cleanup(v9p->dev->bus, v9p->vq, &v9p->qs->alloc);
     qvirtio_pci_device_disable(container_of(v9p->dev, QVirtioPCIDevice, vdev));
     qvirtio_pci_device_free((QVirtioPCIDevice *)v9p->dev);
     qvirtio_9p_stop(v9p);
@@ -222,7 +222,7 @@ static P9Req *v9fs_req_init(QVirtIO9P *v9p, uint32_t size, uint8_t id,
 
     req->v9p = v9p;
     req->t_size = total_size;
-    req->t_msg = guest_alloc(v9p->qs->alloc, req->t_size);
+    req->t_msg = guest_alloc(&v9p->qs->alloc, req->t_size);
     v9fs_memwrite(req, &hdr, 7);
     req->tag = tag;
     return req;
@@ -232,7 +232,7 @@ static void v9fs_req_send(P9Req *req)
 {
     QVirtIO9P *v9p = req->v9p;
 
-    req->r_msg = guest_alloc(v9p->qs->alloc, P9_MAX_SIZE);
+    req->r_msg = guest_alloc(&v9p->qs->alloc, P9_MAX_SIZE);
     req->free_head = qvirtqueue_add(v9p->vq, req->t_msg, req->t_size, false,
                                     true);
     qvirtqueue_add(v9p->vq, req->r_msg, P9_MAX_SIZE, true, false);
@@ -290,8 +290,8 @@ static void v9fs_req_free(P9Req *req)
 {
     QVirtIO9P *v9p = req->v9p;
 
-    guest_free(v9p->qs->alloc, req->t_msg);
-    guest_free(v9p->qs->alloc, req->r_msg);
+    guest_free(&v9p->qs->alloc, req->t_msg);
+    guest_free(&v9p->qs->alloc, req->r_msg);
     g_free(req);
 }
 
diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c
index f97c158..77457f7 100644
--- a/tests/virtio-blk-test.c
+++ b/tests/virtio-blk-test.c
@@ -15,6 +15,7 @@
 #include "libqos/virtio.h"
 #include "libqos/virtio-pci.h"
 #include "libqos/virtio-mmio.h"
+#include "libqos/malloc.h"
 #include "libqos/malloc-generic.h"
 #include "qapi/qmp/qdict.h"
 #include "qemu/bswap.h"
@@ -290,12 +291,12 @@ static void pci_basic(void)
     qs = pci_test_start();
     dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
 
-    vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
+    vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, &qs->alloc, 0);
 
-    test_basic(&dev->vdev, qs->alloc, &vqpci->vq);
+    test_basic(&dev->vdev, &qs->alloc, &vqpci->vq);
 
     /* End test */
-    qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
+    qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, &qs->alloc);
     qvirtio_pci_device_disable(dev);
     qvirtio_pci_device_free(dev);
     qtest_shutdown(qs);
@@ -329,7 +330,7 @@ static void pci_indirect(void)
                             (1u << VIRTIO_BLK_F_SCSI));
     qvirtio_set_features(&dev->vdev, features);
 
-    vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
+    vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, &qs->alloc, 0);
 
     qvirtio_set_driver_ok(&dev->vdev);
 
@@ -340,11 +341,11 @@ static void pci_indirect(void)
     req.data = g_malloc0(512);
     strcpy(req.data, "TEST");
 
-    req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
+    req_addr = virtio_blk_request(&qs->alloc, &dev->vdev, &req, 512);
 
     g_free(req.data);
 
-    indirect = qvring_indirect_desc_setup(&dev->vdev, qs->alloc, 2);
+    indirect = qvring_indirect_desc_setup(&dev->vdev, &qs->alloc, 2);
     qvring_indirect_desc_add(indirect, req_addr, 528, false);
     qvring_indirect_desc_add(indirect, req_addr + 528, 1, true);
     free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
@@ -356,7 +357,7 @@ static void pci_indirect(void)
     g_assert_cmpint(status, ==, 0);
 
     g_free(indirect);
-    guest_free(qs->alloc, req_addr);
+    guest_free(&qs->alloc, req_addr);
 
     /* Read request */
     req.type = VIRTIO_BLK_T_IN;
@@ -365,11 +366,11 @@ static void pci_indirect(void)
     req.data = g_malloc0(512);
     strcpy(req.data, "TEST");
 
-    req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
+    req_addr = virtio_blk_request(&qs->alloc, &dev->vdev, &req, 512);
 
     g_free(req.data);
 
-    indirect = qvring_indirect_desc_setup(&dev->vdev, qs->alloc, 2);
+    indirect = qvring_indirect_desc_setup(&dev->vdev, &qs->alloc, 2);
     qvring_indirect_desc_add(indirect, req_addr, 16, false);
     qvring_indirect_desc_add(indirect, req_addr + 16, 513, true);
     free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
@@ -386,10 +387,10 @@ static void pci_indirect(void)
     g_free(data);
 
     g_free(indirect);
-    guest_free(qs->alloc, req_addr);
+    guest_free(&qs->alloc, req_addr);
 
     /* End test */
-    qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
+    qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, &qs->alloc);
     qvirtio_pci_device_disable(dev);
     qvirtio_pci_device_free(dev);
     qtest_shutdown(qs);
@@ -444,7 +445,7 @@ static void pci_msix(void)
     dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
     qpci_msix_enable(dev->pdev);
 
-    qvirtio_pci_set_msix_configuration_vector(dev, qs->alloc, 0);
+    qvirtio_pci_set_msix_configuration_vector(dev, &qs->alloc, 0);
 
     capacity = qvirtio_config_readq(&dev->vdev, 0);
     g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
@@ -456,8 +457,8 @@ static void pci_msix(void)
                             (1u << VIRTIO_BLK_F_SCSI));
     qvirtio_set_features(&dev->vdev, features);
 
-    vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
-    qvirtqueue_pci_msix_setup(dev, vqpci, qs->alloc, 1);
+    vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, &qs->alloc, 0);
+    qvirtqueue_pci_msix_setup(dev, vqpci, &qs->alloc, 1);
 
     qvirtio_set_driver_ok(&dev->vdev);
 
@@ -477,7 +478,7 @@ static void pci_msix(void)
     req.data = g_malloc0(512);
     strcpy(req.data, "TEST");
 
-    req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
+    req_addr = virtio_blk_request(&qs->alloc, &dev->vdev, &req, 512);
 
     g_free(req.data);
 
@@ -492,7 +493,7 @@ static void pci_msix(void)
     status = readb(req_addr + 528);
     g_assert_cmpint(status, ==, 0);
 
-    guest_free(qs->alloc, req_addr);
+    guest_free(&qs->alloc, req_addr);
 
     /* Read request */
     req.type = VIRTIO_BLK_T_IN;
@@ -500,7 +501,7 @@ static void pci_msix(void)
     req.sector = 0;
     req.data = g_malloc0(512);
 
-    req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
+    req_addr = virtio_blk_request(&qs->alloc, &dev->vdev, &req, 512);
 
     g_free(req.data);
 
@@ -522,10 +523,10 @@ static void pci_msix(void)
     g_assert_cmpstr(data, ==, "TEST");
     g_free(data);
 
-    guest_free(qs->alloc, req_addr);
+    guest_free(&qs->alloc, req_addr);
 
     /* End test */
-    qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
+    qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, &qs->alloc);
     qpci_msix_disable(dev->pdev);
     qvirtio_pci_device_disable(dev);
     qvirtio_pci_device_free(dev);
@@ -552,7 +553,7 @@ static void pci_idx(void)
     dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
     qpci_msix_enable(dev->pdev);
 
-    qvirtio_pci_set_msix_configuration_vector(dev, qs->alloc, 0);
+    qvirtio_pci_set_msix_configuration_vector(dev, &qs->alloc, 0);
 
     capacity = qvirtio_config_readq(&dev->vdev, 0);
     g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
@@ -564,8 +565,8 @@ static void pci_idx(void)
                             (1u << VIRTIO_BLK_F_SCSI));
     qvirtio_set_features(&dev->vdev, features);
 
-    vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
-    qvirtqueue_pci_msix_setup(dev, vqpci, qs->alloc, 1);
+    vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, &qs->alloc, 0);
+    qvirtqueue_pci_msix_setup(dev, vqpci, &qs->alloc, 1);
 
     qvirtio_set_driver_ok(&dev->vdev);
 
@@ -576,7 +577,7 @@ static void pci_idx(void)
     req.data = g_malloc0(512);
     strcpy(req.data, "TEST");
 
-    req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
+    req_addr = virtio_blk_request(&qs->alloc, &dev->vdev, &req, 512);
 
     g_free(req.data);
 
@@ -595,7 +596,7 @@ static void pci_idx(void)
     req.data = g_malloc0(512);
     strcpy(req.data, "TEST");
 
-    req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
+    req_addr = virtio_blk_request(&qs->alloc, &dev->vdev, &req, 512);
 
     g_free(req.data);
 
@@ -613,7 +614,7 @@ static void pci_idx(void)
                                              QVIRTIO_BLK_TIMEOUT_US);
     g_assert_cmpint(status, ==, 0);
 
-    guest_free(qs->alloc, req_addr);
+    guest_free(&qs->alloc, req_addr);
 
     /* Read request */
     req.type = VIRTIO_BLK_T_IN;
@@ -621,7 +622,7 @@ static void pci_idx(void)
     req.sector = 1;
     req.data = g_malloc0(512);
 
-    req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
+    req_addr = virtio_blk_request(&qs->alloc, &dev->vdev, &req, 512);
 
     g_free(req.data);
 
@@ -645,10 +646,10 @@ static void pci_idx(void)
     g_assert_cmpstr(data, ==, "TEST");
     g_free(data);
 
-    guest_free(qs->alloc, req_addr);
+    guest_free(&qs->alloc, req_addr);
 
     /* End test */
-    qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
+    qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, &qs->alloc);
     qpci_msix_disable(dev->pdev);
     qvirtio_pci_device_disable(dev);
     qvirtio_pci_device_free(dev);
@@ -708,7 +709,7 @@ static void mmio_basic(void)
 {
     QVirtioMMIODevice *dev;
     QVirtQueue *vq;
-    QGuestAllocator *alloc;
+    QGuestAllocator alloc;
     int n_size = TEST_IMAGE_SIZE / 2;
     uint64_t capacity;
 
@@ -720,10 +721,10 @@ static void mmio_basic(void)
 
     qvirtio_start_device(&dev->vdev);
 
-    alloc = generic_alloc_init(MMIO_RAM_ADDR, MMIO_RAM_SIZE, MMIO_PAGE_SIZE);
-    vq = qvirtqueue_setup(&dev->vdev, alloc, 0);
+    generic_alloc_init(&alloc, MMIO_RAM_ADDR, MMIO_RAM_SIZE, MMIO_PAGE_SIZE);
+    vq = qvirtqueue_setup(&dev->vdev, &alloc, 0);
 
-    test_basic(&dev->vdev, alloc, vq);
+    test_basic(&dev->vdev, &alloc, vq);
 
     qmp_discard_response("{ 'execute': 'block_resize', "
                          " 'arguments': { 'device': 'drive0', "
@@ -735,9 +736,9 @@ static void mmio_basic(void)
     g_assert_cmpint(capacity, ==, n_size / 512);
 
     /* End test */
-    qvirtqueue_cleanup(dev->vdev.bus, vq, alloc);
+    qvirtqueue_cleanup(dev->vdev.bus, vq, &alloc);
     g_free(dev);
-    generic_alloc_uninit(alloc);
+    alloc_destroy(&alloc);
     test_end();
 }
 
diff --git a/tests/virtio-net-test.c b/tests/virtio-net-test.c
index f89e08f..fa06d9b 100644
--- a/tests/virtio-net-test.c
+++ b/tests/virtio-net-test.c
@@ -224,16 +224,16 @@ static void pci_basic(gconstpointer data)
     qs = pci_test_start(sv[1]);
     dev = virtio_net_pci_init(qs->pcibus, PCI_SLOT);
 
-    rx = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
-    tx = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 1);
+    rx = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, &qs->alloc, 0);
+    tx = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, &qs->alloc, 1);
 
     driver_init(&dev->vdev);
-    func(&dev->vdev, qs->alloc, &rx->vq, &tx->vq, sv[0]);
+    func(&dev->vdev, &qs->alloc, &rx->vq, &tx->vq, sv[0]);
 
     /* End test */
     close(sv[0]);
-    qvirtqueue_cleanup(dev->vdev.bus, &tx->vq, qs->alloc);
-    qvirtqueue_cleanup(dev->vdev.bus, &rx->vq, qs->alloc);
+    qvirtqueue_cleanup(dev->vdev.bus, &tx->vq, &qs->alloc);
+    qvirtqueue_cleanup(dev->vdev.bus, &rx->vq, &qs->alloc);
     qvirtio_pci_device_disable(dev);
     g_free(dev->pdev);
     g_free(dev);
diff --git a/tests/virtio-scsi-test.c b/tests/virtio-scsi-test.c
index 961925c..9298aa8 100644
--- a/tests/virtio-scsi-test.c
+++ b/tests/virtio-scsi-test.c
@@ -62,7 +62,7 @@ static void qvirtio_scsi_pci_free(QVirtIOSCSI *vs)
     int i;
 
     for (i = 0; i < vs->num_queues + 2; i++) {
-        qvirtqueue_cleanup(vs->dev->bus, vs->vq[i], vs->qs->alloc);
+        qvirtqueue_cleanup(vs->dev->bus, vs->vq[i], &vs->qs->alloc);
     }
     qvirtio_pci_device_disable(container_of(vs->dev, QVirtioPCIDevice, vdev));
     qvirtio_pci_device_free((QVirtioPCIDevice *)vs->dev);
@@ -75,7 +75,7 @@ static uint64_t qvirtio_scsi_alloc(QVirtIOSCSI *vs, size_t alloc_size,
 {
     uint64_t addr;
 
-    addr = guest_alloc(vs->qs->alloc, alloc_size);
+    addr = guest_alloc(&vs->qs->alloc, alloc_size);
     if (data) {
         memwrite(addr, data, alloc_size);
     }
@@ -133,10 +133,10 @@ static uint8_t virtio_scsi_do_command(QVirtIOSCSI *vs, const uint8_t *cdb,
         memread(resp_addr, resp_out, sizeof(*resp_out));
     }
 
-    guest_free(vs->qs->alloc, req_addr);
-    guest_free(vs->qs->alloc, resp_addr);
-    guest_free(vs->qs->alloc, data_in_addr);
-    guest_free(vs->qs->alloc, data_out_addr);
+    guest_free(&vs->qs->alloc, req_addr);
+    guest_free(&vs->qs->alloc, resp_addr);
+    guest_free(&vs->qs->alloc, data_in_addr);
+    guest_free(&vs->qs->alloc, data_out_addr);
     return response;
 }
 
@@ -166,7 +166,7 @@ static QVirtIOSCSI *qvirtio_scsi_pci_init(int slot)
     g_assert_cmpint(vs->num_queues, <, MAX_NUM_QUEUES);
 
     for (i = 0; i < vs->num_queues + 2; i++) {
-        vs->vq[i] = qvirtqueue_setup(vs->dev, vs->qs->alloc, i);
+        vs->vq[i] = qvirtqueue_setup(vs->dev, &vs->qs->alloc, i);
     }
 
     /* Clear the POWER ON OCCURRED unit attention */
-- 
1.8.3.1



Re: [Qemu-devel] [PATCH 18/71] tests/libqos: embed allocators instead of malloc-ing them
Posted by Thomas Huth 7 years, 2 months ago
On 2018-12-03 16:32, Paolo Bonzini wrote:
> qgraph will embed these objects instead of allocating them in a separate
> object.  Expose a new API "generic_alloc_init" and "generic_alloc_destroy"
> for that, and rename the existing API with s/init/new/ and s/uninit/free/.

Could you please add a sentence *why* you are doing this? ... without
that information, this just looks like a lot of unnecessary code churn...

 Thomas

Re: [Qemu-devel] [PATCH 18/71] tests/libqos: embed allocators instead of malloc-ing them
Posted by Paolo Bonzini 7 years, 2 months ago
On 07/12/18 13:32, Thomas Huth wrote:
> On 2018-12-03 16:32, Paolo Bonzini wrote:
>> qgraph will embed these objects instead of allocating them in a separate
>> object.  Expose a new API "generic_alloc_init" and "generic_alloc_destroy"
>> for that, and rename the existing API with s/init/new/ and s/uninit/free/.
> 
> Could you please add a sentence *why* you are doing this? ... without
> that information, this just looks like a lot of unnecessary code churn...

The explanation is simply that if you allocate them separately you have
to define a destructor function to free it---more boilerplate and more
stuff that you can get wrong.  Therefore qgraph tries to use embedded
structs when something is always there (a "contains" edge).

The same is true for 16/71, you want to use heap-allocated PCI buses for
non-qgraph tests, but for a qgraph machine it would be very much
preferrable to embed it in the PCI host bridge QOSGraphObject.

Paolo