From: Peter Xu <peterx@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Markus Armbruster" <armbru@redhat.com>,
"Peter Maydell" <peter.maydell@linaro.org>,
"Eduardo Habkost" <eduardo@habkost.net>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Mark Cave-Ayland" <mark.cave-ayland@ilande.co.uk>,
"Igor Mammedov" <imammedo@redhat.com>,
"Michael S . Tsirkin" <mst@redhat.com>,
"Alex Williamson" <alex.williamson@redhat.com>,
"Dr . David Alan Gilbert" <dave@treblig.org>,
peterx@redhat.com, "Daniel P . Berrangé" <berrange@redhat.com>,
"Philippe Mathieu-Daudé" <philmd@linaro.org>,
"Cédric Le Goater" <clg@redhat.com>,
"Fabiano Rosas" <farosas@suse.de>,
"Juraj Marcin" <jmarcin@redhat.com>
Subject: [PATCH RFC v2 1/7] qom: Track dynamic initiations of random object class
Date: Tue, 29 Oct 2024 17:16:01 -0400 [thread overview]
Message-ID: <20241029211607.2114845-2-peterx@redhat.com> (raw)
In-Reply-To: <20241029211607.2114845-1-peterx@redhat.com>
Add a helper object_new_allowed(), use it to track all the places in QEMU
where a new (and especially, random) object can be created.
Currently, it is some form of a cleanup, just to put together all the
errors where QEMU wants to avoid instantiations of abstract classes. The
follow up patch will add more restriction on what object we can create.
A side effect of the cleanup: we could have reported the error message in
different ways even if the reason is always the same (attempts to create an
instance for an abstract class). Now we always report the same message,
could be different from before, but hopefully still worthwhile to change.
Signed-off-by: Peter Xu <peterx@redhat.com>
---
include/qom/object.h | 13 +++++++++++++
chardev/char.c | 4 +---
hw/core/cpu-common.c | 13 +++++++++----
qom/object.c | 17 +++++++++++++++--
qom/object_interfaces.c | 3 +--
system/qdev-monitor.c | 4 +---
6 files changed, 40 insertions(+), 14 deletions(-)
diff --git a/include/qom/object.h b/include/qom/object.h
index 2af9854675..32f1af2986 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -627,6 +627,19 @@ Object *object_new_with_class(ObjectClass *klass);
*/
Object *object_new(const char *typename);
+/**
+ * object_new_allowed:
+ * @klass: The class to instantiate, or fetch instance from.
+ * @errp: The pointer to an Error* that might be filled
+ *
+ * This function detects whether creating a new object of specificed class
+ * is allowed. For example, we do not allow initiations of abstract class.
+ *
+ * Returns: True if new objects allowed, false otherwise. When false is
+ * returned, errp will be set with a proper error message.
+ */
+bool object_new_allowed(ObjectClass *klass, Error **errp);
+
/**
* object_new_with_props:
* @typename: The name of the type of the object to instantiate.
diff --git a/chardev/char.c b/chardev/char.c
index a1722aa076..7fa5b82585 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -533,9 +533,7 @@ static const ChardevClass *char_get_class(const char *driver, Error **errp)
return NULL;
}
- if (object_class_is_abstract(oc)) {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
- "a non-abstract device type");
+ if (!object_new_allowed(oc, errp)) {
return NULL;
}
diff --git a/hw/core/cpu-common.c b/hw/core/cpu-common.c
index 09c7903594..1815b08ba0 100644
--- a/hw/core/cpu-common.c
+++ b/hw/core/cpu-common.c
@@ -154,12 +154,17 @@ ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model)
assert(cc->class_by_name);
assert(cpu_model);
oc = cc->class_by_name(cpu_model);
- if (object_class_dynamic_cast(oc, typename) &&
- !object_class_is_abstract(oc)) {
- return oc;
+
+ if (!object_class_dynamic_cast(oc, typename)) {
+ return NULL;
}
- return NULL;
+ /* TODO: allow error message to be passed to the callers */
+ if (!object_new_allowed(oc, NULL)) {
+ return NULL;
+ }
+
+ return oc;
}
static void cpu_common_parse_features(const char *typename, char *features,
diff --git a/qom/object.c b/qom/object.c
index 11424cf471..4f3739fd85 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -797,6 +797,19 @@ Object *object_new(const char *typename)
return object_new_with_type(ti);
}
+bool object_new_allowed(ObjectClass *klass, Error **errp)
+{
+ ERRP_GUARD();
+
+ /* Abstract classes are not instantiable */
+ if (object_class_is_abstract(klass)) {
+ error_setg(errp, "Object type '%s' is abstract",
+ klass->type->name);
+ return false;
+ }
+
+ return true;
+}
Object *object_new_with_props(const char *typename,
Object *parent,
@@ -831,10 +844,10 @@ Object *object_new_with_propv(const char *typename,
return NULL;
}
- if (object_class_is_abstract(klass)) {
- error_setg(errp, "object type '%s' is abstract", typename);
+ if (!object_new_allowed(klass, errp)) {
return NULL;
}
+
obj = object_new_with_type(klass->type);
if (!object_set_propv(obj, errp, vargs)) {
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
index e0833c8bfe..d68faf2234 100644
--- a/qom/object_interfaces.c
+++ b/qom/object_interfaces.c
@@ -102,8 +102,7 @@ Object *user_creatable_add_type(const char *type, const char *id,
return NULL;
}
- if (object_class_is_abstract(klass)) {
- error_setg(errp, "object type '%s' is abstract", type);
+ if (!object_new_allowed(klass, errp)) {
return NULL;
}
diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c
index 44994ea0e1..5609e73635 100644
--- a/system/qdev-monitor.c
+++ b/system/qdev-monitor.c
@@ -255,9 +255,7 @@ static DeviceClass *qdev_get_device_class(const char **driver, Error **errp)
return NULL;
}
- if (object_class_is_abstract(oc)) {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
- "a non-abstract device type");
+ if (!object_new_allowed(oc, errp)) {
return NULL;
}
--
2.45.0
next prev parent reply other threads:[~2024-10-29 21:17 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-29 21:16 [PATCH RFC v2 0/7] QOM: Singleton interface Peter Xu
2024-10-29 21:16 ` Peter Xu [this message]
2024-10-29 21:16 ` [PATCH RFC v2 2/7] qom: TYPE_SINGLETON interface Peter Xu
2024-10-29 21:16 ` [PATCH RFC v2 3/7] qdev: Make device_set_realized() be fully prepared with !machine Peter Xu
2024-10-29 21:16 ` [PATCH RFC v2 4/7] qdev: Make qdev_get_machine() safe before machine creates Peter Xu
2024-10-29 21:16 ` [PATCH RFC v2 5/7] x86/iommu: Make x86-iommu a singleton object Peter Xu
2024-10-30 10:33 ` Daniel P. Berrangé
2024-10-30 13:01 ` Peter Xu
2024-10-30 13:07 ` Daniel P. Berrangé
2024-10-30 14:33 ` Peter Xu
2024-10-29 21:16 ` [PATCH RFC v2 6/7] migration: Make migration object " Peter Xu
2024-10-29 21:16 ` [PATCH RFC v2 7/7] migration: Reset current_migration properly Peter Xu
2024-10-30 9:48 ` [PATCH RFC v2 0/7] QOM: Singleton interface Daniel P. Berrangé
2024-10-30 13:13 ` Peter Xu
2024-10-30 16:13 ` Daniel P. Berrangé
2024-10-30 17:51 ` Peter Xu
2024-10-30 17:58 ` Daniel P. Berrangé
2024-10-30 18:55 ` Peter Xu
2024-10-30 18:07 ` Daniel P. Berrangé
2024-10-30 19:08 ` Peter Xu
2024-10-31 15:57 ` Daniel P. Berrangé
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20241029211607.2114845-2-peterx@redhat.com \
--to=peterx@redhat.com \
--cc=alex.williamson@redhat.com \
--cc=armbru@redhat.com \
--cc=berrange@redhat.com \
--cc=clg@redhat.com \
--cc=dave@treblig.org \
--cc=eduardo@habkost.net \
--cc=farosas@suse.de \
--cc=imammedo@redhat.com \
--cc=jmarcin@redhat.com \
--cc=mark.cave-ayland@ilande.co.uk \
--cc=mst@redhat.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=philmd@linaro.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.