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