2016-01-29 20:50:02 +03:00
|
|
|
#include "qemu/osdep.h"
|
include/qemu/osdep.h: Don't include qapi/error.h
Commit 57cb38b included qapi/error.h into qemu/osdep.h to get the
Error typedef. Since then, we've moved to include qemu/osdep.h
everywhere. Its file comment explains: "To avoid getting into
possible circular include dependencies, this file should not include
any other QEMU headers, with the exceptions of config-host.h,
compiler.h, os-posix.h and os-win32.h, all of which are doing a
similar job to this file and are under similar constraints."
qapi/error.h doesn't do a similar job, and it doesn't adhere to
similar constraints: it includes qapi-types.h. That's in excess of
100KiB of crap most .c files don't actually need.
Add the typedef to qemu/typedefs.h, and include that instead of
qapi/error.h. Include qapi/error.h in .c files that need it and don't
get it now. Include qapi-types.h in qom/object.h for uint16List.
Update scripts/clean-includes accordingly. Update it further to match
reality: replace config.h by config-target.h, add sysemu/os-posix.h,
sysemu/os-win32.h. Update the list of includes in the qemu/osdep.h
comment quoted above similarly.
This reduces the number of objects depending on qapi/error.h from "all
of them" to less than a third. Unfortunately, the number depending on
qapi-types.h shrinks only a little. More work is needed for that one.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
[Fix compilation without the spice devel packages. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2016-03-14 11:01:28 +03:00
|
|
|
#include "qapi/error.h"
|
2014-01-16 20:34:38 +04:00
|
|
|
#include "qom/object_interfaces.h"
|
|
|
|
#include "qemu/module.h"
|
2016-02-10 21:40:59 +03:00
|
|
|
#include "qapi-visit.h"
|
|
|
|
#include "qapi/qmp-output-visitor.h"
|
|
|
|
#include "qapi/opts-visitor.h"
|
2014-01-16 20:34:38 +04:00
|
|
|
|
|
|
|
void user_creatable_complete(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
|
|
|
|
UserCreatableClass *ucc;
|
|
|
|
UserCreatable *uc =
|
|
|
|
(UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
|
|
|
|
|
|
|
|
if (!uc) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ucc = USER_CREATABLE_GET_CLASS(uc);
|
|
|
|
if (ucc->complete) {
|
|
|
|
ucc->complete(uc, errp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-30 11:36:28 +03:00
|
|
|
bool user_creatable_can_be_deleted(UserCreatable *uc, Error **errp)
|
|
|
|
{
|
|
|
|
|
|
|
|
UserCreatableClass *ucc = USER_CREATABLE_GET_CLASS(uc);
|
|
|
|
|
|
|
|
if (ucc->can_be_deleted) {
|
|
|
|
return ucc->can_be_deleted(uc, errp);
|
|
|
|
} else {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-10 21:40:59 +03:00
|
|
|
|
|
|
|
Object *user_creatable_add(const QDict *qdict,
|
|
|
|
Visitor *v, Error **errp)
|
|
|
|
{
|
|
|
|
char *type = NULL;
|
|
|
|
char *id = NULL;
|
|
|
|
Object *obj = NULL;
|
|
|
|
Error *local_err = NULL, *end_err = NULL;
|
|
|
|
QDict *pdict;
|
|
|
|
|
|
|
|
pdict = qdict_clone_shallow(qdict);
|
|
|
|
|
|
|
|
visit_start_struct(v, NULL, NULL, 0, &local_err);
|
|
|
|
if (local_err) {
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
qdict_del(pdict, "qom-type");
|
|
|
|
visit_type_str(v, "qom-type", &type, &local_err);
|
|
|
|
if (local_err) {
|
|
|
|
goto out_visit;
|
|
|
|
}
|
|
|
|
|
|
|
|
qdict_del(pdict, "id");
|
|
|
|
visit_type_str(v, "id", &id, &local_err);
|
|
|
|
if (local_err) {
|
|
|
|
goto out_visit;
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = user_creatable_add_type(type, id, pdict, v, &local_err);
|
|
|
|
if (local_err) {
|
|
|
|
goto out_visit;
|
|
|
|
}
|
|
|
|
|
|
|
|
out_visit:
|
|
|
|
visit_end_struct(v, &end_err);
|
|
|
|
if (end_err) {
|
|
|
|
error_propagate(&local_err, end_err);
|
|
|
|
if (obj) {
|
|
|
|
user_creatable_del(id, NULL);
|
|
|
|
}
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
QDECREF(pdict);
|
|
|
|
g_free(id);
|
|
|
|
g_free(type);
|
|
|
|
if (local_err) {
|
|
|
|
error_propagate(errp, local_err);
|
|
|
|
object_unref(obj);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Object *user_creatable_add_type(const char *type, const char *id,
|
|
|
|
const QDict *qdict,
|
|
|
|
Visitor *v, Error **errp)
|
|
|
|
{
|
|
|
|
Object *obj;
|
|
|
|
ObjectClass *klass;
|
|
|
|
const QDictEntry *e;
|
|
|
|
Error *local_err = NULL;
|
|
|
|
|
|
|
|
klass = object_class_by_name(type);
|
|
|
|
if (!klass) {
|
|
|
|
error_setg(errp, "invalid object type: %s", type);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) {
|
|
|
|
error_setg(errp, "object type '%s' isn't supported by object-add",
|
|
|
|
type);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (object_class_is_abstract(klass)) {
|
|
|
|
error_setg(errp, "object type '%s' is abstract", type);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = object_new(type);
|
|
|
|
if (qdict) {
|
|
|
|
for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
|
|
|
|
object_property_set(obj, v, e->key, &local_err);
|
|
|
|
if (local_err) {
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
object_property_add_child(object_get_objects_root(),
|
|
|
|
id, obj, &local_err);
|
|
|
|
if (local_err) {
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
user_creatable_complete(obj, &local_err);
|
|
|
|
if (local_err) {
|
|
|
|
object_property_del(object_get_objects_root(),
|
|
|
|
id, &error_abort);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
out:
|
|
|
|
if (local_err) {
|
|
|
|
error_propagate(errp, local_err);
|
|
|
|
object_unref(obj);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Object *user_creatable_add_opts(QemuOpts *opts, Error **errp)
|
|
|
|
{
|
|
|
|
OptsVisitor *ov;
|
|
|
|
QDict *pdict;
|
|
|
|
Object *obj = NULL;
|
|
|
|
|
|
|
|
ov = opts_visitor_new(opts);
|
|
|
|
pdict = qemu_opts_to_qdict(opts, NULL);
|
|
|
|
|
|
|
|
obj = user_creatable_add(pdict, opts_get_visitor(ov), errp);
|
|
|
|
opts_visitor_cleanup(ov);
|
|
|
|
QDECREF(pdict);
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int user_creatable_add_opts_foreach(void *opaque, QemuOpts *opts, Error **errp)
|
|
|
|
{
|
|
|
|
bool (*type_predicate)(const char *) = opaque;
|
|
|
|
Object *obj = NULL;
|
qom: -object error messages lost location, restore it
qemu_opts_foreach() runs its callback with the error location set to
the option's location. Any errors the callback reports use the
option's location automatically.
Commit 90998d5 moved the actual error reporting from "inside"
qemu_opts_foreach() to after it. Here's a typical hunk:
if (qemu_opts_foreach(qemu_find_opts("object"),
- object_create,
- object_create_initial, NULL)) {
+ user_creatable_add_opts_foreach,
+ object_create_initial, &err)) {
+ error_report_err(err);
exit(1);
}
Before, object_create() reports from within qemu_opts_foreach(), using
the option's location. Afterwards, we do it after
qemu_opts_foreach(), using whatever location happens to be current
there. Commonly a "none" location.
This is because Error objects don't have location information.
Problematic.
Reproducer:
$ qemu-system-x86_64 -nodefaults -display none -object secret,id=foo,foo=bar
qemu-system-x86_64: Property '.foo' not found
Note no location. This commit restores it:
qemu-system-x86_64: -object secret,id=foo,foo=bar: Property '.foo' not found
Note that the qemu_opts_foreach() bug just fixed could mask the bug
here: if the location it leaves dangling hasn't been clobbered, yet,
it's the correct one.
Reported-by: Eric Blake <eblake@redhat.com>
Cc: Daniel P. Berrange <berrange@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <1461767349-15329-4-git-send-email-armbru@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
[Paragraph on Error added to commit message]
2016-04-27 17:29:09 +03:00
|
|
|
Error *err = NULL;
|
2016-02-10 21:40:59 +03:00
|
|
|
const char *type;
|
|
|
|
|
|
|
|
type = qemu_opt_get(opts, "qom-type");
|
|
|
|
if (type && type_predicate &&
|
|
|
|
!type_predicate(type)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
qom: -object error messages lost location, restore it
qemu_opts_foreach() runs its callback with the error location set to
the option's location. Any errors the callback reports use the
option's location automatically.
Commit 90998d5 moved the actual error reporting from "inside"
qemu_opts_foreach() to after it. Here's a typical hunk:
if (qemu_opts_foreach(qemu_find_opts("object"),
- object_create,
- object_create_initial, NULL)) {
+ user_creatable_add_opts_foreach,
+ object_create_initial, &err)) {
+ error_report_err(err);
exit(1);
}
Before, object_create() reports from within qemu_opts_foreach(), using
the option's location. Afterwards, we do it after
qemu_opts_foreach(), using whatever location happens to be current
there. Commonly a "none" location.
This is because Error objects don't have location information.
Problematic.
Reproducer:
$ qemu-system-x86_64 -nodefaults -display none -object secret,id=foo,foo=bar
qemu-system-x86_64: Property '.foo' not found
Note no location. This commit restores it:
qemu-system-x86_64: -object secret,id=foo,foo=bar: Property '.foo' not found
Note that the qemu_opts_foreach() bug just fixed could mask the bug
here: if the location it leaves dangling hasn't been clobbered, yet,
it's the correct one.
Reported-by: Eric Blake <eblake@redhat.com>
Cc: Daniel P. Berrange <berrange@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <1461767349-15329-4-git-send-email-armbru@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
[Paragraph on Error added to commit message]
2016-04-27 17:29:09 +03:00
|
|
|
obj = user_creatable_add_opts(opts, &err);
|
2016-02-10 21:40:59 +03:00
|
|
|
if (!obj) {
|
qom: -object error messages lost location, restore it
qemu_opts_foreach() runs its callback with the error location set to
the option's location. Any errors the callback reports use the
option's location automatically.
Commit 90998d5 moved the actual error reporting from "inside"
qemu_opts_foreach() to after it. Here's a typical hunk:
if (qemu_opts_foreach(qemu_find_opts("object"),
- object_create,
- object_create_initial, NULL)) {
+ user_creatable_add_opts_foreach,
+ object_create_initial, &err)) {
+ error_report_err(err);
exit(1);
}
Before, object_create() reports from within qemu_opts_foreach(), using
the option's location. Afterwards, we do it after
qemu_opts_foreach(), using whatever location happens to be current
there. Commonly a "none" location.
This is because Error objects don't have location information.
Problematic.
Reproducer:
$ qemu-system-x86_64 -nodefaults -display none -object secret,id=foo,foo=bar
qemu-system-x86_64: Property '.foo' not found
Note no location. This commit restores it:
qemu-system-x86_64: -object secret,id=foo,foo=bar: Property '.foo' not found
Note that the qemu_opts_foreach() bug just fixed could mask the bug
here: if the location it leaves dangling hasn't been clobbered, yet,
it's the correct one.
Reported-by: Eric Blake <eblake@redhat.com>
Cc: Daniel P. Berrange <berrange@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <1461767349-15329-4-git-send-email-armbru@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
[Paragraph on Error added to commit message]
2016-04-27 17:29:09 +03:00
|
|
|
error_report_err(err);
|
2016-02-10 21:40:59 +03:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
object_unref(obj);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void user_creatable_del(const char *id, Error **errp)
|
|
|
|
{
|
|
|
|
Object *container;
|
|
|
|
Object *obj;
|
|
|
|
|
|
|
|
container = object_get_objects_root();
|
|
|
|
obj = object_resolve_path_component(container, id);
|
|
|
|
if (!obj) {
|
|
|
|
error_setg(errp, "object '%s' not found", id);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!user_creatable_can_be_deleted(USER_CREATABLE(obj), errp)) {
|
|
|
|
error_setg(errp, "object '%s' is in use, can not be deleted", id);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
object_unparent(obj);
|
|
|
|
}
|
|
|
|
|
2014-01-16 20:34:38 +04:00
|
|
|
static void register_types(void)
|
|
|
|
{
|
|
|
|
static const TypeInfo uc_interface_info = {
|
|
|
|
.name = TYPE_USER_CREATABLE,
|
|
|
|
.parent = TYPE_INTERFACE,
|
|
|
|
.class_size = sizeof(UserCreatableClass),
|
|
|
|
};
|
|
|
|
|
|
|
|
type_register_static(&uc_interface_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
type_init(register_types)
|