qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v14 17/21] numa: convert to use QObjectInputVisitor


From: Daniel P. Berrange
Subject: [Qemu-devel] [PATCH v14 17/21] numa: convert to use QObjectInputVisitor for -numa
Date: Fri, 30 Sep 2016 15:45:40 +0100

Switch away from using OptsVisitor to parse the -numa
argument processing. This enables use of the modern
list syntax for specifying CPUs. e.g. the old syntax

  -numa node,nodeid=0,cpus=0-3,cpus=8-11,mem=107

is equivalent to

  -numa node,nodeid=0,cpus.0=0,cpus.1=1,cpus.2=2,cpus.3=3,\
        cpus.4=8,cpus.5=9,cpus.6=10,cpus.7=11,mem=107

Furthermore, the cli arg can now follow the QAPI schema
nesting, so the above is equivalent to the canonical
syntax:

  -numa type=node,data.nodeid=0,data.cpus.0=0,data.cpus.1=1,\
        data.cpus.2=2,data.cpus.3=3,data.cpus.4=8,data.cpus.5=9,\
        data.cpus.6=10,data.cpus.7=11,data.mem=107

A test case is added to cover argument parsing to validate
that both the old and new syntax is correctly handled.

Signed-off-by: Daniel P. Berrange <address@hidden>
---
 include/sysemu/numa_int.h |  11 +++++
 numa.c                    |  36 +++++++++-----
 stubs/Makefile.objs       |   5 ++
 stubs/exec.c              |   6 +++
 stubs/hostmem.c           |  14 ++++++
 stubs/memory.c            |  41 ++++++++++++++++
 stubs/qdev.c              |   8 ++++
 stubs/vl.c                |   8 ++++
 stubs/vmstate.c           |   4 ++
 tests/Makefile.include    |   2 +
 tests/test-numa.c         | 116 ++++++++++++++++++++++++++++++++++++++++++++++
 11 files changed, 240 insertions(+), 11 deletions(-)
 create mode 100644 include/sysemu/numa_int.h
 create mode 100644 stubs/exec.c
 create mode 100644 stubs/hostmem.c
 create mode 100644 stubs/memory.c
 create mode 100644 stubs/qdev.c
 create mode 100644 stubs/vl.c
 create mode 100644 tests/test-numa.c

diff --git a/include/sysemu/numa_int.h b/include/sysemu/numa_int.h
new file mode 100644
index 0000000..93160da
--- /dev/null
+++ b/include/sysemu/numa_int.h
@@ -0,0 +1,11 @@
+#ifndef SYSEMU_NUMA_INT_H
+#define SYSEMU_NUMA_INT_H
+
+#include "sysemu/numa.h"
+
+extern int have_memdevs;
+extern int max_numa_nodeid;
+
+int parse_numa(void *opaque, QemuOpts *opts, Error **errp);
+
+#endif
diff --git a/numa.c b/numa.c
index 6289f46..653ebf1 100644
--- a/numa.c
+++ b/numa.c
@@ -23,14 +23,14 @@
  */
 
 #include "qemu/osdep.h"
-#include "sysemu/numa.h"
+#include "sysemu/numa_int.h"
 #include "exec/cpu-common.h"
 #include "qemu/bitmap.h"
 #include "qom/cpu.h"
 #include "qemu/error-report.h"
 #include "include/exec/cpu-common.h" /* for RAM_ADDR_FMT */
 #include "qapi-visit.h"
-#include "qapi/opts-visitor.h"
+#include "qapi/qobject-input-visitor.h"
 #include "hw/boards.h"
 #include "sysemu/hostmem.h"
 #include "qmp-commands.h"
@@ -45,10 +45,10 @@ QemuOptsList qemu_numa_opts = {
     .desc = { { 0 } } /* validated with OptsVisitor */
 };
 
-static int have_memdevs = -1;
-static int max_numa_nodeid; /* Highest specified NUMA node ID, plus one.
-                             * For all nodes, nodeid < max_numa_nodeid
-                             */
+int have_memdevs = -1;
+int max_numa_nodeid; /* Highest specified NUMA node ID, plus one.
+                      * For all nodes, nodeid < max_numa_nodeid
+                      */
 int nb_numa_nodes;
 NodeInfo numa_info[MAX_NODES];
 
@@ -189,6 +189,9 @@ static void numa_node_parse(NumaNodeOptions *node, QemuOpts 
*opts, Error **errp)
     if (node->has_mem) {
         uint64_t mem_size = node->mem;
         const char *mem_str = qemu_opt_get(opts, "mem");
+        if (!mem_str) {
+            mem_str = qemu_opt_get(opts, "data.mem");
+        }
         /* Fix up legacy suffix-less format */
         if (g_ascii_isdigit(mem_str[strlen(mem_str) - 1])) {
             mem_size <<= 20;
@@ -211,16 +214,27 @@ static void numa_node_parse(NumaNodeOptions *node, 
QemuOpts *opts, Error **errp)
     max_numa_nodeid = MAX(max_numa_nodeid, nodenr + 1);
 }
 
-static int parse_numa(void *opaque, QemuOpts *opts, Error **errp)
+int parse_numa(void *opaque, QemuOpts *opts, Error **errp)
 {
     NumaOptions *object = NULL;
     Error *err = NULL;
+    Visitor *v;
 
-    {
-        Visitor *v = opts_visitor_new(opts);
-        visit_type_NumaOptions(v, NULL, &object, &err);
-        visit_free(v);
+    /*
+     * Needs autocreate_list=true, permit_int_ranges=true and
+     * permit_repeated_opts=true in order to support existing
+     * syntax for 'cpus' parameter which is an int list.
+     *
+     * Needs autocreate_struct_levels=1, because existing syntax
+     * used a nested struct in the QMP schema with a flat namespace
+     * in the CLI args.
+     */
+    v = qobject_input_visitor_new_opts(opts, true, 1, true, true, &err);
+    if (err) {
+        goto end;
     }
+    visit_type_NumaOptions(v, NULL, &object, &err);
+    visit_free(v);
 
     if (err) {
         goto end;
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index c5850e8..661b48a 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -48,3 +48,8 @@ stub-obj-y += iohandler.o
 stub-obj-y += smbios_type_38.o
 stub-obj-y += ipmi.o
 stub-obj-y += pc_madt_cpu_entry.o
+stub-obj-y += vl.o
+stub-obj-y += exec.o
+stub-obj-y += memory.o
+stub-obj-y += hostmem.o
+stub-obj-y += qdev.o
diff --git a/stubs/exec.c b/stubs/exec.c
new file mode 100644
index 0000000..e37f002
--- /dev/null
+++ b/stubs/exec.c
@@ -0,0 +1,6 @@
+
+#include "qemu/osdep.h"
+#include "exec/cpu-common.h"
+#include "qom/cpu.h"
+
+struct CPUTailQ cpus = QTAILQ_HEAD_INITIALIZER(cpus);
diff --git a/stubs/hostmem.c b/stubs/hostmem.c
new file mode 100644
index 0000000..301d853
--- /dev/null
+++ b/stubs/hostmem.c
@@ -0,0 +1,14 @@
+
+#include "qemu/osdep.h"
+#include "sysemu/hostmem.h"
+
+void host_memory_backend_set_mapped(HostMemoryBackend *backend, bool mapped)
+{
+}
+
+
+MemoryRegion *host_memory_backend_get_memory(HostMemoryBackend *backend,
+                                             Error **errp)
+{
+    return NULL;
+}
diff --git a/stubs/memory.c b/stubs/memory.c
new file mode 100644
index 0000000..c849d9d
--- /dev/null
+++ b/stubs/memory.c
@@ -0,0 +1,41 @@
+
+#include "qemu/osdep.h"
+#include "exec/memory.h"
+
+void memory_region_init_ram(MemoryRegion *mr,
+                            struct Object *owner,
+                            const char *name,
+                            uint64_t size,
+                            Error **errp)
+{
+}
+
+#ifdef __linux__
+void memory_region_init_ram_from_file(MemoryRegion *mr,
+                                      struct Object *owner,
+                                      const char *name,
+                                      uint64_t size,
+                                      bool share,
+                                      const char *path,
+                                      Error **errp)
+{
+}
+#endif
+
+void memory_region_init(MemoryRegion *mr,
+                        struct Object *owner,
+                        const char *name,
+                        uint64_t size)
+{
+}
+
+void memory_region_add_subregion(MemoryRegion *mr,
+                                 hwaddr offset,
+                                 MemoryRegion *subregion)
+{
+}
+
+bool memory_region_is_mapped(MemoryRegion *mr)
+{
+    return false;
+}
diff --git a/stubs/qdev.c b/stubs/qdev.c
new file mode 100644
index 0000000..e28fdf2
--- /dev/null
+++ b/stubs/qdev.c
@@ -0,0 +1,8 @@
+
+#include "qemu/osdep.h"
+#include "hw/qdev-core.h"
+
+Object *qdev_get_machine(void)
+{
+    return NULL;
+}
diff --git a/stubs/vl.c b/stubs/vl.c
new file mode 100644
index 0000000..698fa80
--- /dev/null
+++ b/stubs/vl.c
@@ -0,0 +1,8 @@
+
+#include "qemu/osdep.h"
+#include "exec/cpu-common.h"
+
+int max_cpus = 1;
+ram_addr_t ram_size;
+const char *mem_path;
+int mem_prealloc;
diff --git a/stubs/vmstate.c b/stubs/vmstate.c
index 94b831e..f2708ee 100644
--- a/stubs/vmstate.c
+++ b/stubs/vmstate.c
@@ -23,3 +23,7 @@ void vmstate_unregister(DeviceState *dev,
                         void *opaque)
 {
 }
+
+void vmstate_register_ram_global(struct MemoryRegion *memory)
+{
+}
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 605f276..72f71ea 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -116,6 +116,7 @@ check-unit-$(CONFIG_REPLICATION) += 
tests/test-replication$(EXESUF)
 check-unit-y += tests/test-bufferiszero$(EXESUF)
 gcov-files-check-bufferiszero-y = util/bufferiszero.c
 check-unit-y += tests/test-uuid$(EXESUF)
+check-unit-y += tests/test-numa$(EXESUF)
 
 check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
 
@@ -584,6 +585,7 @@ tests/test-crypto-pbkdf$(EXESUF): tests/test-crypto-pbkdf.o 
$(test-crypto-obj-y)
 tests/test-crypto-ivgen$(EXESUF): tests/test-crypto-ivgen.o 
$(test-crypto-obj-y)
 tests/test-crypto-afsplit$(EXESUF): tests/test-crypto-afsplit.o 
$(test-crypto-obj-y)
 tests/test-crypto-block$(EXESUF): tests/test-crypto-block.o 
$(test-crypto-obj-y)
+tests/test-numa$(EXESUF): tests/test-numa.o  numa.o $(test-qom-obj-y)
 
 libqos-obj-y = tests/libqos/pci.o tests/libqos/fw_cfg.o tests/libqos/malloc.o
 libqos-obj-y += tests/libqos/i2c.o tests/libqos/libqos.o
diff --git a/tests/test-numa.c b/tests/test-numa.c
new file mode 100644
index 0000000..458681b
--- /dev/null
+++ b/tests/test-numa.c
@@ -0,0 +1,116 @@
+/*
+ * QEMU NUMA testing
+ *
+ * Copyright (c) 2016 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+
+#include "sysemu/numa_int.h"
+
+static void test_numa_parse(const char **nodestr)
+{
+    QemuOpts *opts;
+    size_t i;
+
+    DECLARE_BITMAP(node0cpus, MAX_CPUMASK_BITS);
+    DECLARE_BITMAP(node5cpus, MAX_CPUMASK_BITS);
+
+    bitmap_zero(node0cpus, MAX_CPUMASK_BITS);
+    bitmap_zero(node5cpus, MAX_CPUMASK_BITS);
+    for (i = 0; i <= 3; i++) {
+        bitmap_set(node0cpus, i, 1);
+    }
+    for (i = 8; i <= 11; i++) {
+        bitmap_set(node0cpus, i, 1);
+    }
+    for (i = 4; i <= 7; i++) {
+        bitmap_set(node5cpus, i, 1);
+    }
+    for (i = 12; i <= 15; i++) {
+        bitmap_set(node5cpus, i, 1);
+    }
+
+    max_cpus = 16;
+
+    opts = qemu_opts_parse_noisily(&qemu_numa_opts,
+                                   nodestr[0], true);
+    g_assert(opts != NULL);
+
+    opts = qemu_opts_parse_noisily(&qemu_numa_opts,
+                                   nodestr[1], true);
+    g_assert(opts != NULL);
+
+    qemu_opts_foreach(&qemu_numa_opts, parse_numa, NULL, NULL);
+
+    g_assert_cmpint(max_numa_nodeid, ==, 6);
+    g_assert(!have_memdevs);
+
+    g_assert_cmpint(nb_numa_nodes, ==, 2);
+    for (i = 0; i < MAX_NODES; i++) {
+        if (i == 0 || i == 5) {
+            g_assert(numa_info[i].present);
+            g_assert_cmpint(numa_info[i].node_mem, ==, 107 * 1024 * 1024);
+
+            if (i == 0) {
+                g_assert(bitmap_equal(node0cpus,
+                                      numa_info[i].node_cpu,
+                                      MAX_CPUMASK_BITS));
+            } else {
+                g_assert(bitmap_equal(node5cpus,
+                                      numa_info[i].node_cpu,
+                                      MAX_CPUMASK_BITS));
+            }
+        } else {
+            g_assert(!numa_info[i].present);
+        }
+    }
+
+    nb_numa_nodes = 0;
+    max_numa_nodeid = 0;
+    memset(&numa_info, 0, sizeof(numa_info));
+    g_assert(!numa_info[0].present);
+    qemu_opts_reset(&qemu_numa_opts);
+}
+
+static void test_numa_parse_legacy(void)
+{
+    const char *nodestr[] = {
+        "node,nodeid=0,cpus=0-3,cpus=8-11,mem=107",
+        "node,nodeid=5,cpus=4-7,cpus=12-15,mem=107"
+    };
+    test_numa_parse(nodestr);
+}
+
+static void test_numa_parse_modern(void)
+{
+    const char *nodestr[] = {
+        
"type=node,data.nodeid=0,data.cpus.0=0,data.cpus.1=1,data.cpus.2=2,data.cpus.3=3,"
+          
"data.cpus.4=8,data.cpus.5=9,data.cpus.6=10,data.cpus.7=11,data.mem=107",
+        
"type=node,data.nodeid=5,data.cpus.0=4,data.cpus.1=5,data.cpus.2=6,data.cpus.3=7,"
+          
"data.cpus.4=12,data.cpus.5=13,data.cpus.6=14,data.cpus.7=15,data.mem=107",
+    };
+    test_numa_parse(nodestr);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+    g_test_add_func("/numa/parse/legacy", test_numa_parse_legacy);
+    g_test_add_func("/numa/parse/modern", test_numa_parse_modern);
+    return g_test_run();
+}
-- 
2.7.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]