mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-11-05 20:35:44 +00:00
qdev-monitor: Fix check for full bus
Property bus has always been too screwed up to be really usable for
values other than plain bus IDs. This just fixes a bug that crept in
in commit 1395af6
"qdev: add a maximum device allowed field for the
bus."
It doesn't always fail when it should:
$ qemu-system-x86_64 -nodefaults -device virtio-serial-pci -device virtio-rng-device,bus=pci.0/virtio-serial-pci/virtio-bus
Happily plugs the virtio-rng-device into the virtio-bus provided by
virtio-serial-pci, even though its only slot is already occupied by a
virtio-serial-device.
And sometimes fails when it shouldn't:
$ qemu-system-x86_64 -nodefaults -device virtio-serial-pci -device virtserialport,bus=virtio-bus/virtio-serial-device
Yes, the virtio-bus is full, but the virtio-serial-bus provided by
virtio-serial-device isn't, and that's the one we're trying to use.
Root cause: we check "bus full" when we resolve the first element of
the path. That's the correct one only when it's also the last one.
Fix by moving the "bus full" check to right before we return a bus.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
parent
a5ec494e27
commit
ed238ba2a0
1 changed files with 17 additions and 14 deletions
|
@ -435,10 +435,6 @@ static BusState *qbus_find(const char *path)
|
||||||
if (!bus) {
|
if (!bus) {
|
||||||
qerror_report(QERR_BUS_NOT_FOUND, elem);
|
qerror_report(QERR_BUS_NOT_FOUND, elem);
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if (qbus_is_full(bus)) {
|
|
||||||
qerror_report(ERROR_CLASS_GENERIC_ERROR, "Bus '%s' is full",
|
|
||||||
elem);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
pos = len;
|
pos = len;
|
||||||
}
|
}
|
||||||
|
@ -449,7 +445,7 @@ static BusState *qbus_find(const char *path)
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
if (path[pos] == '\0') {
|
if (path[pos] == '\0') {
|
||||||
return bus;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find device */
|
/* find device */
|
||||||
|
@ -474,21 +470,21 @@ static BusState *qbus_find(const char *path)
|
||||||
if (path[pos] == '\0') {
|
if (path[pos] == '\0') {
|
||||||
/* last specified element is a device. If it has exactly
|
/* last specified element is a device. If it has exactly
|
||||||
* one child bus accept it nevertheless */
|
* one child bus accept it nevertheless */
|
||||||
switch (dev->num_child_bus) {
|
if (dev->num_child_bus == 1) {
|
||||||
case 0:
|
bus = QLIST_FIRST(&dev->child_bus);
|
||||||
qerror_report(ERROR_CLASS_GENERIC_ERROR,
|
break;
|
||||||
"Device '%s' has no child bus", elem);
|
}
|
||||||
return NULL;
|
if (dev->num_child_bus) {
|
||||||
case 1:
|
|
||||||
return QLIST_FIRST(&dev->child_bus);
|
|
||||||
default:
|
|
||||||
qerror_report(ERROR_CLASS_GENERIC_ERROR,
|
qerror_report(ERROR_CLASS_GENERIC_ERROR,
|
||||||
"Device '%s' has multiple child busses", elem);
|
"Device '%s' has multiple child busses", elem);
|
||||||
if (!monitor_cur_is_qmp()) {
|
if (!monitor_cur_is_qmp()) {
|
||||||
qbus_list_bus(dev);
|
qbus_list_bus(dev);
|
||||||
}
|
}
|
||||||
return NULL;
|
} else {
|
||||||
|
qerror_report(ERROR_CLASS_GENERIC_ERROR,
|
||||||
|
"Device '%s' has no child bus", elem);
|
||||||
}
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find bus */
|
/* find bus */
|
||||||
|
@ -506,6 +502,13 @@ static BusState *qbus_find(const char *path)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (qbus_is_full(bus)) {
|
||||||
|
qerror_report(ERROR_CLASS_GENERIC_ERROR, "Bus '%s' is full",
|
||||||
|
path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return bus;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceState *qdev_device_add(QemuOpts *opts)
|
DeviceState *qdev_device_add(QemuOpts *opts)
|
||||||
|
|
Loading…
Reference in a new issue