From: Daniel P. Berrange Date: Tue, 1 Dec 2009 16:56:24 +0000 (+0000) Subject: Extend the virDomainDeviceAddress struture to allow disk controller addresses X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=d812e7aeb88da21a8b0175ea86a0353e05e4453f;p=libvirt.git Extend the virDomainDeviceAddress struture to allow disk controller addresses 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
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 --- diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index 7e00e7fe9c..f42658751f 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -1189,6 +1189,21 @@ + + + + + + + + + + + + + + + @@ -1305,6 +1320,12 @@ + + + drive + + + @@ -1434,6 +1455,21 @@ (0x)?[0-7] + + + [0-9]{1,2} + + + + + [0-9]{1,2} + + + + + [0-9]{1,2} + + [a-zA-Z0-9\-_]+ diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index f199c08511..d7b1aa199b 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
'controller' attribute")); + goto cleanup; + } + + if (bus && + virStrToLong_ui(bus, NULL, 10, &addr->bus) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse
'bus' attribute")); + goto cleanup; + } + + if (unit && + virStrToLong_ui(unit, NULL, 10, &addr->unit) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse
'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 c50aae0ec9..d4de042226 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);