Before now, all the qemu hotplug functions assumed that all devices to be hotplugged were legacy PCI endpoint devices (VIR_PCI_CONNECT_TYPE_PCI_DEVICE). This worked out "okay", because all devices *are* legacy PCI endpoint devices on x86/440fx machinetypes, and hotplug didn't work properly on machinetypes using PCIe anyway (hotplugging onto a legacy PCI slot doesn't work, and until commit b87703cf any attempt to manually specify a PCIe address for a hotplugged device would be erroneously rejected). This patch makes all qemu hotplug operations honor the pciConnectFlags set by the single all-knowing function qemuDomainDeviceCalculatePCIConnectFlags(). This is done in 3 steps, but in a single commit since we would have to touch the other points at each step anyway: 1) add a flags argument to the hypervisor-agnostic virDomainPCIAddressEnsureAddr() (previously it hardcoded ..._PCI_DEVICE) 2) add a new qemu-specific function qemuDomainEnsurePCIAddress() which gets the correct pciConnectFlags for the device from qemuDomainDeviceConnectFlags(), then calls virDomainPCIAddressEnsureAddr(). 3) in qemu_hotplug.c replace all calls to virDomainPCIAddressEnsureAddr() with calls to qemuDomainEnsurePCIAddress() So in effect, we're putting a "shim" on top of all calls to virDomainPCIAddressEnsureAddr() that sets the right pciConnectFlags. --- Change: modified comments as suggested. src/conf/domain_addr.c | 10 ++-------- src/conf/domain_addr.h | 3 ++- src/qemu/qemu_domain_address.c | 27 +++++++++++++++++++++++++++ src/qemu/qemu_domain_address.h | 4 ++++ src/qemu/qemu_hotplug.c | 20 ++++++++++++++------ 5 files changed, 49 insertions(+), 15 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 3a9e474..fcd5fc1 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -485,17 +485,11 @@ virDomainPCIAddressReserveSlot(virDomainPCIAddressSetPtr addrs, int virDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs, - virDomainDeviceInfoPtr dev) + virDomainDeviceInfoPtr dev, + virDomainPCIConnectFlags flags) { int ret = -1; char *addrStr = NULL; - /* Flags should be set according to the particular device, - * but only the caller knows the type of device. Currently this - * function is only used for hot-plug, though, and hot-plug is - * only supported for standard PCI devices, so we can safely use - * the setting below */ - virDomainPCIConnectFlags flags = (VIR_PCI_CONNECT_HOTPLUGGABLE | - VIR_PCI_CONNECT_TYPE_PCI_DEVICE); if (!(addrStr = virDomainPCIAddressAsString(&dev->addr.pci))) goto cleanup; diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index 4d6d12a..92ee04c 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -144,7 +144,8 @@ int virDomainPCIAddressReserveSlot(virDomainPCIAddressSetPtr addrs, ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); int virDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs, - virDomainDeviceInfoPtr dev) + virDomainDeviceInfoPtr dev, + virDomainPCIConnectFlags flags) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); int virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs, diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 3a685e7..991cfa7 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -2136,6 +2136,33 @@ qemuDomainAssignAddresses(virDomainDefPtr def, return 0; } +/** + * qemuDomainEnsurePCIAddress: + * + * if @dev should have a PCI address but doesn't, assign an address on + * a compatible PCI bus, and set it in @dev->...info. If there is an + * address already, validate that it is on a compatible bus, based on + * @dev->...info.pciConnectFlags. + * + * @obj: the virDomainObjPtr for the domain. This will include + * qemuCaps and address cache (if there is one) + * + * @dev: the device that we need to ensure has a PCI address + * + * returns 0 on success -1 on failure. + */ +int +qemuDomainEnsurePCIAddress(virDomainObjPtr obj, + virDomainDeviceDefPtr dev) +{ + qemuDomainObjPrivatePtr priv = obj->privateData; + virDomainDeviceInfoPtr info = virDomainDeviceGetInfo(dev); + + qemuDomainFillDevicePCIConnectFlags(obj->def, dev, priv->qemuCaps); + + return virDomainPCIAddressEnsureAddr(priv->pciaddrs, info, + info->pciConnectFlags); +} void qemuDomainReleaseDeviceAddress(virDomainObjPtr vm, diff --git a/src/qemu/qemu_domain_address.h b/src/qemu/qemu_domain_address.h index 11d6e92..800859c 100644 --- a/src/qemu/qemu_domain_address.h +++ b/src/qemu/qemu_domain_address.h @@ -37,6 +37,10 @@ int qemuDomainAssignAddresses(virDomainDefPtr def, bool newDomain) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); +int qemuDomainEnsurePCIAddress(virDomainObjPtr obj, + virDomainDeviceDefPtr dev) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + void qemuDomainReleaseDeviceAddress(virDomainObjPtr vm, virDomainDeviceInfoPtr info, const char *devstr); diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index dc0faa6..56256e7 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -304,6 +304,7 @@ qemuDomainAttachVirtioDiskDevice(virConnectPtr conn, int ret = -1; int rv; qemuDomainObjPrivatePtr priv = vm->privateData; + virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_DISK, { .disk = disk } }; virErrorPtr orig_err; char *devstr = NULL; char *drivestr = NULL; @@ -344,7 +345,7 @@ qemuDomainAttachVirtioDiskDevice(virConnectPtr conn, goto error; } else if (!disk->info.type || disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { - if (virDomainPCIAddressEnsureAddr(priv->pciaddrs, &disk->info) < 0) + if (qemuDomainEnsurePCIAddress(vm, &dev) < 0) goto error; } releaseaddr = true; @@ -462,6 +463,8 @@ int qemuDomainAttachControllerDevice(virQEMUDriverPtr driver, const char* type = virDomainControllerTypeToString(controller->type); char *devstr = NULL; qemuDomainObjPrivatePtr priv = vm->privateData; + virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_CONTROLLER, + { .controller = controller } }; virDomainCCWAddressSetPtr ccwaddrs = NULL; bool releaseaddr = false; @@ -501,7 +504,7 @@ int qemuDomainAttachControllerDevice(virQEMUDriverPtr driver, if (controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE || controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { - if (virDomainPCIAddressEnsureAddr(priv->pciaddrs, &controller->info) < 0) + if (qemuDomainEnsurePCIAddress(vm, &dev) < 0) goto cleanup; } else if (controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) { if (!(ccwaddrs = qemuDomainCCWAddrSetCreateFromDomain(vm->def))) @@ -914,6 +917,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, virDomainNetDefPtr net) { qemuDomainObjPrivatePtr priv = vm->privateData; + virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_NET, { .net = net } }; char **tapfdName = NULL; int *tapfd = NULL; size_t tapfdSize = 0; @@ -1110,7 +1114,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("virtio-s390 net device cannot be hotplugged.")); goto cleanup; - } else if (virDomainPCIAddressEnsureAddr(priv->pciaddrs, &net->info) < 0) { + } else if (qemuDomainEnsurePCIAddress(vm, &dev) < 0) { goto cleanup; } @@ -1339,6 +1343,8 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver, virDomainHostdevDefPtr hostdev) { qemuDomainObjPrivatePtr priv = vm->privateData; + virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_HOSTDEV, + { .hostdev = hostdev } }; int ret; char *devstr = NULL; int configfd = -1; @@ -1409,7 +1415,7 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver, if (qemuAssignDeviceHostdevAlias(vm->def, &hostdev->info->alias, -1) < 0) goto error; - if (virDomainPCIAddressEnsureAddr(priv->pciaddrs, hostdev->info) < 0) + if (qemuDomainEnsurePCIAddress(vm, &dev) < 0) goto error; releaseaddr = true; if (backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO && @@ -1641,6 +1647,7 @@ qemuDomainAttachChrDeviceAssignAddr(virDomainObjPtr vm, { virDomainDefPtr def = vm->def; qemuDomainObjPrivatePtr priv = vm->privateData; + virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_CHR, { .chr = chr } }; int ret = -1; virDomainVirtioSerialAddrSetPtr vioaddrs = NULL; @@ -1656,7 +1663,7 @@ qemuDomainAttachChrDeviceAssignAddr(virDomainObjPtr vm, } else if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL && chr->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_PCI) { - if (virDomainPCIAddressEnsureAddr(priv->pciaddrs, &chr->info) < 0) + if (qemuDomainEnsurePCIAddress(vm, &dev) < 0) goto cleanup; ret = 1; @@ -1802,6 +1809,7 @@ qemuDomainAttachRNGDevice(virQEMUDriverPtr driver, virDomainRNGDefPtr rng) { qemuDomainObjPrivatePtr priv = vm->privateData; + virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_RNG, { .rng = rng } }; virErrorPtr orig_err; char *devstr = NULL; char *charAlias = NULL; @@ -1838,7 +1846,7 @@ qemuDomainAttachRNGDevice(virQEMUDriverPtr driver, if (rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE || rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { - if (virDomainPCIAddressEnsureAddr(priv->pciaddrs, &rng->info) < 0) + if (qemuDomainEnsurePCIAddress(vm, &dev) < 0) return -1; } else if (rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) { if (!(ccwaddrs = qemuDomainCCWAddrSetCreateFromDomain(vm->def))) -- 2.7.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list