[libvirt] [PATCH 03/34] Extend the virDomainDeviceAddress struture to allow disk controller addresses

Daniel P. Berrange berrange at redhat.com
Fri Jan 8 17:22:59 UTC 2010


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




More information about the libvir-list mailing list