From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2428AC433EF for ; Mon, 25 Oct 2021 20:30:03 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5EB2860E0B for ; Mon, 25 Oct 2021 20:30:02 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 5EB2860E0B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=nongnu.org Received: from localhost ([::1]:58934 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mf6bZ-0007KF-9j for qemu-devel@archiver.kernel.org; Mon, 25 Oct 2021 16:30:01 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:44714) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mf5eC-00019t-8P for qemu-devel@nongnu.org; Mon, 25 Oct 2021 15:28:41 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:42272) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mf5e6-00040u-1F for qemu-devel@nongnu.org; Mon, 25 Oct 2021 15:28:39 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1635190111; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=0tNvEpZ3qet9Ead1AGmc7KKOZBlFUbBeHNZO9uMqWDc=; b=hzxLwsxnnHgA2SgwWuvmXy2nSZvp1S7Fun5ztsbYg/vAqmBD15QWNZxwuwS5g1TAjHiNWU gfZCVP4gWoUC4m/0LozCb6xBh7neK8kyNLyapZPg/EFM588bJKMCMR5XPcb4TfJ6//z4O/ PXPt/jbFZ9MxpQED1yjPk0xXOifnnao= Received: from mail-ua1-f71.google.com (mail-ua1-f71.google.com [209.85.222.71]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-400-LLdPGPegMl6Bxe1ctfnW7Q-1; Mon, 25 Oct 2021 15:28:27 -0400 X-MC-Unique: LLdPGPegMl6Bxe1ctfnW7Q-1 Received: by mail-ua1-f71.google.com with SMTP id e5-20020ab04985000000b002cad81164cbso6893323uad.10 for ; Mon, 25 Oct 2021 12:28:27 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=0tNvEpZ3qet9Ead1AGmc7KKOZBlFUbBeHNZO9uMqWDc=; b=xlwyX3jYLoUQDG5Xv9G/SvU1MPBADElNwYWS7I1xerZedNUd8MiRtDu0CIdlYS343i do0IL1QM1uAeZXfef/TTbXShPrIQKYMFCxf7kV5HaXjon7zY8BLWd0f2zJ4uentF/KDT aRWEc4BZTxy8RJhg15uJn3WIsNVLKLfabXWIhUBmZZA6yAzK/fIpKMNUdqCAlXW+IAM5 uabL9YH/iB2NH1e10514vk/CZDdarY34O4dCjRIONO46tdyR+80uAYq78oTabLE0CqY4 VMyZfInvAy6LVVVFBbr343HAmb8tlOOfeM38DkvTHEj2OIfR8JEeR2178qFllVTn+WUW AVaA== X-Gm-Message-State: AOAM5302qADOMjATlIf2kyJpVOgg5shYaClzUO6WHwOKW2fmvVXLA05K seyK6M6ve/KurHFoutAl0ARURHwscHmkTSAb69maQt9JPvN8GStjURY7oaO/mQZRn1nnhW/2YlX USTqv8+odQWb0ai7q/jZiMKh6BVSHfa8= X-Received: by 2002:a67:ec94:: with SMTP id h20mr17220448vsp.59.1635190106617; Mon, 25 Oct 2021 12:28:26 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxEKYgknRBoV2B19P1ef9tPBP+SB6mE5lees9aag0CEyhy29rWvGjwKuc67+GqqR42oyQ7GUaguT+gSzzyfi3U= X-Received: by 2002:a67:ec94:: with SMTP id h20mr17220410vsp.59.1635190106359; Mon, 25 Oct 2021 12:28:26 -0700 (PDT) MIME-Version: 1.0 References: <20211025052532.3859634-1-armbru@redhat.com> <20211025052532.3859634-6-armbru@redhat.com> In-Reply-To: <20211025052532.3859634-6-armbru@redhat.com> From: John Snow Date: Mon, 25 Oct 2021 15:28:15 -0400 Message-ID: Subject: Re: [PATCH 5/9] qapi: Generalize struct member policy checking To: Markus Armbruster Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=jsnow@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: multipart/alternative; boundary="0000000000006e1e2b05cf325dcc" Received-SPF: pass client-ip=170.10.133.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , pkrempa@redhat.com, Daniel Berrange , Eduardo Habkost , qemu-block@nongnu.org, Juan Quintela , libvir-list@redhat.com, qemu-devel , mdroth@linux.vnet.ibm.com, "Dr. David Alan Gilbert" , Paolo Bonzini , =?UTF-8?B?TWFyYy1BbmRyw6kgTHVyZWF1?= , Eric Blake , libguestfs@redhat.com Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" --0000000000006e1e2b05cf325dcc Content-Type: text/plain; charset="UTF-8" On Mon, Oct 25, 2021 at 1:25 AM Markus Armbruster wrote: > The generated visitor functions call visit_deprecated_accept() and > visit_deprecated() when visiting a struct member with special feature > flag 'deprecated'. This makes the feature flag visible to the actual > visitors. I want to make feature flag 'unstable' visible there as > well, so I can add policy for it. > > To let me make it visible, replace these functions by > visit_policy_reject() and visit_policy_skip(), which take the member's > special features as an argument. Note that the new functions have the > opposite sense, i.e. the return value flips. > > Signed-off-by: Markus Armbruster > --- > include/qapi/visitor-impl.h | 6 ++++-- > include/qapi/visitor.h | 17 +++++++++++++---- > qapi/qapi-forward-visitor.c | 16 +++++++++------- > qapi/qapi-visit-core.c | 22 ++++++++++++---------- > qapi/qobject-input-visitor.c | 15 ++++++++++----- > qapi/qobject-output-visitor.c | 9 ++++++--- > qapi/trace-events | 4 ++-- > scripts/qapi/visit.py | 14 +++++++------- > 8 files changed, 63 insertions(+), 40 deletions(-) > > diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h > index 72b6537bef..2badec5ba4 100644 > --- a/include/qapi/visitor-impl.h > +++ b/include/qapi/visitor-impl.h > @@ -114,10 +114,12 @@ struct Visitor > void (*optional)(Visitor *v, const char *name, bool *present); > > /* Optional */ > - bool (*deprecated_accept)(Visitor *v, const char *name, Error **errp); > + bool (*policy_reject)(Visitor *v, const char *name, > + unsigned special_features, Error **errp); > > /* Optional */ > - bool (*deprecated)(Visitor *v, const char *name); > + bool (*policy_skip)(Visitor *v, const char *name, > + unsigned special_features); > > /* Must be set */ > VisitorType type; > diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h > index dcb96018a9..d53a84c9ba 100644 > --- a/include/qapi/visitor.h > +++ b/include/qapi/visitor.h > @@ -461,22 +461,31 @@ void visit_end_alternate(Visitor *v, void **obj); > bool visit_optional(Visitor *v, const char *name, bool *present); > > /* > - * Should we reject deprecated member @name? > + * Should we reject member @name due to policy? > + * > + * @special_features is the member's special features encoded as a > + * bitset of QapiSpecialFeature. > * > * @name must not be NULL. This function is only useful between > * visit_start_struct() and visit_end_struct(), since only objects > * have deprecated members. > */ > -bool visit_deprecated_accept(Visitor *v, const char *name, Error **errp); > +bool visit_policy_reject(Visitor *v, const char *name, > + unsigned special_features, Error **errp); > > /* > - * Should we visit deprecated member @name? > + * > + * Should we skip member @name due to policy? > + * > + * @special_features is the member's special features encoded as a > + * bitset of QapiSpecialFeature. > * > * @name must not be NULL. This function is only useful between > * visit_start_struct() and visit_end_struct(), since only objects > * have deprecated members. > */ > -bool visit_deprecated(Visitor *v, const char *name); > +bool visit_policy_skip(Visitor *v, const char *name, > + unsigned special_features); > > /* > * Set policy for handling deprecated management interfaces. > diff --git a/qapi/qapi-forward-visitor.c b/qapi/qapi-forward-visitor.c > index a4b111e22a..25d098aa8a 100644 > --- a/qapi/qapi-forward-visitor.c > +++ b/qapi/qapi-forward-visitor.c > @@ -246,25 +246,27 @@ static void forward_field_optional(Visitor *v, const > char *name, bool *present) > visit_optional(ffv->target, name, present); > } > > -static bool forward_field_deprecated_accept(Visitor *v, const char *name, > - Error **errp) > +static bool forward_field_policy_reject(Visitor *v, const char *name, > + unsigned special_features, > + Error **errp) > { > ForwardFieldVisitor *ffv = to_ffv(v); > > if (!forward_field_translate_name(ffv, &name, errp)) { > return false; > } > - return visit_deprecated_accept(ffv->target, name, errp); > + return visit_policy_reject(ffv->target, name, special_features, errp); > } > > -static bool forward_field_deprecated(Visitor *v, const char *name) > +static bool forward_field_policy_skip(Visitor *v, const char *name, > + unsigned special_features) > { > ForwardFieldVisitor *ffv = to_ffv(v); > > if (!forward_field_translate_name(ffv, &name, NULL)) { > return false; > } > - return visit_deprecated(ffv->target, name); > + return visit_policy_skip(ffv->target, name, special_features); > } > > static void forward_field_complete(Visitor *v, void *opaque) > @@ -313,8 +315,8 @@ Visitor *visitor_forward_field(Visitor *target, const > char *from, const char *to > v->visitor.type_any = forward_field_type_any; > v->visitor.type_null = forward_field_type_null; > v->visitor.optional = forward_field_optional; > - v->visitor.deprecated_accept = forward_field_deprecated_accept; > - v->visitor.deprecated = forward_field_deprecated; > + v->visitor.policy_reject = forward_field_policy_reject; > + v->visitor.policy_skip = forward_field_policy_skip; > v->visitor.complete = forward_field_complete; > v->visitor.free = forward_field_free; > > diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c > index 49136ae88e..b4a81f1757 100644 > --- a/qapi/qapi-visit-core.c > +++ b/qapi/qapi-visit-core.c > @@ -139,22 +139,24 @@ bool visit_optional(Visitor *v, const char *name, > bool *present) > return *present; > } > > -bool visit_deprecated_accept(Visitor *v, const char *name, Error **errp) > +bool visit_policy_reject(Visitor *v, const char *name, > + unsigned special_features, Error **errp) > { > - trace_visit_deprecated_accept(v, name); > - if (v->deprecated_accept) { > - return v->deprecated_accept(v, name, errp); > + trace_visit_policy_reject(v, name); > + if (v->policy_reject) { > + return v->policy_reject(v, name, special_features, errp); > } > - return true; > + return false; > } > > -bool visit_deprecated(Visitor *v, const char *name) > +bool visit_policy_skip(Visitor *v, const char *name, > + unsigned special_features) > { > - trace_visit_deprecated(v, name); > - if (v->deprecated) { > - return v->deprecated(v, name); > + trace_visit_policy_skip(v, name); > + if (v->policy_skip) { > + return v->policy_skip(v, name, special_features); > } > - return true; > + return false; > } > > void visit_set_policy(Visitor *v, CompatPolicy *policy) > diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c > index 71b24a4429..fda485614b 100644 > --- a/qapi/qobject-input-visitor.c > +++ b/qapi/qobject-input-visitor.c > @@ -662,16 +662,21 @@ static void qobject_input_optional(Visitor *v, const > char *name, bool *present) > *present = true; > } > > -static bool qobject_input_deprecated_accept(Visitor *v, const char *name, > - Error **errp) > +static bool qobject_input_policy_reject(Visitor *v, const char *name, > + unsigned special_features, > + Error **errp) > { > + if (!(special_features && 1u << QAPI_DEPRECATED)) { > + return false; > + } > + > switch (v->compat_policy.deprecated_input) { > case COMPAT_POLICY_INPUT_ACCEPT: > - return true; > + return false; > case COMPAT_POLICY_INPUT_REJECT: > error_setg(errp, "Deprecated parameter '%s' disabled by policy", > name); > - return false; > + return true; > case COMPAT_POLICY_INPUT_CRASH: > default: > abort(); > @@ -712,7 +717,7 @@ static QObjectInputVisitor > *qobject_input_visitor_base_new(QObject *obj) > v->visitor.end_list = qobject_input_end_list; > v->visitor.start_alternate = qobject_input_start_alternate; > v->visitor.optional = qobject_input_optional; > - v->visitor.deprecated_accept = qobject_input_deprecated_accept; > + v->visitor.policy_reject = qobject_input_policy_reject; > v->visitor.free = qobject_input_free; > > v->root = qobject_ref(obj); > diff --git a/qapi/qobject-output-visitor.c b/qapi/qobject-output-visitor.c > index 9b7f510036..b5c6564cbb 100644 > --- a/qapi/qobject-output-visitor.c > +++ b/qapi/qobject-output-visitor.c > @@ -13,6 +13,7 @@ > */ > > #include "qemu/osdep.h" > +#include "qapi/compat-policy.h" > #include "qapi/qobject-output-visitor.h" > #include "qapi/visitor-impl.h" > #include "qemu/queue.h" > @@ -208,9 +209,11 @@ static bool qobject_output_type_null(Visitor *v, > const char *name, > return true; > } > > -static bool qobject_output_deprecated(Visitor *v, const char *name) > +static bool qobject_output_policy_skip(Visitor *v, const char *name, > + unsigned special_features) > { > - return v->compat_policy.deprecated_output != > COMPAT_POLICY_OUTPUT_HIDE; > + return !(special_features && 1u << QAPI_DEPRECATED) > + || v->compat_policy.deprecated_output == > COMPAT_POLICY_OUTPUT_HIDE; > } > > /* Finish building, and return the root object. > @@ -262,7 +265,7 @@ Visitor *qobject_output_visitor_new(QObject **result) > v->visitor.type_number = qobject_output_type_number; > v->visitor.type_any = qobject_output_type_any; > v->visitor.type_null = qobject_output_type_null; > - v->visitor.deprecated = qobject_output_deprecated; > + v->visitor.policy_skip = qobject_output_policy_skip; > v->visitor.complete = qobject_output_complete; > v->visitor.free = qobject_output_free; > > diff --git a/qapi/trace-events b/qapi/trace-events > index cccafc07e5..ab108c4f0e 100644 > --- a/qapi/trace-events > +++ b/qapi/trace-events > @@ -17,8 +17,8 @@ visit_start_alternate(void *v, const char *name, void > *obj, size_t size) "v=%p n > visit_end_alternate(void *v, void *obj) "v=%p obj=%p" > > visit_optional(void *v, const char *name, bool *present) "v=%p name=%s > present=%p" > -visit_deprecated_accept(void *v, const char *name) "v=%p name=%s" > -visit_deprecated(void *v, const char *name) "v=%p name=%s" > +visit_policy_reject(void *v, const char *name) "v=%p name=%s" > +visit_policy_skip(void *v, const char *name) "v=%p name=%s" > > visit_type_enum(void *v, const char *name, int *obj) "v=%p name=%s obj=%p" > visit_type_int(void *v, const char *name, int64_t *obj) "v=%p name=%s > obj=%p" > diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py > index 9d9196a143..e13bbe4292 100644 > --- a/scripts/qapi/visit.py > +++ b/scripts/qapi/visit.py > @@ -21,7 +21,7 @@ > indent, > mcgen, > ) > -from .gen import QAPISchemaModularCVisitor, ifcontext > +from .gen import QAPISchemaModularCVisitor, gen_special_features, > ifcontext > from .schema import ( > QAPISchema, > QAPISchemaEnumMember, > @@ -76,7 +76,6 @@ def gen_visit_object_members(name: str, > c_type=base.c_name()) > > for memb in members: > - deprecated = 'deprecated' in [f.name for f in memb.features] > ret += memb.ifcond.gen_if() > if memb.optional: > ret += mcgen(''' > @@ -84,14 +83,15 @@ def gen_visit_object_members(name: str, > ''', > name=memb.name, c_name=c_name(memb.name)) > indent.increase() > - if deprecated: > + special_features = gen_special_features(memb.features) > + if special_features != '0': > Would it be possible for gen_special_features to return something false-y instead of '0'? Do we actually *use* the '0' return anywhere other than to test it to see if we should include additional code? If you actually use the '0' anywhere: Go ahead and treat this as an ack. If you don't, can we clean this up? (Sorry, I find the mcgen stuff hard to read in patch form and I am trying to give you a quick review instead of NO review.) --js > ret += mcgen(''' > - if (!visit_deprecated_accept(v, "%(name)s", errp)) { > + if (visit_policy_reject(v, "%(name)s", %(special_features)s, errp)) { > return false; > } > - if (visit_deprecated(v, "%(name)s")) { > + if (!visit_policy_skip(v, "%(name)s", %(special_features)s)) { > ''', > - name=memb.name) > + name=memb.name, > special_features=special_features) > indent.increase() > ret += mcgen(''' > if (!visit_type_%(c_type)s(v, "%(name)s", &obj->%(c_name)s, errp)) { > @@ -100,7 +100,7 @@ def gen_visit_object_members(name: str, > ''', > c_type=memb.type.c_name(), name=memb.name, > c_name=c_name(memb.name)) > - if deprecated: > + if special_features != '0': > indent.decrease() > ret += mcgen(''' > } > -- > 2.31.1 > > --0000000000006e1e2b05cf325dcc Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable


=
On Mon, Oct 25, 2021 at 1:25 AM Marku= s Armbruster <armbru@redhat.com= > wrote:
The = generated visitor functions call visit_deprecated_accept() and
visit_deprecated() when visiting a struct member with special feature
flag 'deprecated'.=C2=A0 This makes the feature flag visible to the= actual
visitors.=C2=A0 I want to make feature flag 'unstable' visible ther= e as
well, so I can add policy for it.

To let me make it visible, replace these functions by
visit_policy_reject() and visit_policy_skip(), which take the member's<= br> special features as an argument.=C2=A0 Note that the new functions have the=
opposite sense, i.e. the return value flips.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
=C2=A0include/qapi/visitor-impl.h=C2=A0 =C2=A0|=C2=A0 6 ++++--
=C2=A0include/qapi/visitor.h=C2=A0 =C2=A0 =C2=A0 =C2=A0 | 17 +++++++++++++-= ---
=C2=A0qapi/qapi-forward-visitor.c=C2=A0 =C2=A0| 16 +++++++++-------
=C2=A0qapi/qapi-visit-core.c=C2=A0 =C2=A0 =C2=A0 =C2=A0 | 22 ++++++++++++--= --------
=C2=A0qapi/qobject-input-visitor.c=C2=A0 | 15 ++++++++++-----
=C2=A0qapi/qobject-output-visitor.c |=C2=A0 9 ++++++---
=C2=A0qapi/trace-events=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0|=C2= =A0 4 ++--
=C2=A0scripts/qapi/visit.py=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0| 14 +++++++--= -----
=C2=A08 files changed, 63 insertions(+), 40 deletions(-)

diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h
index 72b6537bef..2badec5ba4 100644
--- a/include/qapi/visitor-impl.h
+++ b/include/qapi/visitor-impl.h
@@ -114,10 +114,12 @@ struct Visitor
=C2=A0 =C2=A0 =C2=A0void (*optional)(Visitor *v, const char *name, bool *pr= esent);

=C2=A0 =C2=A0 =C2=A0/* Optional */
-=C2=A0 =C2=A0 bool (*deprecated_accept)(Visitor *v, const char *name, Erro= r **errp);
+=C2=A0 =C2=A0 bool (*policy_reject)(Visitor *v, const char *name,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 unsigned special_features, Error **errp);

=C2=A0 =C2=A0 =C2=A0/* Optional */
-=C2=A0 =C2=A0 bool (*deprecated)(Visitor *v, const char *name);
+=C2=A0 =C2=A0 bool (*policy_skip)(Visitor *v, const char *name,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 unsigned special_features);

=C2=A0 =C2=A0 =C2=A0/* Must be set */
=C2=A0 =C2=A0 =C2=A0VisitorType type;
diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index dcb96018a9..d53a84c9ba 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -461,22 +461,31 @@ void visit_end_alternate(Visitor *v, void **obj);
=C2=A0bool visit_optional(Visitor *v, const char *name, bool *present);

=C2=A0/*
- * Should we reject deprecated member @name?
+ * Should we reject member @name due to policy?
+ *
+ * @special_features is the member's special features encoded as a
+ * bitset of QapiSpecialFeature.
=C2=A0 *
=C2=A0 * @name must not be NULL.=C2=A0 This function is only useful between=
=C2=A0 * visit_start_struct() and visit_end_struct(), since only objects =C2=A0 * have deprecated members.
=C2=A0 */
-bool visit_deprecated_accept(Visitor *v, const char *name, Error **errp);<= br> +bool visit_policy_reject(Visitor *v, const char *name,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0unsigned special_features, Error **errp);

=C2=A0/*
- * Should we visit deprecated member @name?
+ *
+ * Should we skip member @name due to policy?
+ *
+ * @special_features is the member's special features encoded as a
+ * bitset of QapiSpecialFeature.
=C2=A0 *
=C2=A0 * @name must not be NULL.=C2=A0 This function is only useful between=
=C2=A0 * visit_start_struct() and visit_end_struct(), since only objects =C2=A0 * have deprecated members.
=C2=A0 */
-bool visit_deprecated(Visitor *v, const char *name);
+bool visit_policy_skip(Visitor *v, const char *name,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0unsigned special_features);

=C2=A0/*
=C2=A0 * Set policy for handling deprecated management interfaces.
diff --git a/qapi/qapi-forward-visitor.c b/qapi/qapi-forward-visitor.c
index a4b111e22a..25d098aa8a 100644
--- a/qapi/qapi-forward-visitor.c
+++ b/qapi/qapi-forward-visitor.c
@@ -246,25 +246,27 @@ static void forward_field_optional(Visitor *v, const = char *name, bool *present)
=C2=A0 =C2=A0 =C2=A0visit_optional(ffv->target, name, present);
=C2=A0}

-static bool forward_field_deprecated_accept(Visitor *v, const char *name,<= br> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 Error **errp)
+static bool forward_field_policy_reject(Visitor *v, const char *name,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 unsigned= special_features,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Error **= errp)
=C2=A0{
=C2=A0 =C2=A0 =C2=A0ForwardFieldVisitor *ffv =3D to_ffv(v);

=C2=A0 =C2=A0 =C2=A0if (!forward_field_translate_name(ffv, &name, errp)= ) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return false;
=C2=A0 =C2=A0 =C2=A0}
-=C2=A0 =C2=A0 return visit_deprecated_accept(ffv->target, name, errp);<= br> +=C2=A0 =C2=A0 return visit_policy_reject(ffv->target, name, special_fea= tures, errp);
=C2=A0}

-static bool forward_field_deprecated(Visitor *v, const char *name)
+static bool forward_field_policy_skip(Visitor *v, const char *name,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 unsigned specia= l_features)
=C2=A0{
=C2=A0 =C2=A0 =C2=A0ForwardFieldVisitor *ffv =3D to_ffv(v);

=C2=A0 =C2=A0 =C2=A0if (!forward_field_translate_name(ffv, &name, NULL)= ) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return false;
=C2=A0 =C2=A0 =C2=A0}
-=C2=A0 =C2=A0 return visit_deprecated(ffv->target, name);
+=C2=A0 =C2=A0 return visit_policy_skip(ffv->target, name, special_featu= res);
=C2=A0}

=C2=A0static void forward_field_complete(Visitor *v, void *opaque)
@@ -313,8 +315,8 @@ Visitor *visitor_forward_field(Visitor *target, const c= har *from, const char *to
=C2=A0 =C2=A0 =C2=A0v->visitor.type_any =3D forward_field_type_any;
=C2=A0 =C2=A0 =C2=A0v->visitor.type_null =3D forward_field_type_null; =C2=A0 =C2=A0 =C2=A0v->visitor.optional =3D forward_field_optional;
-=C2=A0 =C2=A0 v->visitor.deprecated_accept =3D forward_field_deprecated= _accept;
-=C2=A0 =C2=A0 v->visitor.deprecated =3D forward_field_deprecated;
+=C2=A0 =C2=A0 v->visitor.policy_reject =3D forward_field_policy_reject;=
+=C2=A0 =C2=A0 v->visitor.policy_skip =3D forward_field_policy_skip;
=C2=A0 =C2=A0 =C2=A0v->visitor.complete =3D forward_field_complete;
=C2=A0 =C2=A0 =C2=A0v->visitor.free =3D forward_field_free;

diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index 49136ae88e..b4a81f1757 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -139,22 +139,24 @@ bool visit_optional(Visitor *v, const char *name, boo= l *present)
=C2=A0 =C2=A0 =C2=A0return *present;
=C2=A0}

-bool visit_deprecated_accept(Visitor *v, const char *name, Error **errp) +bool visit_policy_reject(Visitor *v, const char *name,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0unsigned special_features, Error **errp)
=C2=A0{
-=C2=A0 =C2=A0 trace_visit_deprecated_accept(v, name);
-=C2=A0 =C2=A0 if (v->deprecated_accept) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 return v->deprecated_accept(v, name, errp);=
+=C2=A0 =C2=A0 trace_visit_policy_reject(v, name);
+=C2=A0 =C2=A0 if (v->policy_reject) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return v->policy_reject(v, name, special_fe= atures, errp);
=C2=A0 =C2=A0 =C2=A0}
-=C2=A0 =C2=A0 return true;
+=C2=A0 =C2=A0 return false;
=C2=A0}

-bool visit_deprecated(Visitor *v, const char *name)
+bool visit_policy_skip(Visitor *v, const char *name,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0unsigned special_features)
=C2=A0{
-=C2=A0 =C2=A0 trace_visit_deprecated(v, name);
-=C2=A0 =C2=A0 if (v->deprecated) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 return v->deprecated(v, name);
+=C2=A0 =C2=A0 trace_visit_policy_skip(v, name);
+=C2=A0 =C2=A0 if (v->policy_skip) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return v->policy_skip(v, name, special_feat= ures);
=C2=A0 =C2=A0 =C2=A0}
-=C2=A0 =C2=A0 return true;
+=C2=A0 =C2=A0 return false;
=C2=A0}

=C2=A0void visit_set_policy(Visitor *v, CompatPolicy *policy)
diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index 71b24a4429..fda485614b 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -662,16 +662,21 @@ static void qobject_input_optional(Visitor *v, const = char *name, bool *present)
=C2=A0 =C2=A0 =C2=A0*present =3D true;
=C2=A0}

-static bool qobject_input_deprecated_accept(Visitor *v, const char *name,<= br> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 Error **errp)
+static bool qobject_input_policy_reject(Visitor *v, const char *name,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 unsigned= special_features,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Error **= errp)
=C2=A0{
+=C2=A0 =C2=A0 if (!(special_features && 1u << QAPI_DEPRECATE= D)) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return false;
+=C2=A0 =C2=A0 }
+
=C2=A0 =C2=A0 =C2=A0switch (v->compat_policy.deprecated_input) {
=C2=A0 =C2=A0 =C2=A0case COMPAT_POLICY_INPUT_ACCEPT:
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 return true;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return false;
=C2=A0 =C2=A0 =C2=A0case COMPAT_POLICY_INPUT_REJECT:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0error_setg(errp, "Deprecated paramet= er '%s' disabled by policy",
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 name)= ;
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 return false;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return true;
=C2=A0 =C2=A0 =C2=A0case COMPAT_POLICY_INPUT_CRASH:
=C2=A0 =C2=A0 =C2=A0default:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0abort();
@@ -712,7 +717,7 @@ static QObjectInputVisitor *qobject_input_visitor_base_= new(QObject *obj)
=C2=A0 =C2=A0 =C2=A0v->visitor.end_list =3D qobject_input_end_list;
=C2=A0 =C2=A0 =C2=A0v->visitor.start_alternate =3D qobject_input_start_a= lternate;
=C2=A0 =C2=A0 =C2=A0v->visitor.optional =3D qobject_input_optional;
-=C2=A0 =C2=A0 v->visitor.deprecated_accept =3D qobject_input_deprecated= _accept;
+=C2=A0 =C2=A0 v->visitor.policy_reject =3D qobject_input_policy_reject;=
=C2=A0 =C2=A0 =C2=A0v->visitor.free =3D qobject_input_free;

=C2=A0 =C2=A0 =C2=A0v->root =3D qobject_ref(obj);
diff --git a/qapi/qobject-output-visitor.c b/qapi/qobject-output-visitor.c<= br> index 9b7f510036..b5c6564cbb 100644
--- a/qapi/qobject-output-visitor.c
+++ b/qapi/qobject-output-visitor.c
@@ -13,6 +13,7 @@
=C2=A0 */

=C2=A0#include "qemu/osdep.h"
+#include "qapi/compat-policy.h"
=C2=A0#include "qapi/qobject-output-visitor.h"
=C2=A0#include "qapi/visitor-impl.h"
=C2=A0#include "qemu/queue.h"
@@ -208,9 +209,11 @@ static bool qobject_output_type_null(Visitor *v, const= char *name,
=C2=A0 =C2=A0 =C2=A0return true;
=C2=A0}

-static bool qobject_output_deprecated(Visitor *v, const char *name)
+static bool qobject_output_policy_skip(Visitor *v, const char *name,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0unsigned = special_features)
=C2=A0{
-=C2=A0 =C2=A0 return v->compat_policy.deprecated_output !=3D COMPAT_POL= ICY_OUTPUT_HIDE;
+=C2=A0 =C2=A0 return !(special_features && 1u << QAPI_DEPREC= ATED)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 || v->compat_policy.deprecated_output =3D= =3D COMPAT_POLICY_OUTPUT_HIDE;
=C2=A0}

=C2=A0/* Finish building, and return the root object.
@@ -262,7 +265,7 @@ Visitor *qobject_output_visitor_new(QObject **result) =C2=A0 =C2=A0 =C2=A0v->visitor.type_number =3D qobject_output_type_numbe= r;
=C2=A0 =C2=A0 =C2=A0v->visitor.type_any =3D qobject_output_type_any;
=C2=A0 =C2=A0 =C2=A0v->visitor.type_null =3D qobject_output_type_null; -=C2=A0 =C2=A0 v->visitor.deprecated =3D qobject_output_deprecated;
+=C2=A0 =C2=A0 v->visitor.policy_skip =3D qobject_output_policy_skip; =C2=A0 =C2=A0 =C2=A0v->visitor.complete =3D qobject_output_complete;
=C2=A0 =C2=A0 =C2=A0v->visitor.free =3D qobject_output_free;

diff --git a/qapi/trace-events b/qapi/trace-events
index cccafc07e5..ab108c4f0e 100644
--- a/qapi/trace-events
+++ b/qapi/trace-events
@@ -17,8 +17,8 @@ visit_start_alternate(void *v, const char *name, void *ob= j, size_t size) "v=3D%p n
=C2=A0visit_end_alternate(void *v, void *obj) "v=3D%p obj=3D%p"
=C2=A0visit_optional(void *v, const char *name, bool *present) "v=3D%p= name=3D%s present=3D%p"
-visit_deprecated_accept(void *v, const char *name) "v=3D%p name=3D%s&= quot;
-visit_deprecated(void *v, const char *name) "v=3D%p name=3D%s" +visit_policy_reject(void *v, const char *name) "v=3D%p name=3D%s"= ;
+visit_policy_skip(void *v, const char *name) "v=3D%p name=3D%s"<= br>
=C2=A0visit_type_enum(void *v, const char *name, int *obj) "v=3D%p nam= e=3D%s obj=3D%p"
=C2=A0visit_type_int(void *v, const char *name, int64_t *obj) "v=3D%p = name=3D%s obj=3D%p"
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index 9d9196a143..e13bbe4292 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -21,7 +21,7 @@
=C2=A0 =C2=A0 =C2=A0indent,
=C2=A0 =C2=A0 =C2=A0mcgen,
=C2=A0)
-from .gen import QAPISchemaModularCVisitor, ifcontext
+from .gen import QAPISchemaModularCVisitor, gen_special_features, ifcontex= t
=C2=A0from .schema import (
=C2=A0 =C2=A0 =C2=A0QAPISchema,
=C2=A0 =C2=A0 =C2=A0QAPISchemaEnumMember,
@@ -76,7 +76,6 @@ def gen_visit_object_members(name: str,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 c_type=3Dbase.c_name())

=C2=A0 =C2=A0 =C2=A0for memb in members:
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 deprecated =3D 'deprecated' in [f.name for f i= n memb.features]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ret +=3D memb.ifcond.gen_if()
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if memb.optional:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ret +=3D mcgen(''&#= 39;
@@ -84,14 +83,15 @@ def gen_visit_object_members(name: str,
=C2=A0''',
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 name=3Dmemb.name, c_name=3Dc_name(memb.name))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0indent.increase()
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 if deprecated:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 special_features =3D gen_special_features(memb= .features)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if special_features !=3D '0':

Would it be possible for gen_special_feat= ures to return something false-y instead of '0'? Do we actually *us= e* the '0' return anywhere other than to test it to see if we shoul= d include additional code?

If you actually use the= '0' anywhere: Go ahead and treat this as an ack. If you don't,= can we clean this up?
(Sorry, I find the mcgen stuff hard to rea= d in patch form and I am trying to give you a quick review instead of NO re= view.)

--js
=C2=A0
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ret +=3D mcgen(''&#= 39;
-=C2=A0 =C2=A0 if (!visit_deprecated_accept(v, "%(name)s", errp))= {
+=C2=A0 =C2=A0 if (visit_policy_reject(v, "%(name)s", %(special_f= eatures)s, errp)) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return false;
=C2=A0 =C2=A0 =C2=A0}
-=C2=A0 =C2=A0 if (visit_deprecated(v, "%(name)s")) {
+=C2=A0 =C2=A0 if (!visit_policy_skip(v, "%(name)s", %(special_fe= atures)s)) {
=C2=A0''',
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0name=3Dmemb.name)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0name=3Dmemb.name, special_features=3Dspecial_features)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0indent.increase()
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ret +=3D mcgen('''
=C2=A0 =C2=A0 =C2=A0if (!visit_type_%(c_type)s(v, "%(name)s", &am= p;obj->%(c_name)s, errp)) {
@@ -100,7 +100,7 @@ def gen_visit_object_members(name: str,
=C2=A0''',
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 c_type=3Dmemb.type.c_name(), name=3Dmemb.name,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 c_name=3Dc_name(memb.name))
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 if deprecated:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if special_features !=3D '0':
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0indent.decrease()
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ret +=3D mcgen(''&#= 39;
=C2=A0 =C2=A0 =C2=A0}
--
2.31.1



--0000000000006e1e2b05cf325dcc--