From 05875687806b71ae980ca59a46777b742b20ac06 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 3 Mar 2017 13:32:24 +0100 Subject: qmp: Dumb down how we run QMP command registration The way we get QMP commands registered is high tech: * qapi-commands.py generates qmp_init_marshal() that does the actual work * it also generates the magic to register it as a MODULE_INIT_QAPI function, so it runs when someone calls module_call_init(MODULE_INIT_QAPI) * main() calls module_call_init() QEMU needs to register a few non-qapified commands. Same high tech works: monitor.c has its own qmp_init_marshal() along with the magic to make it run in module_call_init(MODULE_INIT_QAPI). QEMU also needs to unregister commands that are not wanted in this build's configuration (commit 5032a16). Simple enough: qmp_unregister_commands_hack(). The difficulty is to make it run after the generated qmp_init_marshal(). We can't simply run it in monitor.c's qmp_init_marshal(), because the order in which the registered functions run is indeterminate. So qmp_init_marshal() registers qmp_unregister_commands_hack() separately. Since registering *appends* to the list of registered functions, this will make it run after all the functions that have been registered already. I suspect it takes a long and expensive computer science education to not find this silly. Dumb it down as follows: * Drop MODULE_INIT_QAPI entirely * Give the generated qmp_init_marshal() external linkage. * Call it instead of module_call_init(MODULE_INIT_QAPI) * Except in QEMU proper, call new monitor_init_qmp_commands() that in turn calls the generated qmp_init_marshal(), registers the additional commands and unregisters the unwanted ones. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Message-Id: <1488544368-30622-5-git-send-email-armbru@redhat.com> --- scripts/qapi-commands.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index 09e8467..a75946f 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -208,14 +208,12 @@ def gen_register_command(name, success_response): def gen_registry(registry): ret = mcgen(''' -static void qmp_init_marshal(void) +void qmp_init_marshal(void) { ''') ret += registry ret += mcgen(''' } - -qapi_init(qmp_init_marshal); ''') return ret @@ -308,6 +306,7 @@ fdecl.write(mcgen(''' #include "qapi/qmp/qdict.h" #include "qapi/error.h" +void qmp_init_marshal(void); ''', prefix=prefix)) -- cgit v1.1 From 1527badb954f2d8c17b86e2a258812def5ea3dcc Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 3 Mar 2017 13:32:25 +0100 Subject: qapi: Support multiple command registries per program The command registry encapsulates a single command list. Give the functions using it a parameter instead. Define suitable command lists in monitor, guest agent and test-qmp-commands. Signed-off-by: Markus Armbruster Message-Id: <1488544368-30622-6-git-send-email-armbru@redhat.com> [Debugging turds buried] Reviewed-by: Eric Blake --- scripts/qapi-commands.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index a75946f..2b062ad 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -198,7 +198,8 @@ def gen_register_command(name, success_response): options = 'QCO_NO_SUCCESS_RESP' ret = mcgen(''' - qmp_register_command("%(name)s", qmp_marshal_%(c_name)s, %(opts)s); + qmp_register_command(cmds, "%(name)s", + qmp_marshal_%(c_name)s, %(opts)s); ''', name=name, c_name=c_name(name), opts=options) @@ -208,9 +209,12 @@ def gen_register_command(name, success_response): def gen_registry(registry): ret = mcgen(''' -void qmp_init_marshal(void) +void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds) { -''') + QTAILQ_INIT(cmds); + +''', + c_prefix=c_name(prefix, protect=False)) ret += registry ret += mcgen(''' } @@ -289,7 +293,6 @@ fdef.write(mcgen(''' #include "qemu-common.h" #include "qemu/module.h" #include "qapi/qmp/types.h" -#include "qapi/qmp/dispatch.h" #include "qapi/visitor.h" #include "qapi/qobject-output-visitor.h" #include "qapi/qobject-input-visitor.h" @@ -304,11 +307,12 @@ fdef.write(mcgen(''' fdecl.write(mcgen(''' #include "%(prefix)sqapi-types.h" #include "qapi/qmp/qdict.h" +#include "qapi/qmp/dispatch.h" #include "qapi/error.h" -void qmp_init_marshal(void); +void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds); ''', - prefix=prefix)) + prefix=prefix, c_prefix=c_name(prefix, protect=False))) schema = QAPISchema(input_file) gen = QAPISchemaGenCommandVisitor() -- cgit v1.1 From 9b0c9a63492f9f8f4dc94b0ac5a28fc6a946389b Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 3 Mar 2017 13:32:26 +0100 Subject: qapi-introspect: Mangle --prefix argument properly for C qapi-introspect.py --prefix hasn't been used so far, but fix it anyway. Signed-off-by: Markus Armbruster Message-Id: <1488544368-30622-7-git-send-email-armbru@redhat.com> [Commit message improved] Reviewed-by: Eric Blake --- scripts/qapi-introspect.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py index 541644e..fb72c61 100644 --- a/scripts/qapi-introspect.py +++ b/scripts/qapi-introspect.py @@ -64,7 +64,7 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaVisitor): # generate C # TODO can generate awfully long lines jsons.extend(self._jsons) - name = prefix + 'qmp_schema_json' + name = c_name(prefix, protect=False) + 'qmp_schema_json' self.decl = mcgen(''' extern const char %(c_name)s[]; ''', -- cgit v1.1 From 048abb7b20c9f822ad9d4b730bade73b3311a47a Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 3 Mar 2017 13:32:39 +0100 Subject: qapi: Drop unused non-strict qobject input visitor The split between tests/test-qobject-input-visitor.c and tests/test-qobject-input-strict.c now makes less sense than ever. The next commit will take care of that. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Message-Id: <1488544368-30622-20-git-send-email-armbru@redhat.com> --- scripts/qapi-commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index 2b062ad..0c05449 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -130,7 +130,7 @@ def gen_marshal(name, arg_type, boxed, ret_type): push_indent() ret += mcgen(''' - v = qobject_input_visitor_new(QOBJECT(args), true); + v = qobject_input_visitor_new(QOBJECT(args)); visit_start_struct(v, NULL, NULL, 0, &err); if (err) { goto out; -- cgit v1.1 From a4a1c70dc759e5b81627e96564f344ab43ea86eb Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 3 Mar 2017 13:32:45 +0100 Subject: qapi: Make input visitors detect unvisited list tails Fix the design flaw demonstrated in the previous commit: new method check_list() lets input visitors report that unvisited input remains for a list, exactly like check_struct() lets them report that unvisited input remains for a struct or union. Implement the method for the qobject input visitor (straightforward), and the string input visitor (less so, due to the magic list syntax there). The opts visitor's list magic is even more impenetrable, and all I can do there today is a stub with a FIXME comment. No worse than before. Signed-off-by: Markus Armbruster Message-Id: <1488544368-30622-26-git-send-email-armbru@redhat.com> Reviewed-by: Eric Blake --- scripts/qapi-visit.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'scripts') diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index 96f2491..330b9f3 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -133,6 +133,9 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error } } + if (!err) { + visit_check_list(v, &err); + } visit_end_list(v, (void **)obj); if (err && visit_is_input(v)) { qapi_free_%(c_name)s(*obj); -- cgit v1.1