qom: centralize module-loading functionality

Put together the common code of object_initialize() and
module_object_class_by_name() into a function that supports
Error **.  Rename the existing function type_get_by_name() to
clarify that it will only look at defined types; this is often
okay within object.c to look at the parents, but not outside it.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2024-10-29 10:31:30 +01:00
parent b801e3cb2a
commit 144d80f69e

View File

@ -195,7 +195,7 @@ void type_register_static_array(const TypeInfo *infos, int nr_infos)
} }
} }
static TypeImpl *type_get_by_name(const char *name) static TypeImpl *type_get_by_name_noload(const char *name)
{ {
if (name == NULL) { if (name == NULL) {
return NULL; return NULL;
@ -204,10 +204,32 @@ static TypeImpl *type_get_by_name(const char *name)
return type_table_lookup(name); return type_table_lookup(name);
} }
static TypeImpl *type_get_or_load_by_name(const char *name, Error **errp)
{
TypeImpl *type = type_get_by_name_noload(name);
#ifdef CONFIG_MODULES
if (!type) {
int rv = module_load_qom(name, errp);
if (rv > 0) {
type = type_get_by_name_noload(name);
} else {
error_prepend(errp, "could not load a module for type '%s'", name);
return NULL;
}
}
#endif
if (!type) {
error_setg(errp, "unknown type '%s'", name);
}
return type;
}
static TypeImpl *type_get_parent(TypeImpl *type) static TypeImpl *type_get_parent(TypeImpl *type)
{ {
if (!type->parent_type && type->parent) { if (!type->parent_type && type->parent) {
type->parent_type = type_get_by_name(type->parent); type->parent_type = type_get_by_name_noload(type->parent);
if (!type->parent_type) { if (!type->parent_type) {
fprintf(stderr, "Type '%s' is missing its parent '%s'\n", fprintf(stderr, "Type '%s' is missing its parent '%s'\n",
type->name, type->parent); type->name, type->parent);
@ -363,7 +385,7 @@ static void type_initialize(TypeImpl *ti)
} }
for (i = 0; i < ti->num_interfaces; i++) { for (i = 0; i < ti->num_interfaces; i++) {
TypeImpl *t = type_get_by_name(ti->interfaces[i].typename); TypeImpl *t = type_get_by_name_noload(ti->interfaces[i].typename);
if (!t) { if (!t) {
error_report("missing interface '%s' for object '%s'", error_report("missing interface '%s' for object '%s'",
ti->interfaces[i].typename, parent->name); ti->interfaces[i].typename, parent->name);
@ -557,23 +579,7 @@ static void object_initialize_with_type(Object *obj, size_t size, TypeImpl *type
void object_initialize(void *data, size_t size, const char *typename) void object_initialize(void *data, size_t size, const char *typename)
{ {
TypeImpl *type = type_get_by_name(typename); TypeImpl *type = type_get_or_load_by_name(typename, &error_fatal);
#ifdef CONFIG_MODULES
if (!type) {
int rv = module_load_qom(typename, &error_fatal);
if (rv > 0) {
type = type_get_by_name(typename);
} else {
error_report("missing object type '%s'", typename);
exit(1);
}
}
#endif
if (!type) {
error_report("missing object type '%s'", typename);
abort();
}
object_initialize_with_type(data, size, type); object_initialize_with_type(data, size, type);
} }
@ -784,7 +790,7 @@ Object *object_new_with_class(ObjectClass *klass)
Object *object_new(const char *typename) Object *object_new(const char *typename)
{ {
TypeImpl *ti = type_get_by_name(typename); TypeImpl *ti = type_get_by_name_noload(typename);
return object_new_with_type(ti); return object_new_with_type(ti);
} }
@ -957,7 +963,7 @@ ObjectClass *object_class_dynamic_cast(ObjectClass *class,
return class; return class;
} }
target_type = type_get_by_name(typename); target_type = type_get_by_name_noload(typename);
if (!target_type) { if (!target_type) {
/* target class type unknown, so fail the cast */ /* target class type unknown, so fail the cast */
return NULL; return NULL;
@ -1055,7 +1061,7 @@ const char *object_class_get_name(ObjectClass *klass)
ObjectClass *object_class_by_name(const char *typename) ObjectClass *object_class_by_name(const char *typename)
{ {
TypeImpl *type = type_get_by_name(typename); TypeImpl *type = type_get_by_name_noload(typename);
if (!type) { if (!type) {
return NULL; return NULL;
@ -1068,21 +1074,15 @@ ObjectClass *object_class_by_name(const char *typename)
ObjectClass *module_object_class_by_name(const char *typename) ObjectClass *module_object_class_by_name(const char *typename)
{ {
ObjectClass *oc; TypeImpl *type = type_get_or_load_by_name(typename, NULL);
oc = object_class_by_name(typename); if (!type) {
#ifdef CONFIG_MODULES return NULL;
if (!oc) {
Error *local_err = NULL;
int rv = module_load_qom(typename, &local_err);
if (rv > 0) {
oc = object_class_by_name(typename);
} else if (rv < 0) {
error_report_err(local_err);
}
} }
#endif
return oc; type_initialize(type);
return type->class;
} }
ObjectClass *object_class_get_parent(ObjectClass *class) ObjectClass *object_class_get_parent(ObjectClass *class)