Re: [PULL 14/15] qdev: Base object creation on QDict rather than QemuOpts
Am 07.07.2022 um 22:24 hat Peter Maydell geschrieben: > On Mon, 4 Jul 2022 at 05:50, Markus Armbruster wrote: > > My initial (knee-jerk) reaction to breaking array properties: Faster, > > Pussycat! Kill! Kill! > > In an ideal world, what would you replace them with? The next (and final) patch in this pull request added JSON syntax for -device, so we can actually have proper list properties now that are accessed with the normal list visitors. I suppose some integration with the qdev property system is still missing, but on the QOM level it could be used. In the ideal world, we would also be able to replace the human CLI syntax so that JSON isn't required for this, but doing this in reality would probably cause new compatibility problems - though libvirt has been using JSON for a while, so I guess it wouldn't mind an incompatible change of human syntax. Kevin
Re: The case for array properties (was: [PULL 14/15] qdev: Base object creation on QDict rather than QemuOpts)
On Fri, 8 Jul 2022 at 12:40, Markus Armbruster wrote: > > Cc'ing QOM maintainers. > > Peter Maydell writes: > > > On Mon, 4 Jul 2022 at 05:50, Markus Armbruster wrote: > >> My initial (knee-jerk) reaction to breaking array properties: Faster, > >> Pussycat! Kill! Kill! > > > > In an ideal world, what would you replace them with? > > Let's first recapitulate their intended purpose. > > commit 339659041f87a76f8b71ad3d12cadfc5f89b4bb3q > Author: Peter Crosthwaite > Date: Tue Aug 19 23:55:52 2014 -0700 > > qom: Add automatic arrayification to object_property_add() > > If "[*]" is given as the last part of a QOM property name, treat that > as an array property. The added property is given the first available > name, replacing the * with a decimal number counting from 0. > > First add with name "foo[*]" will be "foo[0]". Second "foo[1]" and so > on. > > Callers may inspect the ObjectProperty * return value to see what > number the added property was given. > > Signed-off-by: Peter Crosthwaite > Signed-off-by: Andreas Färber > > This describes how they work, but sadly not why we want them. For such > arcane lore, we need to consult a guru. Possibly via the mailing list > archive. This is not the initial array property feature addition. It's adding a convenience extra subfeature (ability to use "[*]" to mean "next one in the array"). The inital array property feature commit is: commit 0be6bfac6262900425c10847de513ee2490078d3 Author: Peter Maydell Date: Fri Mar 15 16:41:57 2013 + qdev: Implement (variable length) array properties Add support for declaring array properties for qdev devices. These work by defining an initial static property 'len-arrayname' which the user of the device should set to the desired size of the array. When this property is set, memory is allocated for the array elements, and dynamic properties "arrayname[0]", "arrayname[1]"... are created so the user of the device can then set the values of the individual array elements. Admittedly this doesn't give the justification either :-( The reason is for the benefit of the following commit (and similar use cases): commit 8bd4824a6122292060a318741595927e0d05ff5e Author: Peter Maydell Date: Fri Mar 15 16:41:57 2013 + hw/arm_sysctl: Implement SYS_CFG_VOLT Implement the SYS_CFG_VOLT registers which return the voltage of various supplies on motherboard and daughterboard. Since QEMU implements a perfectly stable power supply these registers always return a constant value. The number and value of the daughterboard voltages is dependent on the specific daughterboard, so we use a property array to allow the board to configure them appropriately. > We occasionally have a need for an array of properties where the length > of the array is not fixed at compile time. Say in code common to > several related devices, where some have two frobs, some four, and a > future one may have some other number. > > We could define properties frob0, frob1, ... frobN for some fixed N. > Users have to set them like frob0=...,frob1=... and so forth. We need > code to reject frobI=... for I exeeding the actual limit. > > Array properties spare developers picking a fixed N, and users adding an > index to the property name. Whether the latter is a good idea is > unclear. We need code to reject usage exceeding the actual limit. Note that the initial intention of array properties was largely for within-QEMU-code QOM properties. The usage of array properties for user-creatable devices is a later development. The basic rationale for array properties is: Sometimes the thing we want to be able to configure on a device is naturally expressed as "we have an indexed set of things". When writing a device implementation, it's nice to be able to straightforwardly say "this is an indexed set of things" and have the property system set the device struct fields accordingly (ie setting the num_foo struct field to the number of things and the foo field to an allocated array of foos), and for the way that device users to set the values of that indexed set of things not to look too awful either. The specific implementation we have today is just a cute hack that avoided having to mess about too much with the core QOM property implementation. (And it's only the implementation that imposes the "set the length first" constraint, that's not inherent to the idea of array properties.) I don't have a strong feeling about the "[*]" automatic-indexing subfeature -- none of the use of array properties that I've added uses that. thanks -- PMM
Re: The case for array properties (was: [PULL 14/15] qdev: Base object creation on QDict rather than QemuOpts)
On Fri, Jul 08, 2022 at 01:40:43PM +0200, Markus Armbruster wrote: > Cc'ing QOM maintainers. > > Peter Maydell writes: > > > On Mon, 4 Jul 2022 at 05:50, Markus Armbruster wrote: > >> My initial (knee-jerk) reaction to breaking array properties: Faster, > >> Pussycat! Kill! Kill! > > > > In an ideal world, what would you replace them with? > > Let's first recapitulate their intended purpose. > > commit 339659041f87a76f8b71ad3d12cadfc5f89b4bb3q > Author: Peter Crosthwaite > Date: Tue Aug 19 23:55:52 2014 -0700 > > qom: Add automatic arrayification to object_property_add() > > If "[*]" is given as the last part of a QOM property name, treat that > as an array property. The added property is given the first available > name, replacing the * with a decimal number counting from 0. > > First add with name "foo[*]" will be "foo[0]". Second "foo[1]" and so > on. > > Callers may inspect the ObjectProperty * return value to see what > number the added property was given. > > Signed-off-by: Peter Crosthwaite > Signed-off-by: Andreas Färber > > This describes how they work, but sadly not why we want them. For such > arcane lore, we need to consult a guru. Possibly via the mailing list > archive. Also doesn't describe why we need to explicitly set the array length upfront, rather than inferring it from the set of elements that are specified, auto-extending the array bounds as we set each property. > Digression: when you add a feature, please, please, *please* explain why > you need it right in the commit message. Such rationale is useful > information, tends to age well, and can be quite laborious to > reconstruct later. > > Even though I'm sure we discussed the intended purpose(s) of array > properties before, a quick grep of my list archive comes up mostly > empty, so I'm falling back to (foggy) memory. Please correct mistakes > and fill in omissions. > > We occasionally have a need for an array of properties where the length > of the array is not fixed at compile time. Say in code common to > several related devices, where some have two frobs, some four, and a > future one may have some other number. > > We could define properties frob0, frob1, ... frobN for some fixed N. > Users have to set them like frob0=...,frob1=... and so forth. We need > code to reject frobI=... for I exeeding the actual limit. > > Array properties spare developers picking a fixed N, and users adding an > index to the property name. Whether the latter is a good idea is > unclear. We need code to reject usage exceeding the actual limit. If we consider that our canonical representation is aiming to be QAPI, and QAPI has unbounded arrays, then by implication if we want a mapping to a flat CLI syntax, then we need some mechanism for unbounded arrays. It would be valid to argue that we shouldn'be be trying to map the full expressiveness of QAPI into a flat CLI syntax though, and should just strive for full JSON everywhere. Indeed every time we have these discussions, I wish we were already at the "full JSON everywhere" point, so we can stop consuming our time debating how to flatten JSON structure into CLI options. But since these array props already exist, we need to find a way out of the problem... With regards, Daniel -- |: https://berrange.com -o-https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o-https://fstop138.berrange.com :| |: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|
The case for array properties (was: [PULL 14/15] qdev: Base object creation on QDict rather than QemuOpts)
Cc'ing QOM maintainers. Peter Maydell writes: > On Mon, 4 Jul 2022 at 05:50, Markus Armbruster wrote: >> My initial (knee-jerk) reaction to breaking array properties: Faster, >> Pussycat! Kill! Kill! > > In an ideal world, what would you replace them with? Let's first recapitulate their intended purpose. commit 339659041f87a76f8b71ad3d12cadfc5f89b4bb3q Author: Peter Crosthwaite Date: Tue Aug 19 23:55:52 2014 -0700 qom: Add automatic arrayification to object_property_add() If "[*]" is given as the last part of a QOM property name, treat that as an array property. The added property is given the first available name, replacing the * with a decimal number counting from 0. First add with name "foo[*]" will be "foo[0]". Second "foo[1]" and so on. Callers may inspect the ObjectProperty * return value to see what number the added property was given. Signed-off-by: Peter Crosthwaite Signed-off-by: Andreas Färber This describes how they work, but sadly not why we want them. For such arcane lore, we need to consult a guru. Possibly via the mailing list archive. Digression: when you add a feature, please, please, *please* explain why you need it right in the commit message. Such rationale is useful information, tends to age well, and can be quite laborious to reconstruct later. Even though I'm sure we discussed the intended purpose(s) of array properties before, a quick grep of my list archive comes up mostly empty, so I'm falling back to (foggy) memory. Please correct mistakes and fill in omissions. We occasionally have a need for an array of properties where the length of the array is not fixed at compile time. Say in code common to several related devices, where some have two frobs, some four, and a future one may have some other number. We could define properties frob0, frob1, ... frobN for some fixed N. Users have to set them like frob0=...,frob1=... and so forth. We need code to reject frobI=... for I exeeding the actual limit. Array properties spare developers picking a fixed N, and users adding an index to the property name. Whether the latter is a good idea is unclear. We need code to reject usage exceeding the actual limit. A secondary use is (was?) avoiding memory region name clashes in code we don't want to touch. Discussed in the review of my attempt to strangle array properties in 2014: Message-ID: <87sihn9nji@blackfin.pond.sub.org> https://lists.gnu.org/archive/html/qemu-devel/2014-11/msg02103.html
Re: [PULL 14/15] qdev: Base object creation on QDict rather than QemuOpts
On Mon, 4 Jul 2022 at 05:50, Markus Armbruster wrote: > My initial (knee-jerk) reaction to breaking array properties: Faster, > Pussycat! Kill! Kill! In an ideal world, what would you replace them with? thanks -- PMM
Re: [PULL 14/15] qdev: Base object creation on QDict rather than QemuOpts
Markus Armbruster writes: > Peter Maydell writes: > >> On Fri, 15 Oct 2021 at 16:01, Kevin Wolf wrote: >>> 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 >>> Message-Id: <20211008133442.141332-15-kw...@redhat.com> >>> Reviewed-by: Michael S. Tsirkin >>> Tested-by: Peter Krempa >>> Signed-off-by: Kevin Wolf >> >> Hi; we discovered via a report on IRC this this commit broke >> handling of "array properties", of which one example is: >> qemu-system-x86_64 -netdev user,id=a -device rocker,len-ports=1,ports[0]=a >> >> This used to work, and now fails with >> qemu-system-x86_64: -device rocker,len-ports=1,ports[0]=a: Property >> 'rocker.ports[0]' not found >> >> I think this happens because array properties have the >> requirement that the len-foo property is set first before >> any of the foo[n] properties can be set. In the old code >> I guess we used to set properties from the command line >> in the order they were specified, whereas in the new code >> we end up in object_set_properties_from_qdict() which >> tries to set them in whatever order the qdict hash table >> provides them, which turns out to be the wrong one :-( >> >> Any suggestions for how to address this ? > > My initial (knee-jerk) reaction to breaking array properties: Faster, > Pussycat! Kill! Kill! > > Back to serious: replace the implementation of QDict so it iterates in > order? I just sent [RFC PATCH] qobject: Rewrite implementation of QDict for in-order traversal Message-Id: <20220705095421.2455041-1-arm...@redhat.com> Please test whether this fixes the regressions you observed.
Re: [PULL 14/15] qdev: Base object creation on QDict rather than QemuOpts
Peter Maydell writes: > On Fri, 15 Oct 2021 at 16:01, Kevin Wolf wrote: >> 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 >> Message-Id: <20211008133442.141332-15-kw...@redhat.com> >> Reviewed-by: Michael S. Tsirkin >> Tested-by: Peter Krempa >> Signed-off-by: Kevin Wolf > > Hi; we discovered via a report on IRC this this commit broke > handling of "array properties", of which one example is: > qemu-system-x86_64 -netdev user,id=a -device rocker,len-ports=1,ports[0]=a > > This used to work, and now fails with > qemu-system-x86_64: -device rocker,len-ports=1,ports[0]=a: Property > 'rocker.ports[0]' not found > > I think this happens because array properties have the > requirement that the len-foo property is set first before > any of the foo[n] properties can be set. In the old code > I guess we used to set properties from the command line > in the order they were specified, whereas in the new code > we end up in object_set_properties_from_qdict() which > tries to set them in whatever order the qdict hash table > provides them, which turns out to be the wrong one :-( > > Any suggestions for how to address this ? My initial (knee-jerk) reaction to breaking array properties: Faster, Pussycat! Kill! Kill! Back to serious: replace the implementation of QDict so it iterates in order?
Re: [PULL 14/15] qdev: Base object creation on QDict rather than QemuOpts
On Fri, 15 Oct 2021 at 16:01, Kevin Wolf wrote: > 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 > Message-Id: <20211008133442.141332-15-kw...@redhat.com> > Reviewed-by: Michael S. Tsirkin > Tested-by: Peter Krempa > Signed-off-by: Kevin Wolf Hi; we discovered via a report on IRC this this commit broke handling of "array properties", of which one example is: qemu-system-x86_64 -netdev user,id=a -device rocker,len-ports=1,ports[0]=a This used to work, and now fails with qemu-system-x86_64: -device rocker,len-ports=1,ports[0]=a: Property 'rocker.ports[0]' not found I think this happens because array properties have the requirement that the len-foo property is set first before any of the foo[n] properties can be set. In the old code I guess we used to set properties from the command line in the order they were specified, whereas in the new code we end up in object_set_properties_from_qdict() which tries to set them in whatever order the qdict hash table provides them, which turns out to be the wrong one :-( Any suggestions for how to address this ? thanks -- PMM
[PULL 14/15] qdev: Base object creation on QDict rather than QemuOpts
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 Message-Id: <20211008133442.141332-15-kw...@redhat.com> Reviewed-by: Michael S. Tsirkin Tested-by: Peter Krempa Signed-off-by: Kevin Wolf --- include/hw/qdev-core.h | 12 +++--- 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, 61 insertions(+), 59 deletions(-) diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 74d8b614a7..1bad07002d 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; }; @@ -835,13 +835,15 @@ void device_listener_unregister(DeviceListener *listener); /** * @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 + * @errp: pointer to error object * * 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 **errp); 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); 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); /** * 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 *listener) QTAILQ_REMOVE(&device_listeners, listener, link); } -bool qdev_should_hide_device(QemuOpts *opts, Error **errp) +bool qdev_should_hide_device(const QDict *opts, bool from_json, Error **errp) { ERRP_GUARD(); DeviceListener *listener; 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 = NULL; } -qemu_opts_del(dev->opts); +qobject_unref(dev->opts); g_free(dev->id); } 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; } -