From nobody Thu Oct 31 00:24:00 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) client-ip=170.10.133.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1633700285; cv=none; d=zohomail.com; s=zohoarc; b=KQbr2pn/oL+7W5kYZDTnP7T4KtRXfaQbkYnIwM8rwYd9R/95kDdNUvr+U27Ismyei9/O4nrQJ5OeATbPWZwglHg5N8O8F5lk6QX1Y+iE0XmEmqcJlCz9Zvdu4bPzhvGnsXu4x2zpTldvK2UVtiD9g1gkBa2vtGbJagXC1F3cuGc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633700285; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=Kl0F/qu/yfcKfVhGRunhOIBct+Fl2dIvaPt2uCwj9pY=; b=SfnTJ9E2ggoULfK+GqOX5fkNZk5JA6mU2sQq8YHgjfWj8RRQ7BQL4+boodx0zebfHzZ6qmrzIwU8ONPfJNVL4wVZjbwTNXLdIGsRcxWyFohZkXOJ8xt7plRdPOoAY+Njw1QfjG5Eo1VPfUwFpf4eWki3dUesToqCisjWFH1nXUw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by mx.zohomail.com with SMTPS id 1633700285862720.7638620457059; Fri, 8 Oct 2021 06:38:05 -0700 (PDT) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-90-Q6uxSh7QP7mjtJ6dXtEnsw-1; Fri, 08 Oct 2021 09:38:00 -0400 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 9BAE78B6193; Fri, 8 Oct 2021 13:37:09 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 1AC3F1024899; Fri, 8 Oct 2021 13:37:09 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id B6E384EA38; Fri, 8 Oct 2021 13:37:08 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 198Db7QT026387 for ; Fri, 8 Oct 2021 09:37:07 -0400 Received: by smtp.corp.redhat.com (Postfix) id 8CFDE1972E; Fri, 8 Oct 2021 13:37:07 +0000 (UTC) Received: from merkur.redhat.com (unknown [10.39.193.204]) by smtp.corp.redhat.com (Postfix) with ESMTP id 83D3526E74; Fri, 8 Oct 2021 13:37:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1633700284; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=Kl0F/qu/yfcKfVhGRunhOIBct+Fl2dIvaPt2uCwj9pY=; b=jInIArItkfKstL90o/hNmpbjXQLsTDNtz2A1kioiGuVB9QYwsmm7pNkScA3LM+EqeFSIJ6 2qVKoeGiOrd7Ybg4lykCLg1FHhYgnW2xmFUays090TNggA35FziRLqRwgSR0eSgDTJulol f5UUVjZ8XqcP1RZhYb/IyXx7vGX0Czw= X-MC-Unique: Q6uxSh7QP7mjtJ6dXtEnsw-1 From: Kevin Wolf To: qemu-devel@nongnu.org Subject: [PATCH v2 14/15] qdev: Base object creation on QDict rather than QemuOpts Date: Fri, 8 Oct 2021 15:34:41 +0200 Message-Id: <20211008133442.141332-15-kwolf@redhat.com> In-Reply-To: <20211008133442.141332-1-kwolf@redhat.com> References: <20211008133442.141332-1-kwolf@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-loop: libvir-list@redhat.com Cc: kwolf@redhat.com, damien.hedde@greensocs.com, pkrempa@redhat.com, ehabkost@redhat.com, qemu-block@nongnu.org, mst@redhat.com, libvir-list@redhat.com, jasowang@redhat.com, quintela@redhat.com, armbru@redhat.com, vsementsov@virtuozzo.com, lvivier@redhat.com, its@irrelevant.dk, pbonzini@redhat.com, eblake@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1633700286196100002 Content-Type: text/plain; charset="utf-8" QDicts are both what QMP natively uses and what the keyval parser produces. Going through QemuOpts isn't useful for either one, so switch the main device creation function to QDicts. By sharing more code with the -object/object-add code path, we can even reduce the code size a bit. This commit doesn't remove the detour through QemuOpts from any code path yet, but it allows the following commits to do so. Signed-off-by: Kevin Wolf --- include/hw/qdev-core.h | 11 +++--- include/hw/virtio/virtio-net.h | 3 +- include/monitor/qdev.h | 2 + hw/core/qdev.c | 7 ++-- hw/net/virtio-net.c | 23 +++++++----- hw/vfio/pci.c | 4 +- softmmu/qdev-monitor.c | 69 +++++++++++++++------------------- 7 files changed, 60 insertions(+), 59 deletions(-) diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 74d8b614a7..910042c650 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -180,7 +180,7 @@ struct DeviceState { char *canonical_path; bool realized; bool pending_deleted_event; - QemuOpts *opts; + QDict *opts; int hotplugged; bool allow_unplug_during_migration; BusState *parent_bus; @@ -205,8 +205,8 @@ struct DeviceListener { * On errors, it returns false and errp is set. Device creation * should fail in this case. */ - bool (*hide_device)(DeviceListener *listener, QemuOpts *device_opts, - Error **errp); + bool (*hide_device)(DeviceListener *listener, const QDict *device_opts, + bool from_json, Error **errp); QTAILQ_ENTRY(DeviceListener) link; }; =20 @@ -835,13 +835,14 @@ void device_listener_unregister(DeviceListener *liste= ner); =20 /** * @qdev_should_hide_device: - * @opts: QemuOpts as passed on cmdline. + * @opts: options QDict + * @from_json: true if @opts entries are typed, false for all strings * * Check if a device should be added. * When a device is added via qdev_device_add() this will be called, * and return if the device should be added now or not. */ -bool qdev_should_hide_device(QemuOpts *opts, Error **errp); +bool qdev_should_hide_device(const QDict *opts, bool from_json, Error **er= rp); =20 typedef enum MachineInitPhase { /* current_machine is NULL. */ diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index d118c95f69..74a10ebe85 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -209,7 +209,8 @@ struct VirtIONet { bool failover_primary_hidden; bool failover; DeviceListener primary_listener; - QemuOpts *primary_opts; + QDict *primary_opts; + bool primary_opts_from_json; Notifier migration_state; VirtioNetRssData rss_data; struct NetRxPkt *rx_pkt; diff --git a/include/monitor/qdev.h b/include/monitor/qdev.h index 74e6c55a2b..1d57bf6577 100644 --- a/include/monitor/qdev.h +++ b/include/monitor/qdev.h @@ -9,6 +9,8 @@ void qmp_device_add(QDict *qdict, QObject **ret_data, Error= **errp); =20 int qdev_device_help(QemuOpts *opts); DeviceState *qdev_device_add(QemuOpts *opts, Error **errp); +DeviceState *qdev_device_add_from_qdict(const QDict *opts, + bool from_json, Error **errp); =20 /** * qdev_set_id: parent the device and set its id if provided. diff --git a/hw/core/qdev.c b/hw/core/qdev.c index c3a021c444..7f06403752 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -28,6 +28,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qapi/qapi-events-qdev.h" +#include "qapi/qmp/qdict.h" #include "qapi/qmp/qerror.h" #include "qapi/visitor.h" #include "qemu/error-report.h" @@ -211,14 +212,14 @@ void device_listener_unregister(DeviceListener *liste= ner) QTAILQ_REMOVE(&device_listeners, listener, link); } =20 -bool qdev_should_hide_device(QemuOpts *opts, Error **errp) +bool qdev_should_hide_device(const QDict *opts, bool from_json, Error **er= rp) { ERRP_GUARD(); DeviceListener *listener; =20 QTAILQ_FOREACH(listener, &device_listeners, link) { if (listener->hide_device) { - if (listener->hide_device(listener, opts, errp)) { + if (listener->hide_device(listener, opts, from_json, errp)) { return true; } else if (*errp) { return false; @@ -958,7 +959,7 @@ static void device_finalize(Object *obj) dev->canonical_path =3D NULL; } =20 - qemu_opts_del(dev->opts); + qobject_unref(dev->opts); g_free(dev->id); } =20 diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index f503f28c00..09e173a558 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -858,9 +858,11 @@ static void failover_add_primary(VirtIONet *n, Error *= *errp) return; } =20 - dev =3D qdev_device_add(n->primary_opts, &err); + dev =3D qdev_device_add_from_qdict(n->primary_opts, + n->primary_opts_from_json, + &err); if (err) { - qemu_opts_del(n->primary_opts); + qobject_unref(n->primary_opts); n->primary_opts =3D NULL; } else { object_unref(OBJECT(dev)); @@ -3287,7 +3289,9 @@ static void virtio_net_migration_state_notifier(Notif= ier *notifier, void *data) } =20 static bool failover_hide_primary_device(DeviceListener *listener, - QemuOpts *device_opts, Error **er= rp) + const QDict *device_opts, + bool from_json, + Error **errp) { VirtIONet *n =3D container_of(listener, VirtIONet, primary_listener); const char *standby_id; @@ -3295,7 +3299,7 @@ static bool failover_hide_primary_device(DeviceListen= er *listener, if (!device_opts) { return false; } - standby_id =3D qemu_opt_get(device_opts, "failover_pair_id"); + standby_id =3D qdict_get_try_str(device_opts, "failover_pair_id"); if (g_strcmp0(standby_id, n->netclient_name) !=3D 0) { return false; } @@ -3306,12 +3310,8 @@ static bool failover_hide_primary_device(DeviceListe= ner *listener, return false; } =20 - /* - * Having a weak reference here should be okay because a device can't = be - * deleted while it's hidden. This will be replaced soon with a QDict = that - * has a clearer ownership model. - */ - n->primary_opts =3D device_opts; + n->primary_opts =3D qdict_clone_shallow(device_opts); + n->primary_opts_from_json =3D from_json; =20 /* failover_primary_hidden is set during feature negotiation */ return qatomic_read(&n->failover_primary_hidden); @@ -3502,8 +3502,11 @@ static void virtio_net_device_unrealize(DeviceState = *dev) g_free(n->vlans); =20 if (n->failover) { + qobject_unref(n->primary_opts); device_listener_unregister(&n->primary_listener); remove_migration_state_change_notifier(&n->migration_state); + } else { + assert(n->primary_opts =3D=3D NULL); } =20 max_queues =3D n->multiqueue ? n->max_queues : 1; diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 4feaa1cb68..5cdf1d4298 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -29,10 +29,10 @@ #include "hw/qdev-properties.h" #include "hw/qdev-properties-system.h" #include "migration/vmstate.h" +#include "qapi/qmp/qdict.h" #include "qemu/error-report.h" #include "qemu/main-loop.h" #include "qemu/module.h" -#include "qemu/option.h" #include "qemu/range.h" #include "qemu/units.h" #include "sysemu/kvm.h" @@ -941,7 +941,7 @@ static void vfio_pci_size_rom(VFIOPCIDevice *vdev) } =20 if (vfio_opt_rom_in_denylist(vdev)) { - if (dev->opts && qemu_opt_get(dev->opts, "rombar")) { + if (dev->opts && qdict_haskey(dev->opts, "rombar")) { warn_report("Device at %s is known to cause system instability" " issues during option rom execution", vdev->vbasedev.name); diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c index ccc3c11563..90882f1571 100644 --- a/softmmu/qdev-monitor.c +++ b/softmmu/qdev-monitor.c @@ -196,34 +196,6 @@ static void qdev_print_devinfos(bool show_no_user) g_slist_free(list); } =20 -static int set_property(void *opaque, const char *name, const char *value, - Error **errp) -{ - Object *obj =3D opaque; - QString *val; - Visitor *v; - int ret; - - if (strcmp(name, "driver") =3D=3D 0) - return 0; - if (strcmp(name, "bus") =3D=3D 0) - return 0; - - val =3D qstring_from_str(value); - v =3D qobject_input_visitor_new_keyval(QOBJECT(val)); - - if (!object_property_set(obj, name, v, errp)) { - ret =3D -1; - goto out; - } - - ret =3D 0; -out: - visit_free(v); - qobject_unref(val); - return ret; -} - static const char *find_typename_by_alias(const char *alias) { int i; @@ -623,15 +595,17 @@ const char *qdev_set_id(DeviceState *dev, char *id, E= rror **errp) return prop->name; } =20 -DeviceState *qdev_device_add(QemuOpts *opts, Error **errp) +DeviceState *qdev_device_add_from_qdict(const QDict *opts, + bool from_json, Error **errp) { ERRP_GUARD(); DeviceClass *dc; const char *driver, *path; + char *id; DeviceState *dev =3D NULL; BusState *bus =3D NULL; =20 - driver =3D qemu_opt_get(opts, "driver"); + driver =3D qdict_get_try_str(opts, "driver"); if (!driver) { error_setg(errp, QERR_MISSING_PARAMETER, "driver"); return NULL; @@ -644,7 +618,7 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **er= rp) } =20 /* find bus */ - path =3D qemu_opt_get(opts, "bus"); + path =3D qdict_get_try_str(opts, "bus"); if (path !=3D NULL) { bus =3D qbus_find(path, errp); if (!bus) { @@ -664,12 +638,12 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **= errp) } } =20 - if (qemu_opt_get(opts, "failover_pair_id")) { - if (!opts->id) { + if (qdict_haskey(opts, "failover_pair_id")) { + if (!qdict_haskey(opts, "id")) { error_setg(errp, "Device with failover_pair_id don't have id"); return NULL; } - if (qdev_should_hide_device(opts, errp)) { + if (qdev_should_hide_device(opts, from_json, errp)) { if (bus && !qbus_is_hotpluggable(bus)) { error_setg(errp, QERR_BUS_NO_HOTPLUG, bus->name); } @@ -710,18 +684,24 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **= errp) * set dev's parent and register its id. * If it fails it means the id is already taken. */ - if (!qdev_set_id(dev, g_strdup(qemu_opts_id(opts)), errp)) { + id =3D g_strdup(qdict_get_try_str(opts, "id")); + if (!qdev_set_id(dev, id, errp)) { goto err_del_dev; } =20 /* set properties */ - if (qemu_opt_foreach(opts, set_property, dev, errp)) { + dev->opts =3D qdict_clone_shallow(opts); + qdict_del(dev->opts, "driver"); + qdict_del(dev->opts, "bus"); + qdict_del(dev->opts, "id"); + + object_set_properties_from_keyval(&dev->parent_obj, dev->opts, from_js= on, + errp); + if (*errp) { goto err_del_dev; } =20 - dev->opts =3D opts; if (!qdev_realize(DEVICE(dev), bus, errp)) { - dev->opts =3D NULL; goto err_del_dev; } return dev; @@ -734,6 +714,19 @@ err_del_dev: return NULL; } =20 +/* Takes ownership of @opts on success */ +DeviceState *qdev_device_add(QemuOpts *opts, Error **errp) +{ + QDict *qdict =3D qemu_opts_to_qdict(opts, NULL); + DeviceState *ret; + + ret =3D qdev_device_add_from_qdict(qdict, false, errp); + if (ret) { + qemu_opts_del(opts); + } + qobject_unref(qdict); + return ret; +} =20 #define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", #= # __VA_ARGS__) static void qbus_print(Monitor *mon, BusState *bus, int indent); --=20 2.31.1