mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-24 06:35:24 +00:00
Assign PCI addresses before hotplugging devices
PCI disk, disk controllers, net devices and host devices need to have PCI addresses assigned before they are hot-plugged * src/qemu/qemu_conf.c: Add APIs for ensuring a device has an address and releasing unused addresses * src/qemu/qemu_driver.c: Ensure all devices have addresses when hotplugging.
This commit is contained in:
parent
9258ec0a2e
commit
d8acc44672
@ -1652,17 +1652,12 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int qemuDomainPCIAddressReserve(qemuDomainPCIAddressSetPtr addrs,
|
||||
int slot)
|
||||
int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
|
||||
virDomainDeviceInfoPtr dev)
|
||||
{
|
||||
virDomainDeviceInfo dev;
|
||||
char *addr;
|
||||
|
||||
dev.addr.pci.domain = 0;
|
||||
dev.addr.pci.bus = 0;
|
||||
dev.addr.pci.slot = slot;
|
||||
|
||||
addr = qemuPCIAddressAsString(&dev);
|
||||
addr = qemuPCIAddressAsString(dev);
|
||||
if (!addr)
|
||||
return -1;
|
||||
|
||||
@ -1681,6 +1676,29 @@ int qemuDomainPCIAddressReserve(qemuDomainPCIAddressSetPtr addrs,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qemuDomainPCIAddressReserveSlot(qemuDomainPCIAddressSetPtr addrs,
|
||||
int slot)
|
||||
{
|
||||
virDomainDeviceInfo dev;
|
||||
|
||||
dev.addr.pci.domain = 0;
|
||||
dev.addr.pci.bus = 0;
|
||||
dev.addr.pci.slot = slot;
|
||||
|
||||
return qemuDomainPCIAddressReserveAddr(addrs, &dev);
|
||||
}
|
||||
|
||||
|
||||
int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr addrs,
|
||||
virDomainDeviceInfoPtr dev)
|
||||
{
|
||||
int ret = 0;
|
||||
if (dev->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
|
||||
ret = qemuDomainPCIAddressReserveAddr(addrs, dev);
|
||||
else
|
||||
ret = qemuDomainPCIAddressSetNextAddr(addrs, dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void qemuDomainPCIAddressSetFreeEntry(void *payload, const char *name ATTRIBUTE_UNUSED)
|
||||
{
|
||||
@ -1688,6 +1706,24 @@ static void qemuDomainPCIAddressSetFreeEntry(void *payload, const char *name ATT
|
||||
}
|
||||
|
||||
|
||||
int qemuDomainPCIAddressReleaseAddr(qemuDomainPCIAddressSetPtr addrs,
|
||||
virDomainDeviceInfoPtr dev)
|
||||
{
|
||||
char *addr;
|
||||
int ret;
|
||||
|
||||
addr = qemuPCIAddressAsString(dev);
|
||||
if (!addr)
|
||||
return -1;
|
||||
|
||||
ret = virHashRemoveEntry(addrs->used, addr, qemuDomainPCIAddressSetFreeEntry);
|
||||
|
||||
VIR_FREE(addr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void qemuDomainPCIAddressSetFree(qemuDomainPCIAddressSetPtr addrs)
|
||||
{
|
||||
if (!addrs)
|
||||
@ -1746,16 +1782,16 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs)
|
||||
int i;
|
||||
|
||||
/* Host bridge */
|
||||
if (qemuDomainPCIAddressReserve(addrs, 0) < 0)
|
||||
if (qemuDomainPCIAddressReserveSlot(addrs, 0) < 0)
|
||||
goto error;
|
||||
/* PIIX3 (ISA bridge, IDE controller, something else unknown, USB controller) */
|
||||
if (qemuDomainPCIAddressReserve(addrs, 1) < 0)
|
||||
if (qemuDomainPCIAddressReserveSlot(addrs, 1) < 0)
|
||||
goto error;
|
||||
/* VGA */
|
||||
if (qemuDomainPCIAddressReserve(addrs, 2) < 0)
|
||||
if (qemuDomainPCIAddressReserveSlot(addrs, 2) < 0)
|
||||
goto error;
|
||||
/* VirtIO Balloon */
|
||||
if (qemuDomainPCIAddressReserve(addrs, 3) < 0)
|
||||
if (qemuDomainPCIAddressReserveSlot(addrs, 3) < 0)
|
||||
goto error;
|
||||
|
||||
for (i = 0; i < def->ndisks ; i++) {
|
||||
|
@ -275,10 +275,17 @@ virDomainDefPtr qemuParseCommandLineString(virConnectPtr conn,
|
||||
const char *args);
|
||||
|
||||
qemuDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def);
|
||||
int qemuDomainPCIAddressReserve(qemuDomainPCIAddressSetPtr addrs,
|
||||
int slot);
|
||||
int qemuDomainPCIAddressReserveSlot(qemuDomainPCIAddressSetPtr addrs,
|
||||
int slot);
|
||||
int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
|
||||
virDomainDeviceInfoPtr dev);
|
||||
int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,
|
||||
virDomainDeviceInfoPtr dev);
|
||||
int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr addrs,
|
||||
virDomainDeviceInfoPtr dev);
|
||||
int qemuDomainPCIAddressReleaseAddr(qemuDomainPCIAddressSetPtr addrs,
|
||||
virDomainDeviceInfoPtr dev);
|
||||
|
||||
void qemuDomainPCIAddressSetFree(qemuDomainPCIAddressSetPtr addrs);
|
||||
int qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs);
|
||||
|
||||
|
@ -5238,6 +5238,9 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
|
||||
return -1;
|
||||
|
||||
if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
|
||||
if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &disk->info) < 0)
|
||||
goto error;
|
||||
|
||||
if (!(drivestr = qemuBuildDriveStr(disk, 0, qemuCmdFlags)))
|
||||
goto error;
|
||||
|
||||
@ -5283,6 +5286,11 @@ error:
|
||||
VIR_FREE(devstr);
|
||||
VIR_FREE(drivestr);
|
||||
|
||||
if ((qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
|
||||
(disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
|
||||
qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &disk->info) < 0)
|
||||
VIR_WARN("Unable to release PCI address on %s", disk->src);
|
||||
|
||||
if (driver->securityDriver &&
|
||||
driver->securityDriver->domainRestoreSecurityImageLabel &&
|
||||
driver->securityDriver->domainRestoreSecurityImageLabel(conn, vm, disk) < 0)
|
||||
@ -5314,6 +5322,10 @@ static int qemudDomainAttachPciControllerDevice(virConnectPtr conn,
|
||||
}
|
||||
}
|
||||
|
||||
if ((qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
|
||||
qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &controller->info) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (!(devstr = qemuBuildControllerDevStr(controller))) {
|
||||
virReportOOMError(NULL);
|
||||
goto cleanup;
|
||||
@ -5340,6 +5352,12 @@ static int qemudDomainAttachPciControllerDevice(virConnectPtr conn,
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if ((ret != 0) &&
|
||||
(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
|
||||
(controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
|
||||
qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &controller->info) < 0)
|
||||
VIR_WARN0("Unable to release PCI address on controller");
|
||||
|
||||
VIR_FREE(devstr);
|
||||
return ret;
|
||||
}
|
||||
@ -5610,6 +5628,10 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn,
|
||||
qemuAssignNetNames(vm->def, net) < 0)
|
||||
goto no_memory;
|
||||
|
||||
if ((qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
|
||||
qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &net->info) < 0)
|
||||
goto cleanup;
|
||||
|
||||
/* Choose a vlan value greater than all other values since
|
||||
* older versions did not store the value in the state file.
|
||||
*/
|
||||
@ -5663,6 +5685,12 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn,
|
||||
vm->def->nets[vm->def->nnets++] = net;
|
||||
|
||||
cleanup:
|
||||
if ((ret != 0) &&
|
||||
(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
|
||||
(net->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
|
||||
qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &net->info) < 0)
|
||||
VIR_WARN0("Unable to release PCI address on NIC");
|
||||
|
||||
VIR_FREE(nicstr);
|
||||
VIR_FREE(netstr);
|
||||
VIR_FREE(tapfd_name);
|
||||
@ -5736,9 +5764,13 @@ static int qemudDomainAttachHostPciDevice(virConnectPtr conn,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
|
||||
!(devstr = qemuBuildPCIHostdevDevStr(hostdev)))
|
||||
goto error;
|
||||
if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
|
||||
if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &hostdev->info) < 0)
|
||||
goto error;
|
||||
|
||||
if (!(devstr = qemuBuildPCIHostdevDevStr(hostdev)))
|
||||
goto error;
|
||||
}
|
||||
|
||||
qemuDomainObjEnterMonitorWithDriver(driver, vm);
|
||||
if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)
|
||||
@ -5760,6 +5792,11 @@ static int qemudDomainAttachHostPciDevice(virConnectPtr conn,
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if ((qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
|
||||
(hostdev->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) &&
|
||||
qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &hostdev->info) < 0)
|
||||
VIR_WARN0("Unable to release PCI address on host device");
|
||||
|
||||
VIR_FREE(devstr);
|
||||
pciDeviceListDel(conn, driver->activePciHostdevs, pci);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user