mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-28 03:21:19 +00:00
qemu: set/use proper pciConnectFlags during hotplug
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.
This commit is contained in:
parent
7f784f576b
commit
abb7a4bd6b
@ -487,17 +487,11 @@ virDomainPCIAddressReserveSlot(virDomainPCIAddressSetPtr addrs,
|
|||||||
|
|
||||||
int
|
int
|
||||||
virDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs,
|
virDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs,
|
||||||
virDomainDeviceInfoPtr dev)
|
virDomainDeviceInfoPtr dev,
|
||||||
|
virDomainPCIConnectFlags flags)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
char *addrStr = NULL;
|
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)))
|
if (!(addrStr = virDomainPCIAddressAsString(&dev->addr.pci)))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
@ -144,7 +144,8 @@ int virDomainPCIAddressReserveSlot(virDomainPCIAddressSetPtr addrs,
|
|||||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
||||||
|
|
||||||
int virDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs,
|
int virDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs,
|
||||||
virDomainDeviceInfoPtr dev)
|
virDomainDeviceInfoPtr dev,
|
||||||
|
virDomainPCIConnectFlags flags)
|
||||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
||||||
|
|
||||||
int virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs,
|
int virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs,
|
||||||
|
@ -2230,6 +2230,36 @@ qemuDomainAssignAddresses(virDomainDefPtr def,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemuDomainEnsurePCIAddress:
|
||||||
|
*
|
||||||
|
* @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
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* returns 0 on success -1 on failure.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
qemuDomainEnsurePCIAddress(virDomainObjPtr obj,
|
||||||
|
virDomainDeviceDefPtr dev)
|
||||||
|
{
|
||||||
|
qemuDomainObjPrivatePtr priv = obj->privateData;
|
||||||
|
virDomainDeviceInfoPtr info = virDomainDeviceGetInfo(dev);
|
||||||
|
|
||||||
|
if (!info)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
qemuDomainFillDevicePCIConnectFlags(obj->def, dev, priv->qemuCaps);
|
||||||
|
|
||||||
|
return virDomainPCIAddressEnsureAddr(priv->pciaddrs, info,
|
||||||
|
info->pciConnectFlags);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
qemuDomainReleaseDeviceAddress(virDomainObjPtr vm,
|
qemuDomainReleaseDeviceAddress(virDomainObjPtr vm,
|
||||||
|
@ -37,6 +37,10 @@ int qemuDomainAssignAddresses(virDomainDefPtr def,
|
|||||||
bool newDomain)
|
bool newDomain)
|
||||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
||||||
|
|
||||||
|
int qemuDomainEnsurePCIAddress(virDomainObjPtr obj,
|
||||||
|
virDomainDeviceDefPtr dev)
|
||||||
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
||||||
|
|
||||||
void qemuDomainReleaseDeviceAddress(virDomainObjPtr vm,
|
void qemuDomainReleaseDeviceAddress(virDomainObjPtr vm,
|
||||||
virDomainDeviceInfoPtr info,
|
virDomainDeviceInfoPtr info,
|
||||||
const char *devstr);
|
const char *devstr);
|
||||||
|
@ -304,6 +304,7 @@ qemuDomainAttachVirtioDiskDevice(virConnectPtr conn,
|
|||||||
int ret = -1;
|
int ret = -1;
|
||||||
int rv;
|
int rv;
|
||||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
|
virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_DISK, { .disk = disk } };
|
||||||
virErrorPtr orig_err;
|
virErrorPtr orig_err;
|
||||||
char *devstr = NULL;
|
char *devstr = NULL;
|
||||||
char *drivestr = NULL;
|
char *drivestr = NULL;
|
||||||
@ -344,7 +345,7 @@ qemuDomainAttachVirtioDiskDevice(virConnectPtr conn,
|
|||||||
goto error;
|
goto error;
|
||||||
} else if (!disk->info.type ||
|
} else if (!disk->info.type ||
|
||||||
disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
|
disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
|
||||||
if (virDomainPCIAddressEnsureAddr(priv->pciaddrs, &disk->info) < 0)
|
if (qemuDomainEnsurePCIAddress(vm, &dev) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
releaseaddr = true;
|
releaseaddr = true;
|
||||||
@ -462,6 +463,8 @@ int qemuDomainAttachControllerDevice(virQEMUDriverPtr driver,
|
|||||||
const char* type = virDomainControllerTypeToString(controller->type);
|
const char* type = virDomainControllerTypeToString(controller->type);
|
||||||
char *devstr = NULL;
|
char *devstr = NULL;
|
||||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
|
virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_CONTROLLER,
|
||||||
|
{ .controller = controller } };
|
||||||
virDomainCCWAddressSetPtr ccwaddrs = NULL;
|
virDomainCCWAddressSetPtr ccwaddrs = NULL;
|
||||||
bool releaseaddr = false;
|
bool releaseaddr = false;
|
||||||
|
|
||||||
@ -501,7 +504,7 @@ int qemuDomainAttachControllerDevice(virQEMUDriverPtr driver,
|
|||||||
|
|
||||||
if (controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
|
if (controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
|
||||||
controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
|
controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
|
||||||
if (virDomainPCIAddressEnsureAddr(priv->pciaddrs, &controller->info) < 0)
|
if (qemuDomainEnsurePCIAddress(vm, &dev) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else if (controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
|
} else if (controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
|
||||||
if (!(ccwaddrs = qemuDomainCCWAddrSetCreateFromDomain(vm->def)))
|
if (!(ccwaddrs = qemuDomainCCWAddrSetCreateFromDomain(vm->def)))
|
||||||
@ -935,6 +938,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
|
|||||||
virDomainNetDefPtr net)
|
virDomainNetDefPtr net)
|
||||||
{
|
{
|
||||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
|
virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_NET, { .net = net } };
|
||||||
virErrorPtr originalError = NULL;
|
virErrorPtr originalError = NULL;
|
||||||
char **tapfdName = NULL;
|
char **tapfdName = NULL;
|
||||||
int *tapfd = NULL;
|
int *tapfd = NULL;
|
||||||
@ -1133,7 +1137,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
|
|||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
_("virtio-s390 net device cannot be hotplugged."));
|
_("virtio-s390 net device cannot be hotplugged."));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else if (virDomainPCIAddressEnsureAddr(priv->pciaddrs, &net->info) < 0) {
|
} else if (qemuDomainEnsurePCIAddress(vm, &dev) < 0) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1365,6 +1369,8 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver,
|
|||||||
virDomainHostdevDefPtr hostdev)
|
virDomainHostdevDefPtr hostdev)
|
||||||
{
|
{
|
||||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
|
virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_HOSTDEV,
|
||||||
|
{ .hostdev = hostdev } };
|
||||||
int ret;
|
int ret;
|
||||||
char *devstr = NULL;
|
char *devstr = NULL;
|
||||||
int configfd = -1;
|
int configfd = -1;
|
||||||
@ -1435,7 +1441,7 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver,
|
|||||||
|
|
||||||
if (qemuAssignDeviceHostdevAlias(vm->def, &hostdev->info->alias, -1) < 0)
|
if (qemuAssignDeviceHostdevAlias(vm->def, &hostdev->info->alias, -1) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
if (virDomainPCIAddressEnsureAddr(priv->pciaddrs, hostdev->info) < 0)
|
if (qemuDomainEnsurePCIAddress(vm, &dev) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
releaseaddr = true;
|
releaseaddr = true;
|
||||||
if (backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO &&
|
if (backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO &&
|
||||||
@ -1771,6 +1777,7 @@ qemuDomainAttachChrDeviceAssignAddr(virDomainObjPtr vm,
|
|||||||
{
|
{
|
||||||
virDomainDefPtr def = vm->def;
|
virDomainDefPtr def = vm->def;
|
||||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
|
virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_CHR, { .chr = chr } };
|
||||||
|
|
||||||
if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
|
if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
|
||||||
chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO) {
|
chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO) {
|
||||||
@ -1780,7 +1787,7 @@ qemuDomainAttachChrDeviceAssignAddr(virDomainObjPtr vm,
|
|||||||
|
|
||||||
} else if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL &&
|
} else if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL &&
|
||||||
chr->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_PCI) {
|
chr->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_PCI) {
|
||||||
if (virDomainPCIAddressEnsureAddr(priv->pciaddrs, &chr->info) < 0)
|
if (qemuDomainEnsurePCIAddress(vm, &dev) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@ -1936,6 +1943,7 @@ qemuDomainAttachRNGDevice(virConnectPtr conn,
|
|||||||
{
|
{
|
||||||
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
||||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
|
virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_RNG, { .rng = rng } };
|
||||||
virErrorPtr orig_err;
|
virErrorPtr orig_err;
|
||||||
char *devstr = NULL;
|
char *devstr = NULL;
|
||||||
char *charAlias = NULL;
|
char *charAlias = NULL;
|
||||||
@ -1978,7 +1986,7 @@ qemuDomainAttachRNGDevice(virConnectPtr conn,
|
|||||||
|
|
||||||
if (rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
|
if (rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
|
||||||
rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
|
rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
|
||||||
if (virDomainPCIAddressEnsureAddr(priv->pciaddrs, &rng->info) < 0)
|
if (qemuDomainEnsurePCIAddress(vm, &dev) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else if (rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
|
} else if (rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
|
||||||
if (!(ccwaddrs = qemuDomainCCWAddrSetCreateFromDomain(vm->def)))
|
if (!(ccwaddrs = qemuDomainCCWAddrSetCreateFromDomain(vm->def)))
|
||||||
@ -2496,6 +2504,7 @@ qemuDomainAttachShmemDevice(virQEMUDriverPtr driver,
|
|||||||
virErrorPtr orig_err = NULL;
|
virErrorPtr orig_err = NULL;
|
||||||
virJSONValuePtr props = NULL;
|
virJSONValuePtr props = NULL;
|
||||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
|
virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_SHMEM, { .shmem = shmem } };
|
||||||
|
|
||||||
switch ((virDomainShmemModel)shmem->model) {
|
switch ((virDomainShmemModel)shmem->model) {
|
||||||
case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_PLAIN:
|
case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_PLAIN:
|
||||||
@ -2522,7 +2531,7 @@ qemuDomainAttachShmemDevice(virQEMUDriverPtr driver,
|
|||||||
|
|
||||||
if ((shmem->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
|
if ((shmem->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
|
||||||
shmem->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
|
shmem->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
|
||||||
(virDomainPCIAddressEnsureAddr(priv->pciaddrs, &shmem->info) < 0))
|
(qemuDomainEnsurePCIAddress(vm, &dev) < 0))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!(shmstr = qemuBuildShmemDevStr(vm->def, shmem, priv->qemuCaps)))
|
if (!(shmstr = qemuBuildShmemDevStr(vm->def, shmem, priv->qemuCaps)))
|
||||||
|
Loading…
Reference in New Issue
Block a user