Introduce a new structure struct _virDomainDeviceDriveAddress { unsigned int controller; unsigned int bus; unsigned int unit; }; and plug that into virDomainDeviceAddress and generates XML that looks like <address type='drive' controller='1' bus='0' unit='5'/> This syntax will be used by the QEMU driver to explicitly control how drives are attached to the bus * src/conf/domain_conf.h, src/conf/domain_conf.c: Parsing and formatting of drive addresses * docs/schemas/domain.rng: Define new address format for drives --- docs/schemas/domain.rng | 36 +++++++++++++++++++ src/conf/domain_conf.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++- src/conf/domain_conf.h | 13 +++++++ 3 files changed, 135 insertions(+), 1 deletions(-) diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index 7e00e7f..f426587 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -1189,6 +1189,21 @@ <ref name="pciFunc"/> </attribute> </define> + <define name="driveaddress"> + <optional> + <attribute name="controller"> + <ref name="driveController"/> + </attribute> + </optional> + <optional> + <attribute name="bus"> + <ref name="driveBus"/> + </attribute> + </optional> + <attribute name="unit"> + <ref name="driveUnit"/> + </attribute> + </define> <!-- Devices attached to a domain. --> @@ -1305,6 +1320,12 @@ </attribute> <ref name="pciaddress"/> </group> + <group> + <attribute name="type"> + <value>drive</value> + </attribute> + <ref name="driveaddress"/> + </group> </choice> </element> </define> @@ -1434,6 +1455,21 @@ <param name="pattern">(0x)?[0-7]</param> </data> </define> + <define name="driveController"> + <data type="string"> + <param name="pattern">[0-9]{1,2}</param> + </data> + </define> + <define name="driveBus"> + <data type="string"> + <param name="pattern">[0-9]{1,2}</param> + </data> + </define> + <define name="driveUnit"> + <data type="string"> + <param name="pattern">[0-9]{1,2}</param> + </data> + </define> <define name="featureName"> <data type="string"> <param name='pattern'>[a-zA-Z0-9\-_]+</param> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index f199c08..d7b1aa1 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -90,7 +90,8 @@ VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST, VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST, "none", - "pci") + "pci", + "drive"); VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST, "block", @@ -748,6 +749,9 @@ int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info, switch (info->type) { case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI: return virDomainDevicePCIAddressIsValid(&info->addr.pci); + + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE: + return virDomainDeviceDriveAddressIsValid(&info->addr.drive); } return 0; @@ -760,6 +764,13 @@ int virDomainDevicePCIAddressIsValid(virDomainDevicePCIAddressPtr addr) } +int virDomainDeviceDriveAddressIsValid(virDomainDeviceDriveAddressPtr addr ATTRIBUTE_UNUSED) +{ + /*return addr->controller || addr->bus || addr->unit;*/ + return 1; /* 0 is valid for all fields, so any successfully parsed addr is valid */ +} + + int virDomainDeviceInfoIsSet(virDomainDeviceInfoPtr info) { if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) @@ -803,6 +814,13 @@ static int virDomainDeviceInfoFormat(virBufferPtr buf, info->addr.pci.function); break; + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE: + virBufferVSprintf(buf, " controller='%d' bus='%d' unit='%d'", + info->addr.drive.controller, + info->addr.drive.bus, + info->addr.drive.unit); + break; + default: virDomainReportError(NULL, VIR_ERR_INTERNAL_ERROR, _("unknown address type '%d'"), info->type); @@ -828,6 +846,18 @@ int virDomainDevicePCIAddressEqual(virDomainDevicePCIAddressPtr a, } +int virDomainDeviceDriveAddressEqual(virDomainDeviceDriveAddressPtr a, + virDomainDeviceDriveAddressPtr b) +{ + if (a->controller == b->controller && + a->bus == b->bus && + a->unit == b->unit) + return 1; + + return 0; +} + + static int virDomainDevicePCIAddressParseXML(virConnectPtr conn, xmlNodePtr node, @@ -888,6 +918,56 @@ cleanup: } +static int +virDomainDeviceDriveAddressParseXML(virConnectPtr conn, + xmlNodePtr node, + virDomainDeviceDriveAddressPtr addr) +{ + char *bus, *unit, *controller; + int ret = -1; + + memset(addr, 0, sizeof(*addr)); + + controller = virXMLPropString(node, "controller"); + bus = virXMLPropString(node, "bus"); + unit = virXMLPropString(node, "unit"); + + if (controller && + virStrToLong_ui(controller, NULL, 10, &addr->controller) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse <address> 'controller' attribute")); + goto cleanup; + } + + if (bus && + virStrToLong_ui(bus, NULL, 10, &addr->bus) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse <address> 'bus' attribute")); + goto cleanup; + } + + if (unit && + virStrToLong_ui(unit, NULL, 10, &addr->unit) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse <address> 'unit' attribute")); + goto cleanup; + } + + if (!virDomainDeviceDriveAddressIsValid(addr)) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", + _("Insufficient specification for drive address")); + goto cleanup; + } + + ret = 0; + +cleanup: + VIR_FREE(controller); + VIR_FREE(bus); + VIR_FREE(unit); + return ret; +} + /* Parse the XML definition for a device address * @param node XML nodeset to parse for device address definition */ @@ -938,6 +1018,11 @@ virDomainDeviceInfoParseXML(virConnectPtr conn, goto cleanup; break; + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE: + if (virDomainDeviceDriveAddressParseXML(conn, node, &info->addr.drive) < 0) + goto cleanup; + break; + default: /* Should not happen */ virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index c50aae0..d4de042 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -67,6 +67,7 @@ enum virDomainVirtType { enum virDomainDeviceAddressType { VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI, + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST }; @@ -80,12 +81,21 @@ struct _virDomainDevicePCIAddress { unsigned int function; }; +typedef struct _virDomainDeviceDriveAddress virDomainDeviceDriveAddress; +typedef virDomainDeviceDriveAddress *virDomainDeviceDriveAddressPtr; +struct _virDomainDeviceDriveAddress { + unsigned int controller; + unsigned int bus; + unsigned int unit; +}; + typedef struct _virDomainDeviceInfo virDomainDeviceInfo; typedef virDomainDeviceInfo *virDomainDeviceInfoPtr; struct _virDomainDeviceInfo { int type; union { virDomainDevicePCIAddress pci; + virDomainDeviceDriveAddress drive; } addr; }; @@ -690,9 +700,12 @@ void virDomainHostdevDefFree(virDomainHostdevDefPtr def); void virDomainDeviceDefFree(virDomainDeviceDefPtr def); int virDomainDevicePCIAddressEqual(virDomainDevicePCIAddressPtr a, virDomainDevicePCIAddressPtr b); +int virDomainDeviceDriveAddressEqual(virDomainDeviceDriveAddressPtr a, + virDomainDeviceDriveAddressPtr b); int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info, int type); int virDomainDevicePCIAddressIsValid(virDomainDevicePCIAddressPtr addr); +int virDomainDeviceDriveAddressIsValid(virDomainDeviceDriveAddressPtr addr); int virDomainDeviceInfoIsSet(virDomainDeviceInfoPtr info); void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info); void virDomainDefFree(virDomainDefPtr vm); -- 1.6.5.2 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list