<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Oct 25, 2021 at 1:25 AM Markus Armbruster <<a href="mailto:armbru@redhat.com">armbru@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">The code to check command policy can see special feature flag<br>
'deprecated' as command flag QCO_DEPRECATED.  I want to make feature<br>
flag 'unstable' visible there as well, so I can add policy for it.<br>
<br>
To let me make it visible, add member @special_features (a bitset of<br>
QapiSpecialFeature) to QmpCommand, and adjust the generator to pass it<br>
through qmp_register_command().  Then replace "QCO_DEPRECATED in<br>
@flags" by QAPI_DEPRECATED in @special_features", and drop<br>
QCO_DEPRECATED.<br>
<br>
Signed-off-by: Markus Armbruster <<a href="mailto:armbru@redhat.com" target="_blank">armbru@redhat.com</a>><br>
---<br>
 include/qapi/qmp/dispatch.h          | 5 +++--<br>
 monitor/misc.c                       | 6 ++++--<br>
 qapi/qmp-dispatch.c                  | 2 +-<br>
 qapi/qmp-registry.c                  | 4 +++-<br>
 storage-daemon/qemu-storage-daemon.c | 3 ++-<br>
 scripts/qapi/commands.py             | 9 ++++-----<br>
 6 files changed, 17 insertions(+), 12 deletions(-)<br>
<br>
diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h<br>
index 0ce88200b9..1e4240fd0d 100644<br>
--- a/include/qapi/qmp/dispatch.h<br>
+++ b/include/qapi/qmp/dispatch.h<br>
@@ -25,7 +25,6 @@ typedef enum QmpCommandOptions<br>
     QCO_ALLOW_OOB             =  (1U << 1),<br>
     QCO_ALLOW_PRECONFIG       =  (1U << 2),<br>
     QCO_COROUTINE             =  (1U << 3),<br>
-    QCO_DEPRECATED            =  (1U << 4),<br>
 } QmpCommandOptions;<br>
<br>
 typedef struct QmpCommand<br>
@@ -34,6 +33,7 @@ typedef struct QmpCommand<br>
     /* Runs in coroutine context if QCO_COROUTINE is set */<br>
     QmpCommandFunc *fn;<br>
     QmpCommandOptions options;<br>
+    unsigned special_features;<br>
     QTAILQ_ENTRY(QmpCommand) node;<br>
     bool enabled;<br>
     const char *disable_reason;<br>
@@ -42,7 +42,8 @@ typedef struct QmpCommand<br>
 typedef QTAILQ_HEAD(QmpCommandList, QmpCommand) QmpCommandList;<br>
<br>
 void qmp_register_command(QmpCommandList *cmds, const char *name,<br>
-                          QmpCommandFunc *fn, QmpCommandOptions options);<br>
+                          QmpCommandFunc *fn, QmpCommandOptions options,<br>
+                          unsigned special_features);<br>
 const QmpCommand *qmp_find_command(const QmpCommandList *cmds,<br>
                                    const char *name);<br>
 void qmp_disable_command(QmpCommandList *cmds, const char *name,<br>
diff --git a/monitor/misc.c b/monitor/misc.c<br>
index 3556b177f6..c2d227a07c 100644<br>
--- a/monitor/misc.c<br>
+++ b/monitor/misc.c<br>
@@ -230,11 +230,13 @@ static void monitor_init_qmp_commands(void)<br>
<br>
     qmp_init_marshal(&qmp_commands);<br>
<br>
-    qmp_register_command(&qmp_commands, "device_add", qmp_device_add, 0);<br>
+    qmp_register_command(&qmp_commands, "device_add",<br>
+                         qmp_device_add, 0, 0);<br>
<br>
     QTAILQ_INIT(&qmp_cap_negotiation_commands);<br>
     qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",<br>
-                         qmp_marshal_qmp_capabilities, QCO_ALLOW_PRECONFIG);<br>
+                         qmp_marshal_qmp_capabilities,<br>
+                         QCO_ALLOW_PRECONFIG, 0);<br>
 }<br>
<br>
 /* Set the current CPU defined by the user. Callers must hold BQL. */<br>
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c<br>
index 7e943a0af5..8cca18c891 100644<br>
--- a/qapi/qmp-dispatch.c<br>
+++ b/qapi/qmp-dispatch.c<br>
@@ -176,7 +176,7 @@ QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request,<br>
                   "The command %s has not been found", command);<br>
         goto out;<br>
     }<br>
-    if (cmd->options & QCO_DEPRECATED) {<br>
+    if (cmd->special_features & 1u << QAPI_DEPRECATED) {<br>
         switch (compat_policy.deprecated_input) {<br>
         case COMPAT_POLICY_INPUT_ACCEPT:<br>
             break;<br>
diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c<br>
index f78c064aae..485bc5e6fc 100644<br>
--- a/qapi/qmp-registry.c<br>
+++ b/qapi/qmp-registry.c<br>
@@ -16,7 +16,8 @@<br>
 #include "qapi/qmp/dispatch.h"<br>
<br>
 void qmp_register_command(QmpCommandList *cmds, const char *name,<br>
-                          QmpCommandFunc *fn, QmpCommandOptions options)<br>
+                          QmpCommandFunc *fn, QmpCommandOptions options,<br>
+                          unsigned special_features)<br>
 {<br>
     QmpCommand *cmd = g_malloc0(sizeof(*cmd));<br>
<br>
@@ -27,6 +28,7 @@ void qmp_register_command(QmpCommandList *cmds, const char *name,<br>
     cmd->fn = fn;<br>
     cmd->enabled = true;<br>
     cmd->options = options;<br>
+    cmd->special_features = special_features;<br>
     QTAILQ_INSERT_TAIL(cmds, cmd, node);<br>
 }<br>
<br>
diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c<br>
index 10a1a33761..52cf17e8ac 100644<br>
--- a/storage-daemon/qemu-storage-daemon.c<br>
+++ b/storage-daemon/qemu-storage-daemon.c<br>
@@ -146,7 +146,8 @@ static void init_qmp_commands(void)<br>
<br>
     QTAILQ_INIT(&qmp_cap_negotiation_commands);<br>
     qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",<br>
-                         qmp_marshal_qmp_capabilities, QCO_ALLOW_PRECONFIG);<br>
+                         qmp_marshal_qmp_capabilities,<br>
+                         QCO_ALLOW_PRECONFIG, 0);<br>
 }<br>
<br>
 static int getopt_set_loc(int argc, char **argv, const char *optstring,<br>
diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py<br>
index c8a975528f..21001bbd6b 100644<br>
--- a/scripts/qapi/commands.py<br>
+++ b/scripts/qapi/commands.py<br>
@@ -26,6 +26,7 @@<br>
     QAPISchemaModularCVisitor,<br>
     build_params,<br>
     ifcontext,<br>
+    gen_special_features,<br>
 )<br>
 from .schema import (<br>
     QAPISchema,<br>
@@ -217,9 +218,6 @@ def gen_register_command(name: str,<br>
                          coroutine: bool) -> str:<br>
     options = []<br>
<br>
-    if 'deprecated' in [<a href="http://f.name" rel="noreferrer" target="_blank">f.name</a> for f in features]:<br>
-        options += ['QCO_DEPRECATED']<br>
-<br>
     if not success_response:<br>
         options += ['QCO_NO_SUCCESS_RESP']<br>
     if allow_oob:<br>
@@ -231,10 +229,11 @@ def gen_register_command(name: str,<br>
<br>
     ret = mcgen('''<br>
     qmp_register_command(cmds, "%(name)s",<br>
-                         qmp_marshal_%(c_name)s, %(opts)s);<br>
+                         qmp_marshal_%(c_name)s, %(opts)s, %(feats)s);<br>
 ''',<br>
                 name=name, c_name=c_name(name),<br>
-                opts=' | '.join(options) or 0)<br>
+                opts=' | '.join(options) or 0,<br>
+                feats=gen_special_features(features))<br></blockquote><div><br></div><div>Ah, you use the '0' return here. Alright then.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
     return ret<br>
<br>
<br>
-- <br>
2.31.1<br>
<br></blockquote><div><br></div><div>Python bits: Acked-by: John Snow <<a href="mailto:jsnow@redhat.com">jsnow@redhat.com</a>></div><div>C bits: "I believe in my heart that they probably work."<br></div><div><br></div><div>(for this and previous patch.)<br></div></div></div>