mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-12 07:42:56 +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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int qemuDomainPCIAddressReserve(qemuDomainPCIAddressSetPtr addrs,
|
int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
|
||||||
int slot)
|
virDomainDeviceInfoPtr dev)
|
||||||
{
|
{
|
||||||
virDomainDeviceInfo dev;
|
|
||||||
char *addr;
|
char *addr;
|
||||||
|
|
||||||
dev.addr.pci.domain = 0;
|
addr = qemuPCIAddressAsString(dev);
|
||||||
dev.addr.pci.bus = 0;
|
|
||||||
dev.addr.pci.slot = slot;
|
|
||||||
|
|
||||||
addr = qemuPCIAddressAsString(&dev);
|
|
||||||
if (!addr)
|
if (!addr)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -1681,6 +1676,29 @@ int qemuDomainPCIAddressReserve(qemuDomainPCIAddressSetPtr addrs,
|
|||||||
return 0;
|
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)
|
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)
|
void qemuDomainPCIAddressSetFree(qemuDomainPCIAddressSetPtr addrs)
|
||||||
{
|
{
|
||||||
if (!addrs)
|
if (!addrs)
|
||||||
@ -1746,16 +1782,16 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Host bridge */
|
/* Host bridge */
|
||||||
if (qemuDomainPCIAddressReserve(addrs, 0) < 0)
|
if (qemuDomainPCIAddressReserveSlot(addrs, 0) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
/* PIIX3 (ISA bridge, IDE controller, something else unknown, USB controller) */
|
/* PIIX3 (ISA bridge, IDE controller, something else unknown, USB controller) */
|
||||||
if (qemuDomainPCIAddressReserve(addrs, 1) < 0)
|
if (qemuDomainPCIAddressReserveSlot(addrs, 1) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
/* VGA */
|
/* VGA */
|
||||||
if (qemuDomainPCIAddressReserve(addrs, 2) < 0)
|
if (qemuDomainPCIAddressReserveSlot(addrs, 2) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
/* VirtIO Balloon */
|
/* VirtIO Balloon */
|
||||||
if (qemuDomainPCIAddressReserve(addrs, 3) < 0)
|
if (qemuDomainPCIAddressReserveSlot(addrs, 3) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
for (i = 0; i < def->ndisks ; i++) {
|
for (i = 0; i < def->ndisks ; i++) {
|
||||||
|
@ -275,10 +275,17 @@ virDomainDefPtr qemuParseCommandLineString(virConnectPtr conn,
|
|||||||
const char *args);
|
const char *args);
|
||||||
|
|
||||||
qemuDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def);
|
qemuDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def);
|
||||||
int qemuDomainPCIAddressReserve(qemuDomainPCIAddressSetPtr addrs,
|
int qemuDomainPCIAddressReserveSlot(qemuDomainPCIAddressSetPtr addrs,
|
||||||
int slot);
|
int slot);
|
||||||
|
int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
|
||||||
|
virDomainDeviceInfoPtr dev);
|
||||||
int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,
|
int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,
|
||||||
virDomainDeviceInfoPtr dev);
|
virDomainDeviceInfoPtr dev);
|
||||||
|
int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr addrs,
|
||||||
|
virDomainDeviceInfoPtr dev);
|
||||||
|
int qemuDomainPCIAddressReleaseAddr(qemuDomainPCIAddressSetPtr addrs,
|
||||||
|
virDomainDeviceInfoPtr dev);
|
||||||
|
|
||||||
void qemuDomainPCIAddressSetFree(qemuDomainPCIAddressSetPtr addrs);
|
void qemuDomainPCIAddressSetFree(qemuDomainPCIAddressSetPtr addrs);
|
||||||
int qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs);
|
int qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs);
|
||||||
|
|
||||||
|
@ -5238,6 +5238,9 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
|
if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
|
||||||
|
if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &disk->info) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
if (!(drivestr = qemuBuildDriveStr(disk, 0, qemuCmdFlags)))
|
if (!(drivestr = qemuBuildDriveStr(disk, 0, qemuCmdFlags)))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -5283,6 +5286,11 @@ error:
|
|||||||
VIR_FREE(devstr);
|
VIR_FREE(devstr);
|
||||||
VIR_FREE(drivestr);
|
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 &&
|
if (driver->securityDriver &&
|
||||||
driver->securityDriver->domainRestoreSecurityImageLabel &&
|
driver->securityDriver->domainRestoreSecurityImageLabel &&
|
||||||
driver->securityDriver->domainRestoreSecurityImageLabel(conn, vm, disk) < 0)
|
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))) {
|
if (!(devstr = qemuBuildControllerDevStr(controller))) {
|
||||||
virReportOOMError(NULL);
|
virReportOOMError(NULL);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -5340,6 +5352,12 @@ static int qemudDomainAttachPciControllerDevice(virConnectPtr conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
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);
|
VIR_FREE(devstr);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -5610,6 +5628,10 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn,
|
|||||||
qemuAssignNetNames(vm->def, net) < 0)
|
qemuAssignNetNames(vm->def, net) < 0)
|
||||||
goto no_memory;
|
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
|
/* Choose a vlan value greater than all other values since
|
||||||
* older versions did not store the value in the state file.
|
* 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;
|
vm->def->nets[vm->def->nnets++] = net;
|
||||||
|
|
||||||
cleanup:
|
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(nicstr);
|
||||||
VIR_FREE(netstr);
|
VIR_FREE(netstr);
|
||||||
VIR_FREE(tapfd_name);
|
VIR_FREE(tapfd_name);
|
||||||
@ -5736,9 +5764,13 @@ static int qemudDomainAttachHostPciDevice(virConnectPtr conn,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) &&
|
if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
|
||||||
!(devstr = qemuBuildPCIHostdevDevStr(hostdev)))
|
if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &hostdev->info) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
if (!(devstr = qemuBuildPCIHostdevDevStr(hostdev)))
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
qemuDomainObjEnterMonitorWithDriver(driver, vm);
|
qemuDomainObjEnterMonitorWithDriver(driver, vm);
|
||||||
if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)
|
if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)
|
||||||
@ -5760,6 +5792,11 @@ static int qemudDomainAttachHostPciDevice(virConnectPtr conn,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
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);
|
VIR_FREE(devstr);
|
||||||
pciDeviceListDel(conn, driver->activePciHostdevs, pci);
|
pciDeviceListDel(conn, driver->activePciHostdevs, pci);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user