From patchwork Mon Oct 19 15:09:40 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= X-Patchwork-Id: 532375 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 00D0C1401F6 for ; Tue, 20 Oct 2015 02:15:24 +1100 (AEDT) Received: from localhost ([::1]:40061 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZoC9h-0004gB-T2 for incoming@patchwork.ozlabs.org; Mon, 19 Oct 2015 11:15:21 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41519) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZoC52-0005Gh-In for qemu-devel@nongnu.org; Mon, 19 Oct 2015 11:10:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZoC4v-00028q-VC for qemu-devel@nongnu.org; Mon, 19 Oct 2015 11:10:32 -0400 Received: from mx1.redhat.com ([209.132.183.28]:38871) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZoC4m-00023G-SN; Mon, 19 Oct 2015 11:10:17 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (Postfix) with ESMTPS id 6C228A58B7; Mon, 19 Oct 2015 15:10:16 +0000 (UTC) Received: from localhost.localdomain.com (vpn1-7-30.ams2.redhat.com [10.36.7.30]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t9JF9uFt002201; Mon, 19 Oct 2015 11:10:14 -0400 From: "Daniel P. Berrange" To: qemu-devel@nongnu.org Date: Mon, 19 Oct 2015 16:09:40 +0100 Message-Id: <1445267389-21846-9-git-send-email-berrange@redhat.com> In-Reply-To: <1445267389-21846-1-git-send-email-berrange@redhat.com> References: <1445267389-21846-1-git-send-email-berrange@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: Kevin Wolf , Josh Durgin , Ronnie Sahlberg , qemu-block@nongnu.org, Markus Armbruster , Stefan Hajnoczi , Paolo Bonzini Subject: [Qemu-devel] [PATCH 08/17] qom: add user_creatable_add & user_creatable_del methods X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org The QMP monitor code has two helper methods object_add and qmp_object_del that are called from several places in the code (QMP, HMP and main emulator startup). We soon need to use this code from qemu-img, qemu-io and qemu-nbd too, but don't want those to depend on the monitor. To avoid this, move object_add to user_creatable_add an qmp_object_del to user_creatable_del, in the object_interfaces.c file Signed-off-by: Daniel P. Berrange --- hmp.c | 11 ++++-- include/monitor/monitor.h | 3 -- include/qom/object_interfaces.h | 31 +++++++++++++++++ qmp.c | 75 ++++------------------------------------ qom/object_interfaces.c | 76 +++++++++++++++++++++++++++++++++++++++++ vl.c | 8 +++-- 6 files changed, 127 insertions(+), 77 deletions(-) diff --git a/hmp.c b/hmp.c index 5048eee..409d05d 100644 --- a/hmp.c +++ b/hmp.c @@ -28,6 +28,7 @@ #include "qapi/qmp/qerror.h" #include "qapi/string-output-visitor.h" #include "qapi-visit.h" +#include "qom/object_interfaces.h" #include "ui/console.h" #include "block/qapi.h" #include "qemu-io.h" @@ -1630,6 +1631,7 @@ void hmp_object_add(Monitor *mon, const QDict *qdict) void *dummy = NULL; OptsVisitor *ov; QDict *pdict; + Object *obj = NULL; opts = qemu_opts_from_qdict(qemu_find_opts("object"), qdict, &err); if (err) { @@ -1656,12 +1658,12 @@ void hmp_object_add(Monitor *mon, const QDict *qdict) goto out_end; } - object_add(type, id, pdict, opts_get_visitor(ov), &err); + obj = user_creatable_add(type, id, pdict, opts_get_visitor(ov), &err); out_end: visit_end_struct(opts_get_visitor(ov), &err_end); if (!err && err_end) { - qmp_object_del(id, NULL); + user_creatable_del(id, NULL); } error_propagate(&err, err_end); out_clean: @@ -1672,6 +1674,9 @@ out_clean: g_free(id); g_free(type); g_free(dummy); + if (obj) { + object_unref(obj); + } out: hmp_handle_error(mon, &err); @@ -1904,7 +1909,7 @@ void hmp_object_del(Monitor *mon, const QDict *qdict) const char *id = qdict_get_str(qdict, "id"); Error *err = NULL; - qmp_object_del(id, &err); + user_creatable_del(id, &err); hmp_handle_error(mon, &err); } diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h index 91b95ae..aa0f373 100644 --- a/include/monitor/monitor.h +++ b/include/monitor/monitor.h @@ -43,9 +43,6 @@ void monitor_read_command(Monitor *mon, int show_prompt); int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func, void *opaque); -void object_add(const char *type, const char *id, const QDict *qdict, - Visitor *v, Error **errp); - AddfdInfo *monitor_fdset_add_fd(int fd, bool has_fdset_id, int64_t fdset_id, bool has_opaque, const char *opaque, Error **errp); diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h index 283ae0d..3e2afeb 100644 --- a/include/qom/object_interfaces.h +++ b/include/qom/object_interfaces.h @@ -2,6 +2,8 @@ #define OBJECT_INTERFACES_H #include "qom/object.h" +#include "qapi/qmp/qdict.h" +#include "qapi/visitor.h" #define TYPE_USER_CREATABLE "user-creatable" @@ -72,4 +74,33 @@ void user_creatable_complete(Object *obj, Error **errp); * from implements USER_CREATABLE interface. */ bool user_creatable_can_be_deleted(UserCreatable *uc, Error **errp); + +/** + * user_creatable_add: + * @type: the object type name + * @id: the unique ID for the object + * @qdict: the object parameters + * @v: the visitor + * @errp: if an error occurs, a pointer to an area to store the error + * + * Create an instance of the user creatable object @type, placing + * it in the object composition tree with name @id, initializing + * it with properties from @qdict + * + * Returns: the newly created object or NULL on error + */ +Object *user_creatable_add(const char *type, const char *id, + const QDict *qdict, + Visitor *v, Error **errp); + +/** + * user_creatable_del: + * @id: the unique ID for the object + * @errp: if an error occurs, a pointer to an area to store the error + * + * Delete an instance of the user creatable object identified + * by @id. + */ +void user_creatable_del(const char *id, Error **errp); + #endif diff --git a/qmp.c b/qmp.c index d9ecede..feea847 100644 --- a/qmp.c +++ b/qmp.c @@ -613,65 +613,13 @@ void qmp_add_client(const char *protocol, const char *fdname, close(fd); } -void object_add(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; - } - - if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) { - error_setg(errp, "object type '%s' isn't supported by object-add", - type); - return; - } - - if (object_class_is_abstract(klass)) { - error_setg(errp, "object type '%s' is abstract", type); - return; - } - - 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); -} void qmp_object_add(const char *type, const char *id, bool has_props, QObject *props, Error **errp) { const QDict *pdict = NULL; QmpInputVisitor *qiv; + Object *obj; if (props) { pdict = qobject_to_qdict(props); @@ -682,27 +630,16 @@ void qmp_object_add(const char *type, const char *id, } qiv = qmp_input_visitor_new(props); - object_add(type, id, pdict, qmp_input_get_visitor(qiv), errp); + obj = user_creatable_add(type, id, pdict, qmp_input_get_visitor(qiv), errp); qmp_input_visitor_cleanup(qiv); + if (obj) { + object_unref(obj); + } } void qmp_object_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 id not found"); - return; - } - - if (!user_creatable_can_be_deleted(USER_CREATABLE(obj), errp)) { - error_setg(errp, "%s is in use, can not be deleted", id); - return; - } - object_unparent(obj); + user_creatable_del(id, errp); } MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp) diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c index a66cd60..d94995f 100644 --- a/qom/object_interfaces.c +++ b/qom/object_interfaces.c @@ -30,6 +30,82 @@ bool user_creatable_can_be_deleted(UserCreatable *uc, Error **errp) } } +Object *user_creatable_add(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; +} + +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 id not found"); + return; + } + + if (!user_creatable_can_be_deleted(USER_CREATABLE(obj), errp)) { + error_setg(errp, "%s is in use, can not be deleted", id); + return; + } + object_unparent(obj); +} + static void register_types(void) { static const TypeInfo uc_interface_info = { diff --git a/vl.c b/vl.c index 7c806a2..e0b571e 100644 --- a/vl.c +++ b/vl.c @@ -2775,6 +2775,7 @@ static int object_create(void *opaque, QemuOpts *opts, Error **errp) OptsVisitor *ov; QDict *pdict; bool (*type_predicate)(const char *) = opaque; + Object *obj = NULL; ov = opts_visitor_new(opts); pdict = qemu_opts_to_qdict(opts, NULL); @@ -2799,13 +2800,13 @@ static int object_create(void *opaque, QemuOpts *opts, Error **errp) goto out; } - object_add(type, id, pdict, opts_get_visitor(ov), &err); + obj = user_creatable_add(type, id, pdict, opts_get_visitor(ov), &err); if (err) { goto out; } visit_end_struct(opts_get_visitor(ov), &err); if (err) { - qmp_object_del(id, NULL); + user_creatable_del(id, NULL); } out: @@ -2815,6 +2816,9 @@ out: g_free(id); g_free(type); g_free(dummy); + if (obj) { + object_unref(obj); + } if (err) { error_report_err(err); return -1;