[libvirt] [PATCH RFC 2/5] conf: Introduce scsi hostdev

Han Cheng hanc.fnst at cn.fujitsu.com
Mon Mar 4 06:01:20 UTC 2013


Adding scsi hostdev, it should like:

    <hostdev mode='subsystem' type='scsi'>
      <source>
        <adapter name='scsi_host0'/>
        <address bus='0' target='0' unit='0'/>
      </source>
      <address type='drive' controller='0' bus='0' target='4' unit='8'/>
    </hostdev>
---
 docs/schemas/domaincommon.rng |   33 +++++++++
 src/conf/domain_audit.c       |   10 +++
 src/conf/domain_conf.c        |  149 +++++++++++++++++++++++++++++++++++++++--
 src/conf/domain_conf.h        |    7 ++
 4 files changed, 194 insertions(+), 5 deletions(-)

diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index fbb4001..ebd0e42 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -2931,6 +2931,7 @@
     <choice>
       <ref name="hostdevsubsyspci"/>
       <ref name="hostdevsubsysusb"/>
+      <ref name="hostdevsubsysscsi"/>
     </choice>
   </define>
 
@@ -2983,6 +2984,22 @@
     </element>
   </define>
 
+  <define name="hostdevsubsysscsi">
+    <attribute name="type">
+      <value>scsi</value>
+    </attribute>
+    <element name="source">
+      <element name="adapter">
+        <attribute name="name">
+           <ref name="scsiAdapter"/>
+        </attribute>
+      </element>
+      <element name="address">
+        <ref name="scsiaddress"/>
+      </element>
+    </element>
+  </define>
+
   <define name="hostdevcapsstorage">
     <attribute name="type">
       <value>storage</value>
@@ -3027,6 +3044,17 @@
       </attribute>
     </element>
   </define>
+  <define name="scsiaddress">
+    <attribute name="bus">
+      <ref name="driveBus"/>
+    </attribute>
+    <attribute name="target">
+      <ref name="driveTarget"/>
+    </attribute>
+    <attribute name="unit">
+      <ref name="driveUnit"/>
+    </attribute>
+  </define>
   <define name="usbportaddress">
     <attribute name="bus">
       <ref name="usbAddr"/>
@@ -3893,4 +3921,9 @@
     </element>
     <empty/>
   </define>
+  <define name="scsiAdapter">
+    <data type="string">
+      <param name="pattern">scsi_host[0-9]{1,2}</param>
+    </data>
+  </define>
 </grammar>
diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c
index c00bd11..e6d44b1 100644
--- a/src/conf/domain_audit.c
+++ b/src/conf/domain_audit.c
@@ -281,6 +281,16 @@ virDomainAuditHostdev(virDomainObjPtr vm, virDomainHostdevDefPtr hostdev,
                 goto cleanup;
             }
             break;
+        case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
+            if (virAsprintf(&address, "%.3d:%.3d:%.3d:%.3d",
+                            hostdev->source.subsys.u.scsi.adapter,
+                            hostdev->source.subsys.u.scsi.bus,
+                            hostdev->source.subsys.u.scsi.target,
+                            hostdev->source.subsys.u.scsi.unit) < 0) {
+                VIR_WARN("OOM while encoding audit message");
+                goto cleanup;
+            }
+            break;
         default:
             VIR_WARN("Unexpected hostdev type while encoding audit message: %d",
                      hostdev->source.subsys.type);
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 5e385e4..2be9129 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -557,7 +557,8 @@ VIR_ENUM_IMPL(virDomainHostdevMode, VIR_DOMAIN_HOSTDEV_MODE_LAST,
 
 VIR_ENUM_IMPL(virDomainHostdevSubsys, VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST,
               "usb",
-              "pci")
+              "pci",
+              "scsi")
 
 VIR_ENUM_IMPL(virDomainHostdevCaps, VIR_DOMAIN_HOSTDEV_CAPS_TYPE_LAST,
               "storage",
@@ -2928,6 +2929,96 @@ virDomainParseLegacyDeviceAddress(char *devaddr,
 }
 
 static int
+virDomainHostdevSubsysScsiDefParseXML(const xmlNodePtr node,
+                                      virDomainHostdevDefPtr def)
+{
+    int ret = -1;
+    xmlNodePtr cur;
+
+    cur = node->children;
+    while (cur != NULL) {
+        if (cur->type == XML_ELEMENT_NODE) {
+            if (xmlStrEqual(cur->name, BAD_CAST "address")) {
+                char *bus, *target, *unit;
+
+                bus=virXMLPropString(cur, "bus");
+                if (bus) {
+                    ret = virStrToLong_ui(bus, NULL, 0,
+                                          &def->source.subsys.u.scsi.bus);
+                    VIR_FREE(bus);
+                    if (ret < 0) {
+                        virReportError(VIR_ERR_INTERNAL_ERROR,
+                                       _("cannot parse bus %s"), bus);
+                        goto out;
+                    }
+                } else {
+                    virReportError(VIR_ERR_INTERNAL_ERROR,
+                                   "%s", _("scsi address needs bus id"));
+                    goto out;
+                }
+                target=virXMLPropString(cur, "target");
+                if (target) {
+                    ret = virStrToLong_ui(target, NULL, 0,
+                                          &def->source.subsys.u.scsi.target);
+                    VIR_FREE(target);
+                    if (ret < 0) {
+                        virReportError(VIR_ERR_INTERNAL_ERROR,
+                                       _("cannot parse target %s"), target);
+                        goto out;
+                    }
+                } else {
+                    virReportError(VIR_ERR_INTERNAL_ERROR,
+                                   "%s", _("scsi address needs target id"));
+                    goto out;
+                }
+                unit=virXMLPropString(cur, "unit");
+                if (unit) {
+                    ret = virStrToLong_ui(unit, NULL, 0,
+                                          &def->source.subsys.u.scsi.unit);
+                    VIR_FREE(unit);
+                    if (ret < 0) {
+                        virReportError(VIR_ERR_INTERNAL_ERROR,
+                                       _("cannot parse unit %s"), unit);
+                        goto out;
+                    }
+                } else {
+                    virReportError(VIR_ERR_INTERNAL_ERROR,
+                                   "%s", _("scsi address needs unit id"));
+                    goto out;
+                }
+            } else if (xmlStrEqual(cur->name, BAD_CAST "adapter")) {
+                char *adapter;
+                adapter = virXMLPropString(cur, "name");
+                if (adapter && STRSKIP(adapter, "scsi_host")) {
+                    ret = virStrToLong_ui(adapter + strlen("scsi_host"), NULL, 0,
+                                          &def->source.subsys.u.scsi.adapter);
+                    VIR_FREE(adapter);
+                    if (ret < 0) {
+                        virReportError(VIR_ERR_INTERNAL_ERROR,
+                                       _("cannot parse adapter %s"), adapter);
+                        goto out;
+                    }
+                } else {
+                    virReportError(VIR_ERR_INTERNAL_ERROR,
+                                   "%s", _("scsi needs adapter"));
+                    goto out;
+                }
+            } else {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("unknown scsi source type '%s'"),
+                               cur->name);
+                goto out;
+            }
+        }
+        cur = cur->next;
+    }
+
+    ret = 0;
+out:
+    return ret;
+}
+
+static int
 virDomainHostdevSubsysUsbDefParseXML(const xmlNodePtr node,
                                      virDomainHostdevDefPtr def)
 {
@@ -3222,6 +3313,10 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
         if (virDomainHostdevSubsysUsbDefParseXML(sourcenode, def) < 0)
             goto error;
         break;
+    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
+        if (virDomainHostdevSubsysScsiDefParseXML(sourcenode, def) < 0)
+            goto error;
+        break;
     default:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("address type='%s' not supported in hostdev interfaces"),
@@ -12146,6 +12241,30 @@ virDomainDefMaybeAddSmartcardController(virDomainDefPtr def)
     return 0;
 }
 
+static int
+virDomainDefMaybeAddHostdevSCSIcontroller(virDomainDefPtr def)
+{
+    /* Look for any hostdev scsi dev */
+    int i;
+    int maxController = -1;
+    virDomainHostdevDefPtr hostdev;
+
+    for (i = 0; i < def->nhostdevs; i++) {
+        hostdev = *(def->hostdevs + i);
+        if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+            hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI &&
+            (int)hostdev->info->addr.drive.controller > maxController) {
+            maxController = hostdev->info->addr.drive.controller;
+        }
+    }
+
+    for (i = 0; i <= maxController; i++) {
+        if (virDomainDefMaybeAddController(def, VIR_DOMAIN_CONTROLLER_TYPE_SCSI, i) < 0)
+            return -1;
+    }
+
+    return 0;
+}
 
 /*
  * Based on the declared <address/> info for any devices,
@@ -12182,6 +12301,9 @@ virDomainDefAddImplicitControllers(virDomainDefPtr def)
     if (virDomainDefMaybeAddSmartcardController(def) < 0)
         return -1;
 
+    if (virDomainDefMaybeAddHostdevSCSIcontroller(def) < 0)
+        return -1;
+
     return 0;
 }
 
@@ -12997,6 +13119,15 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
     virBufferAdjustIndent(buf, 2);
     switch (def->source.subsys.type)
     {
+    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
+        virBufferAsprintf(buf, "<adapter name='scsi_host%d'/>\n",
+                          def->source.subsys.u.scsi.adapter);
+        virBufferAsprintf(buf, "<address %sbus='%d' target='%d' unit='%d'/>\n",
+                          includeTypeInAddr ? "type='scsi' " : "",
+                          def->source.subsys.u.scsi.bus,
+                          def->source.subsys.u.scsi.target,
+                          def->source.subsys.u.scsi.unit);
+        break;
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
         if (def->source.subsys.u.usb.vendor) {
             virBufferAsprintf(buf, "<vendor id='0x%.4x'/>\n",
@@ -14250,10 +14381,18 @@ virDomainHostdevDefFormat(virBufferPtr buf,
     }
     virBufferAdjustIndent(buf, -6);
 
-    if (virDomainDeviceInfoFormat(buf, def->info,
-                                  flags | VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT
-                                  | VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM) < 0)
-        return -1;
+    if (def->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+        def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) {
+        if (virDomainDeviceInfoFormat(buf, def->info,
+                                      flags | VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT
+                                      | VIR_DOMAIN_XML_INTERNAL_ALLOW_READONLY) < 0)
+            return -1;
+    } else {
+        if (virDomainDeviceInfoFormat(buf, def->info,
+                                      flags | VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT
+                                      | VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM) < 0)
+            return -1;
+    }
 
     virBufferAddLit(buf, "    </hostdev>\n");
 
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 39c5849..c04cb23 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -366,6 +366,7 @@ enum virDomainHostdevMode {
 enum virDomainHostdevSubsysType {
     VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB,
     VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI,
+    VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI,
 
     VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST
 };
@@ -385,6 +386,12 @@ struct _virDomainHostdevSubsys {
             unsigned vendor;
             unsigned product;
         } usb;
+        struct {
+            unsigned adapter;
+            unsigned bus;
+            unsigned target;
+            unsigned unit;
+        } scsi;
         virDevicePCIAddress pci; /* host address */
     } u;
 };
-- 
1.7.1




More information about the libvir-list mailing list