All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Daniel P. Berrange" <berrange@redhat.com>
To: qemu-devel@nongnu.org
Cc: qemu-block@nongnu.org, "Markus Armbruster" <armbru@redhat.com>,
	"Max Reitz" <mreitz@redhat.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Andreas Färber" <afaerber@suse.de>,
	"Daniel P. Berrange" <berrange@redhat.com>
Subject: [Qemu-devel] [PATCH v14 15/19] numa: convert to use QObjectInputVisitor for -numa
Date: Tue, 27 Sep 2016 14:13:17 +0100	[thread overview]
Message-ID: <1474982001-20878-16-git-send-email-berrange@redhat.com> (raw)
In-Reply-To: <1474982001-20878-1-git-send-email-berrange@redhat.com>

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 <berrange@redhat.com>
---
 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..5daa3d1 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 and permit_int_ranges=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, &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 6398678..7625ef7 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
 
@@ -583,6 +584,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

  parent reply	other threads:[~2016-09-27 13:14 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-27 13:13 [Qemu-devel] [PATCH v14 00/19] QAPI/QOM work for non-scalar object properties Daniel P. Berrange
2016-09-27 13:13 ` [Qemu-devel] [PATCH v14 01/19] qdict: implement a qdict_crumple method for un-flattening a dict Daniel P. Berrange
2016-09-27 21:22   ` Eric Blake
2016-09-27 13:13 ` [Qemu-devel] [PATCH v14 02/19] option: make parse_option_bool/number non-static Daniel P. Berrange
2016-09-27 13:13 ` [Qemu-devel] [PATCH v14 03/19] option: allow qemu_opts_to_qdict to merge repeated options Daniel P. Berrange
2016-09-27 22:03   ` Eric Blake
2016-09-28  9:35     ` Daniel P. Berrange
2016-09-28 13:44       ` Daniel P. Berrange
2016-09-27 13:13 ` [Qemu-devel] [PATCH v14 04/19] qapi: add trace events for visitor Daniel P. Berrange
2016-09-27 22:05   ` Eric Blake
2016-09-27 13:13 ` [Qemu-devel] [PATCH v14 05/19] qapi: rename QmpInputVisitor to QObjectInputVisitor Daniel P. Berrange
2016-09-27 13:13 ` [Qemu-devel] [PATCH v14 06/19] qapi: rename QmpOutputVisitor to QObjectOutputVisitor Daniel P. Berrange
2016-09-27 13:13 ` [Qemu-devel] [PATCH v14 07/19] qapi: don't pass two copies of TestInputVisitorData to tests Daniel P. Berrange
2016-09-27 22:10   ` Eric Blake
2016-09-27 22:12     ` Eric Blake
2016-09-28  9:35       ` Daniel P. Berrange
2016-09-27 13:13 ` [Qemu-devel] [PATCH v14 08/19] qapi: permit scalar type conversions in QObjectInputVisitor Daniel P. Berrange
2016-09-27 13:13 ` [Qemu-devel] [PATCH v14 09/19] qapi: permit auto-creating single element lists Daniel P. Berrange
2016-09-27 13:13 ` [Qemu-devel] [PATCH v14 10/19] qapi: permit auto-creating nested structs Daniel P. Berrange
2016-09-27 13:13 ` [Qemu-devel] [PATCH v14 11/19] qapi: add integer range support for QObjectInputVisitor Daniel P. Berrange
2016-09-27 13:13 ` [Qemu-devel] [PATCH v14 12/19] qapi: allow QObjectInputVisitor to be created with QemuOpts Daniel P. Berrange
2016-09-27 13:13 ` [Qemu-devel] [PATCH v14 13/19] qom: support non-scalar properties with -object Daniel P. Berrange
2016-09-27 13:13 ` [Qemu-devel] [PATCH v14 14/19] hmp: support non-scalar properties with object_add Daniel P. Berrange
2016-09-27 13:13 ` Daniel P. Berrange [this message]
2016-09-27 13:13 ` [Qemu-devel] [PATCH v14 16/19] block: convert crypto driver to use QObjectInputVisitor Daniel P. Berrange
2016-09-27 13:13 ` [Qemu-devel] [PATCH v14 17/19] acpi: convert to QObjectInputVisitor for -acpi parsing Daniel P. Berrange
2016-09-27 13:13 ` [Qemu-devel] [PATCH v14 18/19] net: convert to QObjectInputVisitor for -net/-netdev parsing Daniel P. Berrange
2016-09-27 13:13 ` [Qemu-devel] [PATCH v14 19/19] qapi: delete unused OptsVisitor code Daniel P. Berrange
2016-10-20 15:06 ` [Qemu-devel] [PATCH v14 00/19] QAPI/QOM work for non-scalar object properties Markus Armbruster
2016-10-20 15:14   ` Daniel P. Berrange
2016-10-21  9:35   ` Markus Armbruster
2016-10-21  9:38     ` Daniel P. Berrange

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=1474982001-20878-16-git-send-email-berrange@redhat.com \
    --to=berrange@redhat.com \
    --cc=afaerber@suse.de \
    --cc=armbru@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.