提交 abb7a4bd 编写于 作者: L Laine Stump

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.
上级 7f784f57
...@@ -487,17 +487,11 @@ virDomainPCIAddressReserveSlot(virDomainPCIAddressSetPtr addrs, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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)))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册