</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
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.5.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
credentials to the iSCSI server.
</p>
</dd>
+ <dt><code>scsi_host</code></dt>
+ <dd><span class="since">Since 2.5.0</span>, multiple LUNs behind a
+ single SCSI HBA 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>
libvirtd via SSH, using the libssh library; for example:
<tt>qemu+libssh://<i>server</i>/system</tt>
</li>
+ <li>vhost-scsi: Add support scsi_host hostdev passthrough<br/>
+ Add the capability to pass through a scsi_host HBA and the
+ associated LUNs to the guest.
+ </li>
</ul>
</li>
<li><strong>Improvements</strong>
<ref name="hostdevsubsyspci"/>
<ref name="hostdevsubsysusb"/>
<ref name="hostdevsubsysscsi"/>
+ <ref name="hostdevsubsyshost"/>
</choice>
</define>
</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>
virDomainHostdevSubsysUSBPtr usbsrc = &hostdev->source.subsys.u.usb;
virDomainHostdevSubsysPCIPtr pcisrc = &hostdev->source.subsys.u.pci;
virDomainHostdevSubsysSCSIPtr scsisrc = &hostdev->source.subsys.u.scsi;
+ virDomainHostdevSubsysSCSIVHostPtr hostsrc = &hostdev->source.subsys.u.scsi_host;
virUUIDFormat(vm->def->uuid, uuidstr);
if (!(vmname = virAuditEncode("vm", vm->def->name))) {
}
break;
}
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
+ if (VIR_STRDUP_QUIET(address, hostsrc->wwpn) < 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);
} else {
VIR_FREE(scsisrc->u.host.adapter);
}
+ } else if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST) {
+ virDomainHostdevSubsysSCSIVHostPtr hostsrc = &def->source.subsys.u.scsi_host;
+ VIR_FREE(hostsrc->wwpn);
}
break;
}
return ret;
}
+static int
+virDomainHostdevSubsysSCSIVHostDefParseXML(xmlNodePtr sourcenode,
+ virDomainHostdevDefPtr def)
+{
+ char *protocol = NULL;
+ virDomainHostdevSubsysSCSIVHostPtr hostsrc = &def->source.subsys.u.scsi_host;
+
+ if (!(protocol = virXMLPropString(sourcenode, "protocol"))) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Missing scsi_host subsystem protocol"));
+ return -1;
+ }
+
+ if ((hostsrc->protocol =
+ virDomainHostdevSubsysSCSIHostProtocolTypeFromString(protocol)) <= 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Unknown scsi_host subsystem protocol '%s'"),
+ protocol);
+ goto cleanup;
+ }
+
+ switch ((virDomainHostdevSubsysSCSIHostProtocolType) hostsrc->protocol) {
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_VHOST:
+ if (!(hostsrc->wwpn = virXMLPropString(sourcenode, "wwpn"))) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("missing vhost-scsi hostdev source wwpn"));
+ goto cleanup;
+ }
+
+ if (!STRPREFIX(hostsrc->wwpn, "naa.") ||
+ !virValidateWWN(hostsrc->wwpn + 4)) {
+ virReportError(VIR_ERR_XML_ERROR, "%s", _("malformed 'wwpn' value"));
+ goto cleanup;
+ }
+ break;
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_NONE:
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_LAST:
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid hostdev protocol '%s'"),
+ virDomainHostdevSubsysSCSIHostProtocolTypeToString(hostsrc->protocol));
+ goto cleanup;
+ break;
+ }
+
+ return 0;
+
+ cleanup:
+ VIR_FREE(hostsrc->wwpn);
+ VIR_FREE(protocol);
+ return -1;
+}
+
static int
virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
goto error;
break;
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
+ if (virDomainHostdevSubsysSCSIVHostDefParseXML(sourcenode, def) < 0)
+ goto error;
+ break;
+
default:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("address type='%s' not supported in hostdev interfaces"),
def->shareable = true;
break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
+ if (def->info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
+ def->info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI &&
+ def->info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("SCSI_host host device must use 'pci' "
+ "or 'ccw' address type"));
+ goto error;
+ }
+ break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
break;
else
return virDomainHostdevMatchSubsysSCSIHost(a, b);
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
- /* Fall through for now */
+ if (a->source.subsys.u.scsi_host.protocol !=
+ b->source.subsys.u.scsi_host.protocol)
+ return 0;
+ if (STREQ(a->source.subsys.u.scsi_host.wwpn,
+ b->source.subsys.u.scsi_host.wwpn))
+ return 1;
+ else
+ return 0;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
return 0;
}
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;
+ virDomainHostdevSubsysSCSIVHostPtr hostsrc = &def->source.subsys.u.scsi_host;
virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi;
protocol, iscsisrc->path);
}
+ if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST) {
+ const char *protocol =
+ virDomainHostdevSubsysSCSIHostProtocolTypeToString(hostsrc->protocol);
+ closedSource = true;
+
+ virBufferAsprintf(buf, " protocol='%s' wwpn='%s'/",
+ protocol, hostsrc->wwpn);
+ }
+
virBufferAddLit(buf, ">\n");
virBufferAdjustIndent(buf, 2);
scsihostsrc->unit);
}
break;
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
+ break;
default:
virReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected hostdev type %d"),
}
virBufferAdjustIndent(buf, -2);
- virBufferAddLit(buf, "</source>\n");
+ if (!closedSource)
+ virBufferAddLit(buf, "</source>\n");
return 0;
}
--- /dev/null
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu \
+-name QEMUGuest2 \
+-S \
+-M s390-ccw \
+-m 214 \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9466-926a-d65c16db1809 \
+-nographic \
+-nodefaults \
+-monitor unix:/tmp/lib/domain--1-QEMUGuest2/monitor.sock,server,nowait \
+-no-acpi \
+-boot c \
+-device virtio-scsi-ccw,id=scsi0,devno=fe.0.0001 \
+-drive file=/dev/HostVG/QEMUGuest2,format=raw,if=none,id=drive-virtio-disk0 \
+-device virtio-blk-ccw,devno=fe.0.0000,drive=drive-virtio-disk0,\
+id=virtio-disk0 \
+-device vhost-scsi-ccw,wwpn=naa.5123456789abcde0,vhostfd=3,id=hostdev0,\
+devno=fe.0.0002 \
+-device virtio-balloon-ccw,id=balloon0,devno=fe.0.0003
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest2</name>
+ <uuid>c7a5fdbd-edaf-9466-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='s390x' machine='s390-ccw'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest2'/>
+ <target dev='hda' bus='virtio'/>
+ <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0000'/>
+ </disk>
+ <controller type='scsi' index='0' model='virtio-scsi'>
+ <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0001'/>
+ </controller>
+ <hostdev mode='subsystem' type='scsi_host' managed='no'>
+ <source protocol='vhost' wwpn='naa.5123456789abcde0'/>
+ <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0002'/>
+ </hostdev>
+ <memballoon model='virtio'>
+ <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0003'/>
+ </memballoon>
+ <panic model='s390'/>
+ </devices>
+</domain>
--- /dev/null
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu \
+-name QEMUGuest2 \
+-S \
+-M pc \
+-m 214 \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9466-926a-d65c16db1809 \
+-nographic \
+-nodefaults \
+-monitor unix:/tmp/lib/domain--1-QEMUGuest2/monitor.sock,server,nowait \
+-no-acpi \
+-boot c \
+-device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x3 \
+-usb \
+-drive file=/dev/HostVG/QEMUGuest2,format=raw,if=none,id=drive-ide0-0-0 \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
+-device vhost-scsi-pci,wwpn=naa.5123456789abcde0,vhostfd=3,id=hostdev0,\
+bus=pci.0,addr=0x5 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest2</name>
+ <uuid>c7a5fdbd-edaf-9466-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest2'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <controller type='scsi' index='0' model='virtio-scsi'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
+ </controller>
+ <controller type='usb' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+ </controller>
+ <controller type='ide' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+ </controller>
+ <controller type='pci' index='0' model='pci-root'/>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <hostdev mode='subsystem' type='scsi_host' managed='no'>
+ <source protocol='vhost' wwpn='naa.5123456789abcde0'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
+ </hostdev>
+ <memballoon model='virtio'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
+ </memballoon>
+ </devices>
+</domain>
DO_TEST("hostdev-scsi-virtio-iscsi-auth",
QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_VIRTIO_SCSI,
QEMU_CAPS_DEVICE_SCSI_GENERIC);
+ DO_TEST("hostdev-scsi-vhost-scsi-ccw",
+ QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_DEVICE_VHOST_SCSI,
+ QEMU_CAPS_DEVICE_SCSI_GENERIC, QEMU_CAPS_VIRTIO_CCW);
+ DO_TEST("hostdev-scsi-vhost-scsi-pci",
+ QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_DEVICE_VHOST_SCSI,
+ QEMU_CAPS_DEVICE_SCSI_GENERIC);
DO_TEST("mlock-on", QEMU_CAPS_REALTIME_MLOCK);
DO_TEST_FAILURE("mlock-on", NONE);
--- /dev/null
+../qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.xml
\ No newline at end of file
--- /dev/null
+../qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.xml
\ No newline at end of file
QEMU_CAPS_DEVICE_IOH3420,
QEMU_CAPS_HDA_DUPLEX);
+ DO_TEST("hostdev-scsi-vhost-scsi-ccw",
+ QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_DEVICE_VHOST_SCSI,
+ QEMU_CAPS_DEVICE_SCSI_GENERIC, QEMU_CAPS_VIRTIO_CCW);
+ DO_TEST("hostdev-scsi-vhost-scsi-pci",
+ QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_DEVICE_VHOST_SCSI,
+ QEMU_CAPS_DEVICE_SCSI_GENERIC);
DO_TEST("hostdev-scsi-lsi",
QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_SCSI_LSI,
QEMU_CAPS_DEVICE_SCSI_GENERIC);