[PATCH 3/4] crypto: use QOM macros for declaration/definition of secret types

Daniel P. Berrangé posted 4 patches 5 years, 6 months ago
[PATCH 3/4] crypto: use QOM macros for declaration/definition of secret types
Posted by Daniel P. Berrangé 5 years, 6 months ago
This introduces the use of the OBJECT_DEFINE and OBJECT_DECLARE macro
families in the secret types, in order to eliminate boilerplate code.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 crypto/secret.c                 | 24 ++++--------------------
 crypto/secret_common.c          | 32 +++++++++-----------------------
 crypto/secret_keyring.c         | 28 +++++++++-------------------
 include/crypto/secret.h         | 11 ++---------
 include/crypto/secret_common.h  | 13 ++-----------
 include/crypto/secret_keyring.h | 18 ++----------------
 6 files changed, 28 insertions(+), 98 deletions(-)

diff --git a/crypto/secret.c b/crypto/secret.c
index 281cb81f0f..55b406f79e 100644
--- a/crypto/secret.c
+++ b/crypto/secret.c
@@ -25,6 +25,9 @@
 #include "qemu/module.h"
 #include "trace.h"
 
+OBJECT_DEFINE_TYPE_WITH_INTERFACES(QCryptoSecret, qcrypto_secret,
+                                   QCRYPTO_SECRET, QCRYPTO_SECRET_COMMON,
+                                   { TYPE_USER_CREATABLE }, { NULL })
 
 static void
 qcrypto_secret_load_data(QCryptoSecretCommon *sec_common,
@@ -140,26 +143,7 @@ qcrypto_secret_class_init(ObjectClass *oc, void *data)
                                   qcrypto_secret_prop_set_file);
 }
 
-
-static const TypeInfo qcrypto_secret_info = {
-    .parent = TYPE_QCRYPTO_SECRET_COMMON,
-    .name = TYPE_QCRYPTO_SECRET,
-    .instance_size = sizeof(QCryptoSecret),
-    .instance_finalize = qcrypto_secret_finalize,
-    .class_size = sizeof(QCryptoSecretClass),
-    .class_init = qcrypto_secret_class_init,
-    .interfaces = (InterfaceInfo[]) {
-        { TYPE_USER_CREATABLE },
-        { }
-    }
-};
-
-
 static void
-qcrypto_secret_register_types(void)
+qcrypto_secret_init(Object *obj)
 {
-    type_register_static(&qcrypto_secret_info);
 }
-
-
-type_init(qcrypto_secret_register_types);
diff --git a/crypto/secret_common.c b/crypto/secret_common.c
index b03d530867..9a054b90b5 100644
--- a/crypto/secret_common.c
+++ b/crypto/secret_common.c
@@ -28,6 +28,9 @@
 #include "trace.h"
 
 
+OBJECT_DEFINE_ABSTRACT_TYPE(QCryptoSecretCommon, qcrypto_secret_common,
+                            QCRYPTO_SECRET_COMMON, OBJECT)
+
 static void qcrypto_secret_decrypt(QCryptoSecretCommon *secret,
                                    const uint8_t *input,
                                    size_t inputlen,
@@ -269,7 +272,7 @@ qcrypto_secret_prop_get_keyid(Object *obj,
 
 
 static void
-qcrypto_secret_finalize(Object *obj)
+qcrypto_secret_common_finalize(Object *obj)
 {
     QCryptoSecretCommon *secret = QCRYPTO_SECRET_COMMON(obj);
 
@@ -279,7 +282,7 @@ qcrypto_secret_finalize(Object *obj)
 }
 
 static void
-qcrypto_secret_class_init(ObjectClass *oc, void *data)
+qcrypto_secret_common_class_init(ObjectClass *oc, void *data)
 {
     object_class_property_add_bool(oc, "loaded",
                                    qcrypto_secret_prop_get_loaded,
@@ -297,6 +300,10 @@ qcrypto_secret_class_init(ObjectClass *oc, void *data)
                                   qcrypto_secret_prop_set_iv);
 }
 
+static void
+qcrypto_secret_common_init(Object *obj)
+{
+}
 
 int qcrypto_secret_lookup(const char *secretid,
                           uint8_t **data,
@@ -380,24 +387,3 @@ char *qcrypto_secret_lookup_as_base64(const char *secretid,
     g_free(data);
     return ret;
 }
-
-
-static const TypeInfo qcrypto_secret_info = {
-    .parent = TYPE_OBJECT,
-    .name = TYPE_QCRYPTO_SECRET_COMMON,
-    .instance_size = sizeof(QCryptoSecretCommon),
-    .instance_finalize = qcrypto_secret_finalize,
-    .class_size = sizeof(QCryptoSecretCommonClass),
-    .class_init = qcrypto_secret_class_init,
-    .abstract = true,
-};
-
-
-static void
-qcrypto_secret_register_types(void)
-{
-    type_register_static(&qcrypto_secret_info);
-}
-
-
-type_init(qcrypto_secret_register_types);
diff --git a/crypto/secret_keyring.c b/crypto/secret_keyring.c
index 8bfc58ebf4..463aefe5dc 100644
--- a/crypto/secret_keyring.c
+++ b/crypto/secret_keyring.c
@@ -26,6 +26,9 @@
 #include "trace.h"
 #include "crypto/secret_keyring.h"
 
+OBJECT_DEFINE_TYPE_WITH_INTERFACES(QCryptoSecretKeyring, qcrypto_secret_keyring,
+                                   QCRYPTO_SECRET_KEYRING, QCRYPTO_SECRET_COMMON,
+                                   { TYPE_USER_CREATABLE }, { NULL })
 
 static inline
 long keyctl_read(int32_t key, uint8_t *buffer, size_t buflen)
@@ -109,6 +112,11 @@ qcrypto_secret_keyring_complete(UserCreatable *uc, Error **errp)
 }
 
 
+static void
+qcrypto_secret_keyring_finalize(Object *obj)
+{
+}
+
 static void
 qcrypto_secret_keyring_class_init(ObjectClass *oc, void *data)
 {
@@ -124,25 +132,7 @@ qcrypto_secret_keyring_class_init(ObjectClass *oc, void *data)
                                   NULL, NULL);
 }
 
-
-static const TypeInfo qcrypto_secret_info = {
-    .parent = TYPE_QCRYPTO_SECRET_COMMON,
-    .name = TYPE_QCRYPTO_SECRET_KEYRING,
-    .instance_size = sizeof(QCryptoSecretKeyring),
-    .class_size = sizeof(QCryptoSecretKeyringClass),
-    .class_init = qcrypto_secret_keyring_class_init,
-    .interfaces = (InterfaceInfo[]) {
-        { TYPE_USER_CREATABLE },
-        { }
-    }
-};
-
-
 static void
-qcrypto_secret_register_types(void)
+qcrypto_secret_keyring_init(Object *obj)
 {
-    type_register_static(&qcrypto_secret_info);
 }
-
-
-type_init(qcrypto_secret_register_types);
diff --git a/include/crypto/secret.h b/include/crypto/secret.h
index 2deb461d2f..4eb4e5ffef 100644
--- a/include/crypto/secret.h
+++ b/include/crypto/secret.h
@@ -26,11 +26,9 @@
 #include "crypto/secret_common.h"
 
 #define TYPE_QCRYPTO_SECRET "secret"
-#define QCRYPTO_SECRET(obj)                  \
-    OBJECT_CHECK(QCryptoSecret, (obj), TYPE_QCRYPTO_SECRET)
 
-typedef struct QCryptoSecret QCryptoSecret;
-typedef struct QCryptoSecretClass QCryptoSecretClass;
+OBJECT_DECLARE_SIMPLE_TYPE(QCryptoSecret, qcrypto_secret,
+                           QCRYPTO_SECRET, QCryptoSecretCommon)
 
 /**
  * QCryptoSecret:
@@ -125,9 +123,4 @@ struct QCryptoSecret {
     char *file;
 };
 
-
-struct QCryptoSecretClass {
-    QCryptoSecretCommonClass parent_class;
-};
-
 #endif /* QCRYPTO_SECRET_H */
diff --git a/include/crypto/secret_common.h b/include/crypto/secret_common.h
index 980c02ab71..999a6b4651 100644
--- a/include/crypto/secret_common.h
+++ b/include/crypto/secret_common.h
@@ -25,17 +25,8 @@
 #include "qom/object.h"
 
 #define TYPE_QCRYPTO_SECRET_COMMON "secret_common"
-#define QCRYPTO_SECRET_COMMON(obj) \
-    OBJECT_CHECK(QCryptoSecretCommon, (obj), TYPE_QCRYPTO_SECRET_COMMON)
-#define QCRYPTO_SECRET_COMMON_CLASS(class) \
-    OBJECT_CLASS_CHECK(QCryptoSecretCommonClass, \
-                       (class), TYPE_QCRYPTO_SECRET_COMMON)
-#define QCRYPTO_SECRET_COMMON_GET_CLASS(obj) \
-    OBJECT_GET_CLASS(QCryptoSecretCommonClass, \
-                     (obj), TYPE_QCRYPTO_SECRET_COMMON)
-
-typedef struct QCryptoSecretCommon QCryptoSecretCommon;
-typedef struct QCryptoSecretCommonClass QCryptoSecretCommonClass;
+OBJECT_DECLARE_TYPE(QCryptoSecretCommon, qcrypto_secret_common,
+                    QCRYPTO_SECRET_COMMON)
 
 struct QCryptoSecretCommon {
     Object parent_obj;
diff --git a/include/crypto/secret_keyring.h b/include/crypto/secret_keyring.h
index 9f371ad251..4470306853 100644
--- a/include/crypto/secret_keyring.h
+++ b/include/crypto/secret_keyring.h
@@ -26,18 +26,8 @@
 #include "crypto/secret_common.h"
 
 #define TYPE_QCRYPTO_SECRET_KEYRING "secret_keyring"
-#define QCRYPTO_SECRET_KEYRING(obj) \
-    OBJECT_CHECK(QCryptoSecretKeyring, (obj), \
-                 TYPE_QCRYPTO_SECRET_KEYRING)
-#define QCRYPTO_SECRET_KEYRING_CLASS(class) \
-    OBJECT_CLASS_CHECK(QCryptoSecretKeyringClass, \
-                       (class), TYPE_QCRYPTO_SECRET_KEYRING)
-#define QCRYPTO_SECRET_KEYRING_GET_CLASS(class) \
-    OBJECT_GET_CLASS(QCryptoSecretKeyringClass, \
-                     (class), TYPE_QCRYPTO_SECRET_KEYRING)
-
-typedef struct QCryptoSecretKeyring QCryptoSecretKeyring;
-typedef struct QCryptoSecretKeyringClass QCryptoSecretKeyringClass;
+OBJECT_DECLARE_SIMPLE_TYPE(QCryptoSecretKeyring, qcrypto_secret_keyring,
+                           QCRYPTO_SECRET_KEYRING, QCryptoSecretCommon)
 
 typedef struct QCryptoSecretKeyring {
     QCryptoSecretCommon parent;
@@ -45,8 +35,4 @@ typedef struct QCryptoSecretKeyring {
 } QCryptoSecretKeyring;
 
 
-typedef struct QCryptoSecretKeyringClass {
-    QCryptoSecretCommonClass parent;
-} QCryptoSecretKeyringClass;
-
 #endif /* QCRYPTO_SECRET_KEYRING_H */
-- 
2.26.2


Re: [PATCH 3/4] crypto: use QOM macros for declaration/definition of secret types
Posted by Eduardo Habkost 5 years, 6 months ago
On Thu, Jul 23, 2020 at 07:14:09PM +0100, Daniel P. Berrangé wrote:
> This introduces the use of the OBJECT_DEFINE and OBJECT_DECLARE macro
> families in the secret types, in order to eliminate boilerplate code.
> 
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>  crypto/secret.c                 | 24 ++++--------------------
>  crypto/secret_common.c          | 32 +++++++++-----------------------
>  crypto/secret_keyring.c         | 28 +++++++++-------------------
>  include/crypto/secret.h         | 11 ++---------
>  include/crypto/secret_common.h  | 13 ++-----------
>  include/crypto/secret_keyring.h | 18 ++----------------
>  6 files changed, 28 insertions(+), 98 deletions(-)
> 

Beautiful.

I wonder how hard it would be to automate this.  I'm assuming
Coccinelle won't be able to deal with the macro definitions, but
a handwritten conversion script would be really useful for
dealing with our 1226 static TypeInfo structs.

-- 
Eduardo


Re: [PATCH 3/4] crypto: use QOM macros for declaration/definition of secret types
Posted by Daniel P. Berrangé 5 years, 6 months ago
On Thu, Jul 23, 2020 at 02:50:06PM -0400, Eduardo Habkost wrote:
> On Thu, Jul 23, 2020 at 07:14:09PM +0100, Daniel P. Berrangé wrote:
> > This introduces the use of the OBJECT_DEFINE and OBJECT_DECLARE macro
> > families in the secret types, in order to eliminate boilerplate code.
> > 
> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> > ---
> >  crypto/secret.c                 | 24 ++++--------------------
> >  crypto/secret_common.c          | 32 +++++++++-----------------------
> >  crypto/secret_keyring.c         | 28 +++++++++-------------------
> >  include/crypto/secret.h         | 11 ++---------
> >  include/crypto/secret_common.h  | 13 ++-----------
> >  include/crypto/secret_keyring.h | 18 ++----------------
> >  6 files changed, 28 insertions(+), 98 deletions(-)
> > 
> 
> Beautiful.
> 
> I wonder how hard it would be to automate this.  I'm assuming
> Coccinelle won't be able to deal with the macro definitions, but
> a handwritten conversion script would be really useful for
> dealing with our 1226 static TypeInfo structs.

Probably possible to do a reasonably good job with a perl script or
similar. The code patterns to be replaced are reasonably easy to
identify with a few regexes.

Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|


Re: [PATCH 3/4] crypto: use QOM macros for declaration/definition of secret types
Posted by Eduardo Habkost 5 years, 6 months ago
On Fri, Jul 24, 2020 at 10:12:45AM +0100, Daniel P. Berrangé wrote:
> On Thu, Jul 23, 2020 at 02:50:06PM -0400, Eduardo Habkost wrote:
> > On Thu, Jul 23, 2020 at 07:14:09PM +0100, Daniel P. Berrangé wrote:
> > > This introduces the use of the OBJECT_DEFINE and OBJECT_DECLARE macro
> > > families in the secret types, in order to eliminate boilerplate code.
> > > 
> > > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> > > ---
> > >  crypto/secret.c                 | 24 ++++--------------------
> > >  crypto/secret_common.c          | 32 +++++++++-----------------------
> > >  crypto/secret_keyring.c         | 28 +++++++++-------------------
> > >  include/crypto/secret.h         | 11 ++---------
> > >  include/crypto/secret_common.h  | 13 ++-----------
> > >  include/crypto/secret_keyring.h | 18 ++----------------
> > >  6 files changed, 28 insertions(+), 98 deletions(-)
> > > 
> > 
> > Beautiful.
> > 
> > I wonder how hard it would be to automate this.  I'm assuming
> > Coccinelle won't be able to deal with the macro definitions, but
> > a handwritten conversion script would be really useful for
> > dealing with our 1226 static TypeInfo structs.
> 
> Probably possible to do a reasonably good job with a perl script or
> similar. The code patterns to be replaced are reasonably easy to
> identify with a few regexes.

I've attempted to parse all the TypeInfo structs in the tree.
The data I've extracted is available at:
https://gist.github.com/ehabkost/7a398640492f369685c789ffed0f67aa

It turns out 230 of our 1259 TypeInfo variables don't have
instance_size set and don't have their own struct type defined.

We could:
* Make that a supported use case, and add helper macros that don't
  require MyDevice to be defined;
* Make that not supported, and convert those 230 types automatically; or
* Make that not supported, and convert those 230 types manually.

-- 
Eduardo


Re: [PATCH 3/4] crypto: use QOM macros for declaration/definition of secret types
Posted by Daniel P. Berrangé 5 years, 6 months ago
On Thu, Aug 06, 2020 at 02:01:54PM -0400, Eduardo Habkost wrote:
> On Fri, Jul 24, 2020 at 10:12:45AM +0100, Daniel P. Berrangé wrote:
> > On Thu, Jul 23, 2020 at 02:50:06PM -0400, Eduardo Habkost wrote:
> > > On Thu, Jul 23, 2020 at 07:14:09PM +0100, Daniel P. Berrangé wrote:
> > > > This introduces the use of the OBJECT_DEFINE and OBJECT_DECLARE macro
> > > > families in the secret types, in order to eliminate boilerplate code.
> > > > 
> > > > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> > > > ---
> > > >  crypto/secret.c                 | 24 ++++--------------------
> > > >  crypto/secret_common.c          | 32 +++++++++-----------------------
> > > >  crypto/secret_keyring.c         | 28 +++++++++-------------------
> > > >  include/crypto/secret.h         | 11 ++---------
> > > >  include/crypto/secret_common.h  | 13 ++-----------
> > > >  include/crypto/secret_keyring.h | 18 ++----------------
> > > >  6 files changed, 28 insertions(+), 98 deletions(-)
> > > > 
> > > 
> > > Beautiful.
> > > 
> > > I wonder how hard it would be to automate this.  I'm assuming
> > > Coccinelle won't be able to deal with the macro definitions, but
> > > a handwritten conversion script would be really useful for
> > > dealing with our 1226 static TypeInfo structs.
> > 
> > Probably possible to do a reasonably good job with a perl script or
> > similar. The code patterns to be replaced are reasonably easy to
> > identify with a few regexes.
> 
> I've attempted to parse all the TypeInfo structs in the tree.
> The data I've extracted is available at:
> https://gist.github.com/ehabkost/7a398640492f369685c789ffed0f67aa
> 
> It turns out 230 of our 1259 TypeInfo variables don't have
> instance_size set and don't have their own struct type defined.
> 
> We could:
> * Make that a supported use case, and add helper macros that don't
>   require MyDevice to be defined;
> * Make that not supported, and convert those 230 types automatically; or
> * Make that not supported, and convert those 230 types manually.

When we force an instance struct, we also force definition of an
instance init and finalize function.

230 types is probably enough to justify a further macro that allows
the instance struct, init & finalize funtions to be omitted.

Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|


Re: [PATCH 3/4] crypto: use QOM macros for declaration/definition of secret types
Posted by Eduardo Habkost 5 years, 6 months ago
On Fri, Aug 07, 2020 at 12:11:48PM +0100, Daniel P. Berrangé wrote:
> On Thu, Aug 06, 2020 at 02:01:54PM -0400, Eduardo Habkost wrote:
> > On Fri, Jul 24, 2020 at 10:12:45AM +0100, Daniel P. Berrangé wrote:
> > > On Thu, Jul 23, 2020 at 02:50:06PM -0400, Eduardo Habkost wrote:
> > > > On Thu, Jul 23, 2020 at 07:14:09PM +0100, Daniel P. Berrangé wrote:
> > > > > This introduces the use of the OBJECT_DEFINE and OBJECT_DECLARE macro
> > > > > families in the secret types, in order to eliminate boilerplate code.
> > > > > 
> > > > > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> > > > > ---
> > > > >  crypto/secret.c                 | 24 ++++--------------------
> > > > >  crypto/secret_common.c          | 32 +++++++++-----------------------
> > > > >  crypto/secret_keyring.c         | 28 +++++++++-------------------
> > > > >  include/crypto/secret.h         | 11 ++---------
> > > > >  include/crypto/secret_common.h  | 13 ++-----------
> > > > >  include/crypto/secret_keyring.h | 18 ++----------------
> > > > >  6 files changed, 28 insertions(+), 98 deletions(-)
> > > > > 
> > > > 
> > > > Beautiful.
> > > > 
> > > > I wonder how hard it would be to automate this.  I'm assuming
> > > > Coccinelle won't be able to deal with the macro definitions, but
> > > > a handwritten conversion script would be really useful for
> > > > dealing with our 1226 static TypeInfo structs.
> > > 
> > > Probably possible to do a reasonably good job with a perl script or
> > > similar. The code patterns to be replaced are reasonably easy to
> > > identify with a few regexes.
> > 
> > I've attempted to parse all the TypeInfo structs in the tree.
> > The data I've extracted is available at:
> > https://gist.github.com/ehabkost/7a398640492f369685c789ffed0f67aa
> > 
> > It turns out 230 of our 1259 TypeInfo variables don't have
> > instance_size set and don't have their own struct type defined.
> > 
> > We could:
> > * Make that a supported use case, and add helper macros that don't
> >   require MyDevice to be defined;
> > * Make that not supported, and convert those 230 types automatically; or
> > * Make that not supported, and convert those 230 types manually.
> 
> When we force an instance struct, we also force definition of an
> instance init and finalize function.
> 
> 230 types is probably enough to justify a further macro that allows
> the instance struct, init & finalize funtions to be omitted.

Status update: the TypeInfo parser evolved to become a converter
able to replace the type checking macros (automatic conversion of
TypeInfo declarations will be done soon).

https://github.com/ehabkost/qemu-hacks/commits/work/qom-macros-autoconvert

Additional obstacles we'll need to address:

- Sometimes the struct typedefs are in a completely different
  file from the type checking macros.  I've worked around this
  problem by introducing macros that will only add the type
  casting functions, but no typedefs.
- There's some usage of const object pointers in the code,
  which breaks the new type cast functions:
  https://travis-ci.org/github/ehabkost/qemu-hacks/jobs/716033062#L1417

We can probably use _Generic to make the type cast functions
const-safe, but I'm sure this will break existing code that
expects the type casts to always return non-const pointers.

-- 
Eduardo


Re: [PATCH 3/4] crypto: use QOM macros for declaration/definition of secret types
Posted by Eric Blake 5 years, 6 months ago
On 7/23/20 1:14 PM, Daniel P. Berrangé wrote:
> This introduces the use of the OBJECT_DEFINE and OBJECT_DECLARE macro
> families in the secret types, in order to eliminate boilerplate code.
> 
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
Reviewed-by: Eric Blake <eblake@redhat.com>

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