提交 f183b87f 编写于 作者: Y Yi Min Zhao 提交者: Andrea Bolognani

conf: Allocate/release 'uid' and 'fid' in PCI address

This patch adds new functions for reservation, assignment and release
to handle the uid/fid. If the uid/fid is defined in the domain XML,
they will be reserved directly in the collecting phase. If any of them
is not defined, we will find out an available value for them from the
zPCI address hashtable, and reserve them. For the hotplug case there
might not be a zPCI definition. So allocate and reserve uid/fid the
case. Assign if needed and reserve uid/fid for the defined case.
Signed-off-by: NYi Min Zhao <zyimin@linux.ibm.com>
Reviewed-by: NBjoern Walk <bwalk@linux.ibm.com>
Reviewed-by: NBoris Fiuczynski <fiuczy@linux.ibm.com>
Reviewed-by: NAndrea Bolognani <abologna@redhat.com>
上级 e6565d54
......@@ -28,6 +28,7 @@
#include "viruuid.h"
#include "virbuffer.h"
#include "device_conf.h"
#include "domain_addr.h"
#include "virstring.h"
#define VIR_FROM_THIS VIR_FROM_DEVICE
......@@ -215,6 +216,21 @@ virDeviceInfoPCIAddressIsPresent(const virDomainDeviceInfo *info)
}
bool
virDeviceInfoPCIAddressExtensionIsWanted(const virDomainDeviceInfo *info)
{
return (info->addr.pci.extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) &&
virZPCIDeviceAddressIsEmpty(&info->addr.pci.zpci);
}
bool
virDeviceInfoPCIAddressExtensionIsPresent(const virDomainDeviceInfo *info)
{
return (info->addr.pci.extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) &&
!virZPCIDeviceAddressIsEmpty(&info->addr.pci.zpci);
}
int
virPCIDeviceAddressParseXML(xmlNodePtr node,
virPCIDeviceAddressPtr addr)
......
......@@ -198,6 +198,9 @@ bool virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
bool virDeviceInfoPCIAddressIsWanted(const virDomainDeviceInfo *info);
bool virDeviceInfoPCIAddressIsPresent(const virDomainDeviceInfo *info);
bool virDeviceInfoPCIAddressExtensionIsWanted(const virDomainDeviceInfo *info);
bool virDeviceInfoPCIAddressExtensionIsPresent(const virDomainDeviceInfo *info);
int virPCIDeviceAddressParseXML(xmlNodePtr node,
virPCIDeviceAddressPtr addr);
......
......@@ -33,6 +33,238 @@
VIR_LOG_INIT("conf.domain_addr");
static int
virDomainZPCIAddressReserveId(virHashTablePtr set,
unsigned int id,
const char *name)
{
if (virHashLookup(set, &id)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("zPCI %s %o is already reserved"),
name, id);
return -1;
}
if (virHashAddEntry(set, &id, (void*)1) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to reserve %s %o"),
name, id);
return -1;
}
return 0;
}
static int
virDomainZPCIAddressReserveUid(virHashTablePtr set,
virZPCIDeviceAddressPtr addr)
{
return virDomainZPCIAddressReserveId(set, addr->uid, "uid");
}
static int
virDomainZPCIAddressReserveFid(virHashTablePtr set,
virZPCIDeviceAddressPtr addr)
{
return virDomainZPCIAddressReserveId(set, addr->fid, "fid");
}
static int
virDomainZPCIAddressAssignId(virHashTablePtr set,
unsigned int *id,
unsigned int min,
unsigned int max,
const char *name)
{
while (virHashLookup(set, &min)) {
if (min == max) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("There is no more free %s."),
name);
return -1;
}
++min;
}
*id = min;
return 0;
}
static int
virDomainZPCIAddressAssignUid(virHashTablePtr set,
virZPCIDeviceAddressPtr addr)
{
return virDomainZPCIAddressAssignId(set, &addr->uid, 1,
VIR_DOMAIN_DEVICE_ZPCI_MAX_UID, "uid");
}
static int
virDomainZPCIAddressAssignFid(virHashTablePtr set,
virZPCIDeviceAddressPtr addr)
{
return virDomainZPCIAddressAssignId(set, &addr->fid, 0,
VIR_DOMAIN_DEVICE_ZPCI_MAX_FID, "fid");
}
static void
virDomainZPCIAddressReleaseId(virHashTablePtr set,
unsigned int *id,
const char *name)
{
if (virHashRemoveEntry(set, id) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Release %s %o failed"),
name, *id);
}
*id = 0;
}
static void
virDomainZPCIAddressReleaseUid(virHashTablePtr set,
virZPCIDeviceAddressPtr addr)
{
virDomainZPCIAddressReleaseId(set, &addr->uid, "uid");
}
static void
virDomainZPCIAddressReleaseFid(virHashTablePtr set,
virZPCIDeviceAddressPtr addr)
{
virDomainZPCIAddressReleaseId(set, &addr->fid, "fid");
}
static void
virDomainZPCIAddressReleaseIds(virDomainZPCIAddressIdsPtr zpciIds,
virZPCIDeviceAddressPtr addr)
{
if (!zpciIds || virZPCIDeviceAddressIsEmpty(addr))
return;
virDomainZPCIAddressReleaseUid(zpciIds->uids, addr);
virDomainZPCIAddressReleaseFid(zpciIds->fids, addr);
}
static int
virDomainZPCIAddressReserveNextUid(virHashTablePtr uids,
virZPCIDeviceAddressPtr zpci)
{
if (virDomainZPCIAddressAssignUid(uids, zpci) < 0)
return -1;
if (virDomainZPCIAddressReserveUid(uids, zpci) < 0)
return -1;
return 0;
}
static int
virDomainZPCIAddressReserveNextFid(virHashTablePtr fids,
virZPCIDeviceAddressPtr zpci)
{
if (virDomainZPCIAddressAssignFid(fids, zpci) < 0)
return -1;
if (virDomainZPCIAddressReserveFid(fids, zpci) < 0)
return -1;
return 0;
}
static int
virDomainZPCIAddressReserveAddr(virDomainZPCIAddressIdsPtr zpciIds,
virZPCIDeviceAddressPtr addr)
{
if (virDomainZPCIAddressReserveUid(zpciIds->uids, addr) < 0)
return -1;
if (virDomainZPCIAddressReserveFid(zpciIds->fids, addr) < 0) {
virDomainZPCIAddressReleaseUid(zpciIds->uids, addr);
return -1;
}
return 0;
}
static int
virDomainZPCIAddressReserveNextAddr(virDomainZPCIAddressIdsPtr zpciIds,
virZPCIDeviceAddressPtr addr)
{
if (virDomainZPCIAddressReserveNextUid(zpciIds->uids, addr) < 0)
return -1;
if (virDomainZPCIAddressReserveNextFid(zpciIds->fids, addr) < 0) {
virDomainZPCIAddressReleaseUid(zpciIds->uids, addr);
return -1;
}
return 0;
}
int
virDomainPCIAddressExtensionReserveAddr(virDomainPCIAddressSetPtr addrs,
virPCIDeviceAddressPtr addr)
{
if (addr->extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) {
/* Reserve uid/fid to ZPCI device which has defined uid/fid
* in the domain.
*/
return virDomainZPCIAddressReserveAddr(addrs->zpciIds, &addr->zpci);
}
return 0;
}
int
virDomainPCIAddressExtensionReserveNextAddr(virDomainPCIAddressSetPtr addrs,
virPCIDeviceAddressPtr addr)
{
if (addr->extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) {
virZPCIDeviceAddress zpci = { 0 };
if (virDomainZPCIAddressReserveNextAddr(addrs->zpciIds, &zpci) < 0)
return -1;
if (!addrs->dryRun)
addr->zpci = zpci;
}
return 0;
}
static int
virDomainPCIAddressExtensionEnsureAddr(virDomainPCIAddressSetPtr addrs,
virPCIDeviceAddressPtr addr)
{
if (addr->extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) {
virZPCIDeviceAddressPtr zpci = &addr->zpci;
if (virZPCIDeviceAddressIsEmpty(zpci))
return virDomainZPCIAddressReserveNextAddr(addrs->zpciIds, zpci);
else
return virDomainZPCIAddressReserveAddr(addrs->zpciIds, zpci);
}
return 0;
}
virDomainPCIConnectFlags
virDomainPCIControllerModelToConnectType(virDomainControllerModelPCI model)
{
......@@ -715,12 +947,24 @@ virDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs,
ret = virDomainPCIAddressReserveNextAddr(addrs, dev, flags, -1);
}
dev->addr.pci.extFlags = dev->pciAddrExtFlags;
ret = virDomainPCIAddressExtensionEnsureAddr(addrs, &dev->addr.pci);
cleanup:
VIR_FREE(addrStr);
return ret;
}
void
virDomainPCIAddressExtensionReleaseAddr(virDomainPCIAddressSetPtr addrs,
virPCIDeviceAddressPtr addr)
{
if (addr->extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI)
virDomainZPCIAddressReleaseIds(addrs->zpciIds, &addr->zpci);
}
void
virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs,
virPCIDeviceAddressPtr addr)
......
......@@ -160,6 +160,14 @@ bool virDomainPCIAddressSlotInUse(virDomainPCIAddressSetPtr addrs,
virPCIDeviceAddressPtr addr)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int virDomainPCIAddressExtensionReserveAddr(virDomainPCIAddressSetPtr addrs,
virPCIDeviceAddressPtr addr)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int virDomainPCIAddressExtensionReserveNextAddr(virDomainPCIAddressSetPtr addrs,
virPCIDeviceAddressPtr addr)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs,
virPCIDeviceAddressPtr addr,
virDomainPCIConnectFlags flags,
......@@ -181,6 +189,10 @@ void virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs,
virPCIDeviceAddressPtr addr)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
void virDomainPCIAddressExtensionReleaseAddr(virDomainPCIAddressSetPtr addrs,
virPCIDeviceAddressPtr addr)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
void virDomainPCIAddressSetAllMulti(virDomainDefPtr def)
ATTRIBUTE_NONNULL(1);
......
......@@ -93,6 +93,8 @@ virCPUModeTypeToString;
# conf/device_conf.h
virDeviceInfoPCIAddressExtensionIsPresent;
virDeviceInfoPCIAddressExtensionIsWanted;
virDeviceInfoPCIAddressIsPresent;
virDeviceInfoPCIAddressIsWanted;
virDomainDeviceAddressIsValid;
......@@ -119,6 +121,9 @@ virDomainCCWAddressSetFree;
virDomainPCIAddressBusIsFullyReserved;
virDomainPCIAddressBusSetModel;
virDomainPCIAddressEnsureAddr;
virDomainPCIAddressExtensionReleaseAddr;
virDomainPCIAddressExtensionReserveAddr;
virDomainPCIAddressExtensionReserveNextAddr;
virDomainPCIAddressReleaseAddr;
virDomainPCIAddressReserveAddr;
virDomainPCIAddressReserveNextAddr;
......
......@@ -1407,6 +1407,24 @@ qemuDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs,
}
static int
qemuDomainAssignPCIAddressExtension(virDomainDefPtr def ATTRIBUTE_UNUSED,
virDomainDeviceDefPtr device ATTRIBUTE_UNUSED,
virDomainDeviceInfoPtr info,
void *opaque)
{
virDomainPCIAddressSetPtr addrs = opaque;
virPCIDeviceAddressPtr addr = &info->addr.pci;
if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
addr->extFlags = info->pciAddrExtFlags;
if (virDeviceInfoPCIAddressExtensionIsWanted(info))
return virDomainPCIAddressExtensionReserveNextAddr(addrs, addr);
return 0;
}
static int
qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
virDomainDeviceDefPtr device,
......@@ -1500,6 +1518,31 @@ qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
return ret;
}
static int
qemuDomainCollectPCIAddressExtension(virDomainDefPtr def ATTRIBUTE_UNUSED,
virDomainDeviceDefPtr device,
virDomainDeviceInfoPtr info,
void *opaque)
{
virDomainPCIAddressSetPtr addrs = opaque;
virPCIDeviceAddressPtr addr = &info->addr.pci;
if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
addr->extFlags = info->pciAddrExtFlags;
if (!virDeviceInfoPCIAddressExtensionIsPresent(info) ||
((device->type == VIR_DOMAIN_DEVICE_HOSTDEV) &&
(device->data.hostdev->parent.type != VIR_DOMAIN_DEVICE_NONE))) {
/* If a hostdev has a parent, its info will be a part of the
* parent, and will have its address collected during the scan
* of the parent's device type.
*/
return 0;
}
return virDomainPCIAddressExtensionReserveAddr(addrs, addr);
}
static virDomainPCIAddressSetPtr
qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
virQEMUCapsPtr qemuCaps,
......@@ -1591,6 +1634,12 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
if (virDomainDeviceInfoIterate(def, qemuDomainCollectPCIAddress, addrs) < 0)
goto error;
if (virDomainDeviceInfoIterate(def,
qemuDomainCollectPCIAddressExtension,
addrs) < 0) {
goto error;
}
return addrs;
error:
......@@ -2595,6 +2644,9 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
if (qemuDomainAssignDevicePCISlots(def, qemuCaps, addrs) < 0)
goto cleanup;
if (virDomainDeviceInfoIterate(def, qemuDomainAssignPCIAddressExtension, addrs) < 0)
goto cleanup;
/* Only for *new* domains with pcie-root (and no other
* manually specified PCI controllers in the definition): If,
* after assigning addresses/reserving slots for all devices,
......@@ -2689,6 +2741,9 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
if (qemuDomainAssignDevicePCISlots(def, qemuCaps, addrs) < 0)
goto cleanup;
if (virDomainDeviceInfoIterate(def, qemuDomainAssignPCIAddressExtension, addrs) < 0)
goto cleanup;
/* set multi attribute for devices at function 0 of
* any slot that has multiple functions in use
*/
......@@ -3148,8 +3203,10 @@ qemuDomainReleaseDeviceAddress(virDomainObjPtr vm,
if (!devstr)
devstr = info->alias;
if (virDeviceInfoPCIAddressIsPresent(info))
if (virDeviceInfoPCIAddressIsPresent(info)) {
virDomainPCIAddressReleaseAddr(priv->pciaddrs, &info->addr.pci);
virDomainPCIAddressExtensionReleaseAddr(priv->pciaddrs, &info->addr.pci);
}
if (virDomainUSBAddressRelease(priv->usbaddrs, info) < 0)
VIR_WARN("Unable to release USB address on %s", NULLSTR(devstr));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册