Skip to content

Commit 253e399

Browse files
committed
Merge remote-tracking branch 'remotes/kwolf/tags/for-upstream' into staging
qdev: Add JSON -device - Add a JSON mode to the -device command line option - net/vhost-{user,vdpa}: Fix device compatibility check - Minor iotests fixes # gpg: Signature made Fri 15 Oct 2021 07:41:22 AM PDT # gpg: using RSA key DC3DEB159A9AF95D3D7456FE7F09B272C88F2FD6 # gpg: issuer "[email protected]" # gpg: Good signature from "Kevin Wolf <[email protected]>" [full] * remotes/kwolf/tags/for-upstream: vl: Enable JSON syntax for -device qdev: Base object creation on QDict rather than QemuOpts virtio-net: Avoid QemuOpts in failover_find_primary_device() virtio-net: Store failover primary opts pointer locally qdev: Add Error parameter to hide_device() callbacks qemu-option: Allow deleting opts during qemu_opts_foreach() softmmu/qdev-monitor: add error handling in qdev_set_id qdev: Make DeviceState.id independent of QemuOpts qdev: Avoid using string visitor for properties iotests/051: Fix typo iotests/245: Fix type for iothread property qom: Reduce use of error_propagate() net/vhost-vdpa: Fix device compatibility check net/vhost-user: Fix device compatibility check net: Introduce NetClientInfo.check_peer_type() Signed-off-by: Richard Henderson <[email protected]>
2 parents 82d88f8 + 5dacda5 commit 253e399

File tree

23 files changed

+280
-178
lines changed

23 files changed

+280
-178
lines changed

hw/arm/virt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1459,7 +1459,7 @@ static void create_platform_bus(VirtMachineState *vms)
14591459
MemoryRegion *sysmem = get_system_memory();
14601460

14611461
dev = qdev_new(TYPE_PLATFORM_BUS_DEVICE);
1462-
dev->id = TYPE_PLATFORM_BUS_DEVICE;
1462+
dev->id = g_strdup(TYPE_PLATFORM_BUS_DEVICE);
14631463
qdev_prop_set_uint32(dev, "num_irqs", PLATFORM_BUS_NUM_IRQS);
14641464
qdev_prop_set_uint32(dev, "mmio_size", vms->memmap[VIRT_PLATFORM_BUS].size);
14651465
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);

hw/core/qdev-properties-system.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,12 @@ static void set_netdev(Object *obj, Visitor *v, const char *name,
431431
goto out;
432432
}
433433

434+
if (peers[i]->info->check_peer_type) {
435+
if (!peers[i]->info->check_peer_type(peers[i], obj->class, errp)) {
436+
goto out;
437+
}
438+
}
439+
434440
ncs[i] = peers[i];
435441
ncs[i]->queue_index = i;
436442
}

hw/core/qdev.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "qemu/osdep.h"
2929
#include "qapi/error.h"
3030
#include "qapi/qapi-events-qdev.h"
31+
#include "qapi/qmp/qdict.h"
3132
#include "qapi/qmp/qerror.h"
3233
#include "qapi/visitor.h"
3334
#include "qemu/error-report.h"
@@ -211,14 +212,17 @@ void device_listener_unregister(DeviceListener *listener)
211212
QTAILQ_REMOVE(&device_listeners, listener, link);
212213
}
213214

214-
bool qdev_should_hide_device(QemuOpts *opts)
215+
bool qdev_should_hide_device(const QDict *opts, bool from_json, Error **errp)
215216
{
217+
ERRP_GUARD();
216218
DeviceListener *listener;
217219

218220
QTAILQ_FOREACH(listener, &device_listeners, link) {
219221
if (listener->hide_device) {
220-
if (listener->hide_device(listener, opts)) {
222+
if (listener->hide_device(listener, opts, from_json, errp)) {
221223
return true;
224+
} else if (*errp) {
225+
return false;
222226
}
223227
}
224228
}
@@ -955,7 +959,8 @@ static void device_finalize(Object *obj)
955959
dev->canonical_path = NULL;
956960
}
957961

958-
qemu_opts_del(dev->opts);
962+
qobject_unref(dev->opts);
963+
g_free(dev->id);
959964
}
960965

961966
static void device_class_base_init(ObjectClass *class, void *data)

hw/net/virtio-net.c

Lines changed: 42 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -796,48 +796,34 @@ static inline uint64_t virtio_net_supported_guest_offloads(VirtIONet *n)
796796

797797
typedef struct {
798798
VirtIONet *n;
799-
char *id;
800-
} FailoverId;
799+
DeviceState *dev;
800+
} FailoverDevice;
801801

802802
/**
803-
* Set the id of the failover primary device
803+
* Set the failover primary device
804804
*
805805
* @opaque: FailoverId to setup
806806
* @opts: opts for device we are handling
807807
* @errp: returns an error if this function fails
808808
*/
809-
static int failover_set_primary(void *opaque, QemuOpts *opts, Error **errp)
809+
static int failover_set_primary(DeviceState *dev, void *opaque)
810810
{
811-
FailoverId *fid = opaque;
812-
const char *standby_id = qemu_opt_get(opts, "failover_pair_id");
811+
FailoverDevice *fdev = opaque;
812+
PCIDevice *pci_dev = (PCIDevice *)
813+
object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE);
813814

814-
if (g_strcmp0(standby_id, fid->n->netclient_name) == 0) {
815-
fid->id = g_strdup(opts->id);
815+
if (!pci_dev) {
816+
return 0;
817+
}
818+
819+
if (!g_strcmp0(pci_dev->failover_pair_id, fdev->n->netclient_name)) {
820+
fdev->dev = dev;
816821
return 1;
817822
}
818823

819824
return 0;
820825
}
821826

822-
/**
823-
* Find the primary device id for this failover virtio-net
824-
*
825-
* @n: VirtIONet device
826-
* @errp: returns an error if this function fails
827-
*/
828-
static char *failover_find_primary_device_id(VirtIONet *n)
829-
{
830-
Error *err = NULL;
831-
FailoverId fid;
832-
833-
fid.n = n;
834-
if (!qemu_opts_foreach(qemu_find_opts("device"),
835-
failover_set_primary, &fid, &err)) {
836-
return NULL;
837-
}
838-
return fid.id;
839-
}
840-
841827
/**
842828
* Find the primary device for this failover virtio-net
843829
*
@@ -846,39 +832,38 @@ static char *failover_find_primary_device_id(VirtIONet *n)
846832
*/
847833
static DeviceState *failover_find_primary_device(VirtIONet *n)
848834
{
849-
char *id = failover_find_primary_device_id(n);
850-
851-
if (!id) {
852-
return NULL;
853-
}
835+
FailoverDevice fdev = {
836+
.n = n,
837+
};
854838

855-
return qdev_find_recursive(sysbus_get_default(), id);
839+
qbus_walk_children(sysbus_get_default(), failover_set_primary, NULL,
840+
NULL, NULL, &fdev);
841+
return fdev.dev;
856842
}
857843

858844
static void failover_add_primary(VirtIONet *n, Error **errp)
859845
{
860846
Error *err = NULL;
861-
QemuOpts *opts;
862-
char *id;
863847
DeviceState *dev = failover_find_primary_device(n);
864848

865849
if (dev) {
866850
return;
867851
}
868852

869-
id = failover_find_primary_device_id(n);
870-
if (!id) {
853+
if (!n->primary_opts) {
871854
error_setg(errp, "Primary device not found");
872855
error_append_hint(errp, "Virtio-net failover will not work. Make "
873856
"sure primary device has parameter"
874857
" failover_pair_id=%s\n", n->netclient_name);
875858
return;
876859
}
877-
opts = qemu_opts_find(qemu_find_opts("device"), id);
878-
g_assert(opts); /* cannot be NULL because id was found using opts list */
879-
dev = qdev_device_add(opts, &err);
860+
861+
dev = qdev_device_add_from_qdict(n->primary_opts,
862+
n->primary_opts_from_json,
863+
&err);
880864
if (err) {
881-
qemu_opts_del(opts);
865+
qobject_unref(n->primary_opts);
866+
n->primary_opts = NULL;
882867
} else {
883868
object_unref(OBJECT(dev));
884869
}
@@ -3304,19 +3289,30 @@ static void virtio_net_migration_state_notifier(Notifier *notifier, void *data)
33043289
}
33053290

33063291
static bool failover_hide_primary_device(DeviceListener *listener,
3307-
QemuOpts *device_opts)
3292+
const QDict *device_opts,
3293+
bool from_json,
3294+
Error **errp)
33083295
{
33093296
VirtIONet *n = container_of(listener, VirtIONet, primary_listener);
33103297
const char *standby_id;
33113298

33123299
if (!device_opts) {
33133300
return false;
33143301
}
3315-
standby_id = qemu_opt_get(device_opts, "failover_pair_id");
3302+
standby_id = qdict_get_try_str(device_opts, "failover_pair_id");
33163303
if (g_strcmp0(standby_id, n->netclient_name) != 0) {
33173304
return false;
33183305
}
33193306

3307+
if (n->primary_opts) {
3308+
error_setg(errp, "Cannot attach more than one primary device to '%s'",
3309+
n->netclient_name);
3310+
return false;
3311+
}
3312+
3313+
n->primary_opts = qdict_clone_shallow(device_opts);
3314+
n->primary_opts_from_json = from_json;
3315+
33203316
/* failover_primary_hidden is set during feature negotiation */
33213317
return qatomic_read(&n->failover_primary_hidden);
33223318
}
@@ -3506,8 +3502,11 @@ static void virtio_net_device_unrealize(DeviceState *dev)
35063502
g_free(n->vlans);
35073503

35083504
if (n->failover) {
3505+
qobject_unref(n->primary_opts);
35093506
device_listener_unregister(&n->primary_listener);
35103507
remove_migration_state_change_notifier(&n->migration_state);
3508+
} else {
3509+
assert(n->primary_opts == NULL);
35113510
}
35123511

35133512
max_queues = n->multiqueue ? n->max_queues : 1;

hw/pci-bridge/pci_expander_bridge.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ static void pxb_dev_realize_common(PCIDevice *dev, bool pcie, Error **errp)
245245
} else {
246246
bus = pci_root_bus_new(ds, "pxb-internal", NULL, NULL, 0, TYPE_PXB_BUS);
247247
bds = qdev_new("pci-bridge");
248-
bds->id = dev_name;
248+
bds->id = g_strdup(dev_name);
249249
qdev_prop_set_uint8(bds, PCI_BRIDGE_DEV_PROP_CHASSIS_NR, pxb->bus_nr);
250250
qdev_prop_set_bit(bds, PCI_BRIDGE_DEV_PROP_SHPC, false);
251251
}

hw/ppc/e500.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1006,7 +1006,7 @@ void ppce500_init(MachineState *machine)
10061006
/* Platform Bus Device */
10071007
if (pmc->has_platform_bus) {
10081008
dev = qdev_new(TYPE_PLATFORM_BUS_DEVICE);
1009-
dev->id = TYPE_PLATFORM_BUS_DEVICE;
1009+
dev->id = g_strdup(TYPE_PLATFORM_BUS_DEVICE);
10101010
qdev_prop_set_uint32(dev, "num_irqs", pmc->platform_bus_num_irqs);
10111011
qdev_prop_set_uint32(dev, "mmio_size", pmc->platform_bus_size);
10121012
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);

hw/vfio/pci.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@
2929
#include "hw/qdev-properties.h"
3030
#include "hw/qdev-properties-system.h"
3131
#include "migration/vmstate.h"
32+
#include "qapi/qmp/qdict.h"
3233
#include "qemu/error-report.h"
3334
#include "qemu/main-loop.h"
3435
#include "qemu/module.h"
35-
#include "qemu/option.h"
3636
#include "qemu/range.h"
3737
#include "qemu/units.h"
3838
#include "sysemu/kvm.h"
@@ -941,7 +941,7 @@ static void vfio_pci_size_rom(VFIOPCIDevice *vdev)
941941
}
942942

943943
if (vfio_opt_rom_in_denylist(vdev)) {
944-
if (dev->opts && qemu_opt_get(dev->opts, "rombar")) {
944+
if (dev->opts && qdict_haskey(dev->opts, "rombar")) {
945945
warn_report("Device at %s is known to cause system instability"
946946
" issues during option rom execution",
947947
vdev->vbasedev.name);

hw/xen/xen-legacy-backend.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,8 @@ static struct XenLegacyDevice *xen_be_get_xendev(const char *type, int dom,
276276
xendev = g_malloc0(ops->size);
277277
object_initialize(&xendev->qdev, ops->size, TYPE_XENBACKEND);
278278
OBJECT(xendev)->free = g_free;
279-
qdev_set_id(DEVICE(xendev), g_strdup_printf("xen-%s-%d", type, dev));
279+
qdev_set_id(DEVICE(xendev), g_strdup_printf("xen-%s-%d", type, dev),
280+
&error_fatal);
280281
qdev_realize(DEVICE(xendev), xen_sysbus, &error_fatal);
281282
object_unref(OBJECT(xendev));
282283

include/hw/qdev-core.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,11 @@ struct DeviceState {
176176
Object parent_obj;
177177
/*< public >*/
178178

179-
const char *id;
179+
char *id;
180180
char *canonical_path;
181181
bool realized;
182182
bool pending_deleted_event;
183-
QemuOpts *opts;
183+
QDict *opts;
184184
int hotplugged;
185185
bool allow_unplug_during_migration;
186186
BusState *parent_bus;
@@ -201,8 +201,12 @@ struct DeviceListener {
201201
* informs qdev if a device should be visible or hidden. We can
202202
* hide a failover device depending for example on the device
203203
* opts.
204+
*
205+
* On errors, it returns false and errp is set. Device creation
206+
* should fail in this case.
204207
*/
205-
bool (*hide_device)(DeviceListener *listener, QemuOpts *device_opts);
208+
bool (*hide_device)(DeviceListener *listener, const QDict *device_opts,
209+
bool from_json, Error **errp);
206210
QTAILQ_ENTRY(DeviceListener) link;
207211
};
208212

@@ -831,13 +835,15 @@ void device_listener_unregister(DeviceListener *listener);
831835

832836
/**
833837
* @qdev_should_hide_device:
834-
* @opts: QemuOpts as passed on cmdline.
838+
* @opts: options QDict
839+
* @from_json: true if @opts entries are typed, false for all strings
840+
* @errp: pointer to error object
835841
*
836842
* Check if a device should be added.
837843
* When a device is added via qdev_device_add() this will be called,
838844
* and return if the device should be added now or not.
839845
*/
840-
bool qdev_should_hide_device(QemuOpts *opts);
846+
bool qdev_should_hide_device(const QDict *opts, bool from_json, Error **errp);
841847

842848
typedef enum MachineInitPhase {
843849
/* current_machine is NULL. */

include/hw/virtio/virtio-net.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ struct VirtIONet {
209209
bool failover_primary_hidden;
210210
bool failover;
211211
DeviceListener primary_listener;
212+
QDict *primary_opts;
213+
bool primary_opts_from_json;
212214
Notifier migration_state;
213215
VirtioNetRssData rss_data;
214216
struct NetRxPkt *rx_pkt;

0 commit comments

Comments
 (0)