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(a)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 feaeaa2..b79da95 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -3655,6 +3655,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
@@ -3693,6 +3704,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
@@ -3756,6 +3773,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 af32df8..7fd6bd2 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3938,6 +3938,7 @@
<ref name="hostdevsubsyspci"/>
<ref name="hostdevsubsysusb"/>
<ref name="hostdevsubsysscsi"/>
+ <ref name="hostdevsubsyshost"/>
</choice>
</define>
@@ -4066,6 +4067,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 c8c4f61..45b643b 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;
}
@@ -5977,6 +5985,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,
@@ -6101,6 +6134,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"),
@@ -20521,9 +20559,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;
@@ -20564,6 +20604,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);
@@ -20617,6 +20666,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"),
@@ -20632,7 +20683,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 0fe4154..781ea7b 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 bb16738..8419e6a 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 d13474a..e9140a9 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -3238,6 +3238,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