[libvirt] [PATCH v2 1/5] Introduce a "scsi_host" hostdev type

Eric Farman farman at linux.vnet.ibm.com
Sat Aug 20 15:52:41 UTC 2016


We already have a "scsi" hostdev type, which refers to a single LUN
that is passed through to a guest.  But what of things where multiple
LUNs are passed through via a single SCSI HBA, such as with the
vhost-scsi target?  Create a new hostdev type that will carry
this, and its associated documentation and XML schema information.

Signed-off-by: Eric Farman <farman at linux.vnet.ibm.com>
---
 docs/formatdomain.html.in           | 24 ++++++++++++++++
 docs/schemas/domaincommon.rng       | 23 +++++++++++++++
 src/conf/domain_audit.c             |  2 ++
 src/conf/domain_conf.c              | 56 +++++++++++++++++++++++++++++++++++--
 src/conf/domain_conf.h              | 17 +++++++++++
 src/qemu/qemu_domain_address.c      | 10 +++++++
 src/qemu/qemu_hotplug.c             |  1 +
 src/security/security_dac.c         |  2 ++
 tests/domaincapsschemadata/full.xml |  1 +
 9 files changed, 134 insertions(+), 2 deletions(-)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index bfbb0f2..b27740b 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -3585,6 +3585,17 @@
   </devices>
   ...</pre>
 
+    <p>or:</p>
+
+<pre>
+  ...
+  <devices>
+    <hostdev mode='subsystem' type='scsi_host'>
+      <source protocol='vhost' wwpn='naa.50014057667280d8'/>
+    </hostdev>
+  </devices>
+  ...</pre>
+
     <dl>
       <dt><code>hostdev</code></dt>
       <dd>The <code>hostdev</code> element is the main container for describing
@@ -3623,6 +3634,12 @@
             If a disk lun in the domain already has the rawio capability,
             then this setting not required.
           </dd>
+          <dt><code>scsi_host</code></dt>
+          <dd><span class="since">since 2.2.0</span>For SCSI devices, user
+            is responsible to make sure the device is not used by host. This
+            <code>type</code> passes all LUNs presented by a single HBA to
+            the guest.
+          </dd>
         </dl>
         <p>
           Note: The <code>managed</code> attribute is only used with PCI devices
@@ -3686,6 +3703,13 @@
             credentials to the iSCSI server.
             </p>
           </dd>
+          <dt><code>scsi_host</code></dt>
+          <dd><span class="since">Since 2.2.0</span>, multiple LUNs behind a
+            single SCSI HBI are described by a <code>protocol</code>
+            attribute set to "vhost" and a <code>wwpn</code> attribute that
+            is the vhost_scsi wwpn (16 hexadecimal digits with a prefix of
+            "naa.") established in the host configfs.
+          </dd>
         </dl>
       </dd>
       <dt><code>vendor</code>, <code>product</code></dt>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 052f28c..b8cea46 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3909,6 +3909,7 @@
       <ref name="hostdevsubsyspci"/>
       <ref name="hostdevsubsysusb"/>
       <ref name="hostdevsubsysscsi"/>
+      <ref name="hostdevsubsyshost"/>
     </choice>
   </define>
 
@@ -4037,6 +4038,28 @@
     </element>
   </define>
 
+  <define name="hostdevsubsyshost">
+    <attribute name="type">
+      <value>scsi_host</value>
+    </attribute>
+    <element name="source">
+      <choice>
+        <group>
+          <attribute name="protocol">
+            <choice>
+              <value>vhost</value>     <!-- vhost, required -->
+            </choice>
+          </attribute>
+          <attribute name="wwpn">
+            <data type="string">
+              <param name="pattern">(naa\.)[0-9a-fA-F]{16}</param>
+            </data>
+          </attribute>
+        </group>
+      </choice>
+    </element>
+  </define>
+
   <define name="hostdevcapsstorage">
     <attribute name="type">
       <value>storage</value>
diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c
index 53a58ac..406dd8f 100644
--- a/src/conf/domain_audit.c
+++ b/src/conf/domain_audit.c
@@ -443,6 +443,8 @@ virDomainAuditHostdev(virDomainObjPtr vm, virDomainHostdevDefPtr hostdev,
             }
             break;
         }
+        case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_HOST:
+            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 14d4f7d..636e81a 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -646,7 +646,8 @@ VIR_ENUM_IMPL(virDomainHostdevMode, VIR_DOMAIN_HOSTDEV_MODE_LAST,
 VIR_ENUM_IMPL(virDomainHostdevSubsys, VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST,
               "usb",
               "pci",
-              "scsi")
+              "scsi",
+              "scsi_host")
 
 VIR_ENUM_IMPL(virDomainHostdevSubsysPCIBackend,
               VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST,
@@ -660,6 +661,10 @@ VIR_ENUM_IMPL(virDomainHostdevSubsysSCSIProtocol,
               "adapter",
               "iscsi")
 
+VIR_ENUM_IMPL(virDomainHostdevSubsysHostProtocol,
+              VIR_DOMAIN_HOSTDEV_HOST_PROTOCOL_TYPE_LAST,
+              "vhost")
+
 VIR_ENUM_IMPL(virDomainHostdevCaps, VIR_DOMAIN_HOSTDEV_CAPS_TYPE_LAST,
               "storage",
               "misc",
@@ -2270,6 +2275,9 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr def)
             } else {
                 VIR_FREE(scsisrc->u.host.adapter);
             }
+        } else if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_HOST) {
+            virDomainHostdevSubsysHostPtr hostsrc = &def->source.subsys.u.host;
+            VIR_FREE(hostsrc->wwpn);
         }
         break;
     }
@@ -5926,6 +5934,31 @@ virDomainHostdevSubsysSCSIDefParseXML(xmlNodePtr sourcenode,
     return ret;
 }
 
+static int
+virDomainHostdevSubsysHostDefParseXML(xmlNodePtr sourcenode,
+                                      virDomainHostdevDefPtr def)
+{
+    virDomainHostdevSubsysHostPtr hostsrc = &def->source.subsys.u.host;
+
+    if (!(hostsrc->wwpn = virXMLPropString(sourcenode, "wwpn"))) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("missing vhost-scsi hostdev source path name"));
+        goto cleanup;
+    }
+
+    if (!STRPREFIX(hostsrc->wwpn, "naa.") ||
+        strlen(hostsrc->wwpn) != strlen("naa.") + 16) {
+        virReportError(VIR_ERR_XML_ERROR, "%s", _("malformed 'wwpn' value"));
+        goto cleanup;
+    }
+
+    return 0;
+
+ cleanup:
+    VIR_FREE(hostsrc->wwpn);
+    return -1;
+}
+
 
 static int
 virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
@@ -6050,6 +6083,11 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
             goto error;
         break;
 
+    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_HOST:
+        if (virDomainHostdevSubsysHostDefParseXML(sourcenode, def) < 0)
+            goto error;
+        break;
+
     default:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("address type='%s' not supported in hostdev interfaces"),
@@ -20389,9 +20427,11 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
                                 unsigned int flags,
                                 bool includeTypeInAddr)
 {
+    bool closedSource = false;
     virDomainHostdevSubsysUSBPtr usbsrc = &def->source.subsys.u.usb;
     virDomainHostdevSubsysPCIPtr pcisrc = &def->source.subsys.u.pci;
     virDomainHostdevSubsysSCSIPtr scsisrc = &def->source.subsys.u.scsi;
+    virDomainHostdevSubsysHostPtr hostsrc = &def->source.subsys.u.host;
     virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
     virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi;
 
@@ -20432,6 +20472,15 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
                           protocol, iscsisrc->path);
     }
 
+    if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_HOST) {
+        const char *protocol =
+            virDomainHostdevSubsysHostProtocolTypeToString(hostsrc->protocol);
+        closedSource = true;
+
+        virBufferAsprintf(buf, " protocol='%s' wwpn='%s'/",
+                          protocol, hostsrc->wwpn);
+    }
+
     virBufferAddLit(buf, ">\n");
 
     virBufferAdjustIndent(buf, 2);
@@ -20485,6 +20534,8 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
                               scsihostsrc->unit);
         }
         break;
+    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_HOST:
+        break;
     default:
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unexpected hostdev type %d"),
@@ -20500,7 +20551,8 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
     }
 
     virBufferAdjustIndent(buf, -2);
-    virBufferAddLit(buf, "</source>\n");
+    if (!closedSource)
+        virBufferAddLit(buf, "</source>\n");
 
     return 0;
 }
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 8b26724..93d4ef5 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -294,6 +294,7 @@ typedef enum {
     VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB,
     VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI,
     VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI,
+    VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_HOST,
 
     VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST
 } virDomainHostdevSubsysType;
@@ -368,6 +369,21 @@ struct _virDomainHostdevSubsysSCSI {
     } u;
 };
 
+typedef enum {
+    VIR_DOMAIN_HOSTDEV_HOST_PROTOCOL_TYPE_VHOST,
+
+    VIR_DOMAIN_HOSTDEV_HOST_PROTOCOL_TYPE_LAST,
+} virDomainHostdevHostProtocolType;
+
+VIR_ENUM_DECL(virDomainHostdevSubsysHostProtocol)
+
+typedef struct _virDomainHostdevSubsysHost virDomainHostdevSubsysHost;
+typedef virDomainHostdevSubsysHost *virDomainHostdevSubsysHostPtr;
+struct _virDomainHostdevSubsysHost {
+    int protocol;
+    char *wwpn;
+};
+
 typedef struct _virDomainHostdevSubsys virDomainHostdevSubsys;
 typedef virDomainHostdevSubsys *virDomainHostdevSubsysPtr;
 struct _virDomainHostdevSubsys {
@@ -376,6 +392,7 @@ struct _virDomainHostdevSubsys {
         virDomainHostdevSubsysUSB usb;
         virDomainHostdevSubsysPCI pci;
         virDomainHostdevSubsysSCSI scsi;
+        virDomainHostdevSubsysHost host;
     } u;
 };
 
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
index 3d52d72..1eab2bf 100644
--- a/src/qemu/qemu_domain_address.c
+++ b/src/qemu/qemu_domain_address.c
@@ -301,6 +301,16 @@ qemuDomainPrimeVirtioDeviceAddresses(virDomainDefPtr def,
             def->controllers[i]->info.type = type;
     }
 
+    for (i = 0; i < def->nhostdevs; i++) {
+        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+            def->hostdevs[i]->source.subsys.type ==
+            VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_HOST &&
+            def->hostdevs[i]->source.subsys.u.host.protocol ==
+            VIR_DOMAIN_HOSTDEV_HOST_PROTOCOL_TYPE_VHOST &&
+            def->hostdevs[i]->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+            def->hostdevs[i]->info->type = type;
+    }
+
     if (def->memballoon &&
         def->memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO &&
         def->memballoon->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 00e4a75..7a6d285 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -3253,6 +3253,7 @@ qemuDomainRemoveHostDevice(virQEMUDriverPtr driver,
         qemuDomainRemoveUSBHostDevice(driver, vm, hostdev);
         break;
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
+    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_HOST:
         qemuDomainRemoveSCSIHostDevice(driver, vm, hostdev);
         break;
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index 442ce70..de2b921 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -676,6 +676,7 @@ virSecurityDACSetHostdevLabel(virSecurityManagerPtr mgr,
         break;
     }
 
+    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_HOST:
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
         ret = 0;
         break;
@@ -805,6 +806,7 @@ virSecurityDACRestoreHostdevLabel(virSecurityManagerPtr mgr,
         break;
     }
 
+    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_HOST:
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
         ret = 0;
         break;
diff --git a/tests/domaincapsschemadata/full.xml b/tests/domaincapsschemadata/full.xml
index 2f529ff..41fb1fa 100644
--- a/tests/domaincapsschemadata/full.xml
+++ b/tests/domaincapsschemadata/full.xml
@@ -75,6 +75,7 @@
         <value>usb</value>
         <value>pci</value>
         <value>scsi</value>
+        <value>scsi_host</value>
       </enum>
       <enum name='capsType'>
         <value>storage</value>
-- 
1.9.1




More information about the libvir-list mailing list