[PATCH v2 4/5] qapi: Implement deprecated-input={reject, crash} for enum values

Markus Armbruster posted 5 patches 1 month, 4 weeks ago

[PATCH v2 4/5] qapi: Implement deprecated-input={reject, crash} for enum values

Posted by Markus Armbruster 1 month, 4 weeks ago
This copies the code implementing the policy from qapi/qmp-dispatch.c
to qapi/qobject-input-visitor.c.  Tolerable, but if we acquire more
copes, we should look into factoring them out.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 docs/devel/qapi-code-gen.rst |  6 ++++--
 qapi/compat.json             |  3 ++-
 include/qapi/util.h          |  6 +++++-
 qapi/qapi-visit-core.c       | 18 +++++++++++++++---
 scripts/qapi/types.py        | 17 ++++++++++++++++-
 5 files changed, 42 insertions(+), 8 deletions(-)

diff --git a/docs/devel/qapi-code-gen.rst b/docs/devel/qapi-code-gen.rst
index 00334e9fb8..006a6f4a9a 100644
--- a/docs/devel/qapi-code-gen.rst
+++ b/docs/devel/qapi-code-gen.rst
@@ -708,8 +708,10 @@ QEMU shows a certain behaviour.
 Special features
 ~~~~~~~~~~~~~~~~
 
-Feature "deprecated" marks a command, event, or struct member as
-deprecated.  It is not supported elsewhere so far.
+Feature "deprecated" marks a command, event, struct or enum member as
+deprecated.  It is not supported elsewhere so far.  Interfaces so
+marked may be withdrawn in future releases in accordance with QEMU's
+deprecation policy.
 
 
 Naming rules and reserved names
diff --git a/qapi/compat.json b/qapi/compat.json
index 1d2b76f00c..74a8493d3d 100644
--- a/qapi/compat.json
+++ b/qapi/compat.json
@@ -42,7 +42,8 @@
 # with feature 'deprecated'.  We may want to extend it to cover
 # semantic aspects, CLI, and experimental features.
 #
-# Limitation: not implemented for deprecated enumeration values.
+# Limitation: deprecated-output policy @hide is not implemented for
+# enumeration values.  They behave the same as with policy @accept.
 #
 # @deprecated-input: how to handle deprecated input (default 'accept')
 # @deprecated-output: how to handle deprecated output (default 'accept')
diff --git a/include/qapi/util.h b/include/qapi/util.h
index d7bfb30e25..257c600f99 100644
--- a/include/qapi/util.h
+++ b/include/qapi/util.h
@@ -11,9 +11,13 @@
 #ifndef QAPI_UTIL_H
 #define QAPI_UTIL_H
 
+/* QEnumLookup flags */
+#define QAPI_ENUM_DEPRECATED 1
+
 typedef struct QEnumLookup {
     const char *const *array;
-    int size;
+    const unsigned char *const flags;
+    const int size;
 } QEnumLookup;
 
 const char *qapi_enum_lookup(const QEnumLookup *lookup, int val);
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index 066f77a26d..49136ae88e 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -393,7 +393,7 @@ static bool input_type_enum(Visitor *v, const char *name, int *obj,
                             const QEnumLookup *lookup, Error **errp)
 {
     int64_t value;
-    char *enum_str;
+    g_autofree char *enum_str = NULL;
 
     if (!visit_type_str(v, name, &enum_str, errp)) {
         return false;
@@ -402,11 +402,23 @@ static bool input_type_enum(Visitor *v, const char *name, int *obj,
     value = qapi_enum_parse(lookup, enum_str, -1, NULL);
     if (value < 0) {
         error_setg(errp, QERR_INVALID_PARAMETER, enum_str);
-        g_free(enum_str);
         return false;
     }
 
-    g_free(enum_str);
+    if (lookup->flags && (lookup->flags[value] & QAPI_ENUM_DEPRECATED)) {
+        switch (v->compat_policy.deprecated_input) {
+        case COMPAT_POLICY_INPUT_ACCEPT:
+            break;
+        case COMPAT_POLICY_INPUT_REJECT:
+            error_setg(errp, "Deprecated value '%s' disabled by policy",
+                       enum_str);
+            return false;
+        case COMPAT_POLICY_INPUT_CRASH:
+        default:
+            abort();
+        }
+    }
+
     *obj = value;
     return true;
 }
diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index 831294fe42..ab2441adc9 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -38,6 +38,8 @@
 def gen_enum_lookup(name: str,
                     members: List[QAPISchemaEnumMember],
                     prefix: Optional[str] = None) -> str:
+    max_index = c_enum_const(name, '_MAX', prefix)
+    flags = ''
     ret = mcgen('''
 
 const QEnumLookup %(c_name)s_lookup = {
@@ -52,13 +54,26 @@ def gen_enum_lookup(name: str,
 ''',
                      index=index, name=memb.name)
         ret += memb.ifcond.gen_endif()
+        if 'deprecated' in (f.name for f in memb.features):
+            flags += mcgen('''
+        [%(index)s] = QAPI_ENUM_DEPRECATED,
+''',
+                           index=index)
+
+    if flags:
+        ret += mcgen('''
+    },
+    .flags = (const unsigned char[%(max_index)s]) {
+''',
+                     max_index=max_index)
+        ret += flags
 
     ret += mcgen('''
     },
     .size = %(max_index)s
 };
 ''',
-                 max_index=c_enum_const(name, '_MAX', prefix))
+                 max_index=max_index)
     return ret
 
 
-- 
2.31.1

Re: [PATCH v2 4/5] qapi: Implement deprecated-input={reject,crash} for enum values

Posted by Eric Blake 1 month, 3 weeks ago
On Sat, Oct 09, 2021 at 02:09:43PM +0200, Markus Armbruster wrote:
> This copies the code implementing the policy from qapi/qmp-dispatch.c
> to qapi/qobject-input-visitor.c.  Tolerable, but if we acquire more
> copes, we should look into factoring them out.

copies

> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  docs/devel/qapi-code-gen.rst |  6 ++++--
>  qapi/compat.json             |  3 ++-
>  include/qapi/util.h          |  6 +++++-
>  qapi/qapi-visit-core.c       | 18 +++++++++++++++---
>  scripts/qapi/types.py        | 17 ++++++++++++++++-
>  5 files changed, 42 insertions(+), 8 deletions(-)
> 
> diff --git a/docs/devel/qapi-code-gen.rst b/docs/devel/qapi-code-gen.rst
> index 00334e9fb8..006a6f4a9a 100644
> --- a/docs/devel/qapi-code-gen.rst
> +++ b/docs/devel/qapi-code-gen.rst
> @@ -708,8 +708,10 @@ QEMU shows a certain behaviour.
>  Special features
>  ~~~~~~~~~~~~~~~~
>  
> -Feature "deprecated" marks a command, event, or struct member as
> -deprecated.  It is not supported elsewhere so far.
> +Feature "deprecated" marks a command, event, struct or enum member as

Do we want the comma before the conjunction?  (I've seen style guides
that recommend it, and style guides that discourage it; while I tend
to write by the former style, I usually don't care about the latter.
Rather, switching styles mid-patch caught my attention).

> +deprecated.  It is not supported elsewhere so far.  Interfaces so
> +marked may be withdrawn in future releases in accordance with QEMU's
> +deprecation policy.
>  
>  
> +++ b/qapi/qapi-visit-core.c
> @@ -393,7 +393,7 @@ static bool input_type_enum(Visitor *v, const char *name, int *obj,
>                              const QEnumLookup *lookup, Error **errp)
>  {
>      int64_t value;
> -    char *enum_str;
> +    g_autofree char *enum_str = NULL;

Nice change while touching the code.  Is it worth mentioning in the
commit message?

>  
>      if (!visit_type_str(v, name, &enum_str, errp)) {
>          return false;
> @@ -402,11 +402,23 @@ static bool input_type_enum(Visitor *v, const char *name, int *obj,
>      value = qapi_enum_parse(lookup, enum_str, -1, NULL);
>      if (value < 0) {
>          error_setg(errp, QERR_INVALID_PARAMETER, enum_str);
> -        g_free(enum_str);
>          return false;
>      }
>  
> -    g_free(enum_str);
> +    if (lookup->flags && (lookup->flags[value] & QAPI_ENUM_DEPRECATED)) {
> +        switch (v->compat_policy.deprecated_input) {
> +        case COMPAT_POLICY_INPUT_ACCEPT:
> +            break;
> +        case COMPAT_POLICY_INPUT_REJECT:
> +            error_setg(errp, "Deprecated value '%s' disabled by policy",
> +                       enum_str);
> +            return false;
> +        case COMPAT_POLICY_INPUT_CRASH:
> +        default:
> +            abort();
> +        }
> +    }
> +
>      *obj = value;
>      return true;
>  }

Grammar fixes are minor, so:

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org

Re: [PATCH v2 4/5] qapi: Implement deprecated-input={reject,crash} for enum values

Posted by Markus Armbruster 1 month, 2 weeks ago
Eric Blake <eblake@redhat.com> writes:

> On Sat, Oct 09, 2021 at 02:09:43PM +0200, Markus Armbruster wrote:
>> This copies the code implementing the policy from qapi/qmp-dispatch.c
>> to qapi/qobject-input-visitor.c.  Tolerable, but if we acquire more
>> copes, we should look into factoring them out.
>
> copies

Fixing, thanks!

>> 
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>  docs/devel/qapi-code-gen.rst |  6 ++++--
>>  qapi/compat.json             |  3 ++-
>>  include/qapi/util.h          |  6 +++++-
>>  qapi/qapi-visit-core.c       | 18 +++++++++++++++---
>>  scripts/qapi/types.py        | 17 ++++++++++++++++-
>>  5 files changed, 42 insertions(+), 8 deletions(-)
>> 
>> diff --git a/docs/devel/qapi-code-gen.rst b/docs/devel/qapi-code-gen.rst
>> index 00334e9fb8..006a6f4a9a 100644
>> --- a/docs/devel/qapi-code-gen.rst
>> +++ b/docs/devel/qapi-code-gen.rst
>> @@ -708,8 +708,10 @@ QEMU shows a certain behaviour.
>>  Special features
>>  ~~~~~~~~~~~~~~~~
>>  
>> -Feature "deprecated" marks a command, event, or struct member as
>> -deprecated.  It is not supported elsewhere so far.
>> +Feature "deprecated" marks a command, event, struct or enum member as
>
> Do we want the comma before the conjunction?  (I've seen style guides
> that recommend it, and style guides that discourage it; while I tend
> to write by the former style, I usually don't care about the latter.
> Rather, switching styles mid-patch caught my attention).

With a comma there, we claim structs can be marked, which is actually
wrong.  Correct is "command, event, struct member, or enum member".

I'll rephrase to "marks a command, event, enum value, or struct member
deprecated."

>> +deprecated.  It is not supported elsewhere so far.  Interfaces so
>> +marked may be withdrawn in future releases in accordance with QEMU's
>> +deprecation policy.
>>  
>>  
>> +++ b/qapi/qapi-visit-core.c
>> @@ -393,7 +393,7 @@ static bool input_type_enum(Visitor *v, const char *name, int *obj,
>>                              const QEnumLookup *lookup, Error **errp)
>>  {
>>      int64_t value;
>> -    char *enum_str;
>> +    g_autofree char *enum_str = NULL;
>
> Nice change while touching the code.  Is it worth mentioning in the
> commit message?

I figure it would be more distracting than useful.

>>  
>>      if (!visit_type_str(v, name, &enum_str, errp)) {
>>          return false;
>> @@ -402,11 +402,23 @@ static bool input_type_enum(Visitor *v, const char *name, int *obj,
>>      value = qapi_enum_parse(lookup, enum_str, -1, NULL);
>>      if (value < 0) {
>>          error_setg(errp, QERR_INVALID_PARAMETER, enum_str);
>> -        g_free(enum_str);
>>          return false;
>>      }
>>  
>> -    g_free(enum_str);
>> +    if (lookup->flags && (lookup->flags[value] & QAPI_ENUM_DEPRECATED)) {
>> +        switch (v->compat_policy.deprecated_input) {
>> +        case COMPAT_POLICY_INPUT_ACCEPT:
>> +            break;
>> +        case COMPAT_POLICY_INPUT_REJECT:
>> +            error_setg(errp, "Deprecated value '%s' disabled by policy",
>> +                       enum_str);
>> +            return false;
>> +        case COMPAT_POLICY_INPUT_CRASH:
>> +        default:
>> +            abort();
>> +        }
>> +    }
>> +
>>      *obj = value;
>>      return true;
>>  }
>
> Grammar fixes are minor, so:
>
> Reviewed-by: Eric Blake <eblake@redhat.com>

Thanks!