[libvirt] [PATCH v4 0/9] Implementation of QEMU vhost-scsi

This patch series provides a libvirt implementation of the vhost-scsi interface in QEMU. As near as I can see, this was discussed upstream in July 2014[1], and ended in a desire to replace a vhost-scsi controller in favor of a hostdev element instead[2]. Host setup via targetcli (SCSI LUN(s) are already defined to host): # targetcli targetcli shell version 2.1.fb35 Copyright 2011-2013 by Datera, Inc and others. For help on commands, type 'help'. /> backstores/block create name=disk1 write_back=false \ dev=/dev/disk/by-id/dm-name-36005076306ffc7630000000000002211 Created block storage object disk1 using /dev/disk/by-id/dm-name-36005076306ffc7630000000000002211. /> vhost/ create Created target naa.5001405df3e54061. Created TPG 1. /> vhost/naa.5001405df3e54061/tpg1/luns create /backstores/block/disk1 Created LUN 0. /> exit Host Filesystem Example: # ls /sys/kernel/config/target/vhost/ discovery_auth naa.5001405df3e54061 version # ls /sys/kernel/config/target/vhost/naa.5001405df3e54061/tpgt_1/lun/ lun_0 QEMU Example (snippet): -device vhost-scsi-ccw,wwpn=naa.5001405df3e54061,devno=fe.0.1000 Libvirt Example (snippet): <hostdev mode='subsystem' type='scsi_host'> <source protocol='vhost' wwpn='naa.5001405df3e54061'/> <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x1000'/> </hostdev> Guest Viewpoint: # lsscsi [1:0:1:0] disk LIO-ORG disk0 4.0 /dev/sda # dmesg | grep 1: [ 6.065735] scsi host1: Virtio SCSI HBA [ 6.093892] scsi 1:0:1:0: Direct-Access LIO-ORG disk0 4.0 PQ: 0 ANSI: 5 [ 6.313615] sd 1:0:1:0: Attached scsi generic sg0 type 0 [ 6.314981] sd 1:0:1:0: [sda] 29360128 512-byte logical blocks: (15.0 GB/14.0 GiB) [ 6.317290] sd 1:0:1:0: [sda] Write Protect is off [ 6.317566] sd 1:0:1:0: [sda] Mode Sense: 43 00 10 08 [ 6.317853] sd 1:0:1:0: [sda] Write cache: enabled, read cache: enabled, supports DPO and FUA [ 6.352722] sd 1:0:1:0: [sda] Attached SCSI disk Changelog: v4: - Rebase - Rebased to current master (21 November) - s/virDomainPCIAddressEnsureAddr/qemuDomainEnsurePCIAddress/ (per commit abb7a4bd) - Renaming (apologies if this list is off slightly from the code) - Per comments in v3.2, some renaming has been performed: -- virDomainHostdevSubsysHostProtocol => virDomainHostdevSubsysSCSIHostProtocol -- VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_HOST => VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST -- VIR_DOMAIN_HOSTDEV_SUBSYS_HOST_PROTOCOL_TYPE_ => VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_ -- virDomainHostdevSubsysHost => virDomainHostdevSubsysSCSIVHost -- virDomainHostdevSubsysHost host; => virDomainHostdevSubsysSCSIVHost scsi_host; -- src/util/virhost.[ch] => src/util/virscsivhost.[ch] -- virHost... => virSCSIVHost... -- activeHostHostdevs => activeSCSIVHostHostdevs -- qemuBuildHostHostdevDevStr => qemuBuildSCSIVHostHostdevDevStr -- qemuSetupHostHostDeviceCgroup => qemuSetupHostSCSIVHostDeviceCgroup - Comments - Checked for a guest address tag that is of type PCI or CCW (it is optional, and should be calculated automatically) - Removed the array of "used by" information in hostdev utilities, since devices will not be shared - Fixed the existing tests to properly check for an address - Added a set of CCW tests in addition to the existing PCI ones - Removed protocol check in PrimeVirtioDeviceAddresses - Things *NOT* done (later?) from v2 feedback - Investigation/tie-in with virsh nodedev-list stuff - Implementation of 'num_queues', 'max_sectors', and 'cmd_per_lun' (Need to research these in the virtio space, before figuring out how to apply to vhost-scsi) - Dropping the "naa." prefix of wwn - Split the "tests" patch into earlier patches - Other v3.2: https://www.redhat.com/archives/libvir-list/2016-November/msg00454.html v3.1: https://www.redhat.com/archives/libvir-list/2016-October/msg01324.html v3: https://www.redhat.com/archives/libvir-list/2016-October/msg01201.html v2.1: https://www.redhat.com/archives/libvir-list/2016-September/msg00148.html v2: https://www.redhat.com/archives/libvir-list/2016-August/msg01028.html v1: https://www.redhat.com/archives/libvir-list/2016-July/msg01004.html [1] http://www.redhat.com/archives/libvir-list/2014-July/msg01235.html [2] http://www.redhat.com/archives/libvir-list/2014-July/msg01390.html Eric Farman (9): qemu: Introduce vhost-scsi capability Introduce framework for a hostdev SCSI_host subsystem type util: Management routines for scsi_host devices qemu: Add vhost-scsi string for -device parameter qemu: Allow hotplug of vhost-scsi device conf: Wire up the vhost-scsi connection from/to XML security: Include vhost-scsi in security labels tests: Introduce basic vhost-scsi tests docs: Add vhost-scsi docs/formatdomain.html.in | 24 ++ docs/schemas/domaincommon.rng | 23 ++ po/POTFILES.in | 1 + src/Makefile.am | 1 + src/conf/domain_audit.c | 7 + src/conf/domain_conf.c | 101 +++++++- src/conf/domain_conf.h | 18 ++ src/libvirt_private.syms | 18 ++ src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_cgroup.c | 39 +++ src/qemu/qemu_command.c | 80 ++++++ src/qemu/qemu_command.h | 5 + src/qemu/qemu_domain_address.c | 14 +- src/qemu/qemu_hostdev.c | 41 +++ src/qemu/qemu_hostdev.h | 8 + src/qemu/qemu_hotplug.c | 166 ++++++++++++ src/security/security_apparmor.c | 22 ++ src/security/security_dac.c | 50 ++++ src/security/security_selinux.c | 47 ++++ src/util/virhostdev.c | 163 ++++++++++++ src/util/virhostdev.h | 16 ++ src/util/virscsivhost.c | 288 +++++++++++++++++++++ src/util/virscsivhost.h | 65 +++++ tests/domaincapsschemadata/full.xml | 1 + tests/qemucapabilitiesdata/caps_1.5.3.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_1.6.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_1.7.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.1.1.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml | 1 + .../caps_2.6.0-gicv2.aarch64.xml | 1 + .../caps_2.6.0-gicv3.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml | 1 + tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml | 1 + .../qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.args | 23 ++ .../qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.xml | 34 +++ .../qemuxml2argv-hostdev-scsi-vhost-scsi-pci.args | 24 ++ .../qemuxml2argv-hostdev-scsi-vhost-scsi-pci.xml | 42 +++ tests/qemuxml2argvmock.c | 9 + tests/qemuxml2argvtest.c | 6 + .../qemuxml2xmlout-hostdev-scsi-vhost-scsi-ccw.xml | 1 + .../qemuxml2xmlout-hostdev-scsi-vhost-scsi-pci.xml | 1 + tests/qemuxml2xmltest.c | 6 + 45 files changed, 1355 insertions(+), 3 deletions(-) create mode 100644 src/util/virscsivhost.c create mode 100644 src/util/virscsivhost.h create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.xml create mode 120000 tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-ccw.xml create mode 120000 tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-pci.xml -- 1.9.1

Do all the stuff for the vhost-scsi capability in QEMU, so it's in place for our checks later. Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> Reviewed-by: Boris Fiuczynski <fiuczy@linux.vnet.ibm.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_1.5.3.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_1.6.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_1.7.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.1.1.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml | 1 + tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml | 1 + 13 files changed, 14 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index cfd090c..f9e39a3 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -352,6 +352,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "ivshmem-doorbell", /* 240 */ "query-qmp-schema", "gluster.debug_level", + "vhost-scsi", ); @@ -1596,6 +1597,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "intel-iommu", QEMU_CAPS_DEVICE_INTEL_IOMMU }, { "ivshmem-plain", QEMU_CAPS_DEVICE_IVSHMEM_PLAIN }, { "ivshmem-doorbell", QEMU_CAPS_DEVICE_IVSHMEM_DOORBELL }, + { "vhost-scsi", QEMU_CAPS_DEVICE_VHOST_SCSI }, }; static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioBalloon[] = { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 9163572..5255815 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -387,6 +387,7 @@ typedef enum { QEMU_CAPS_DEVICE_IVSHMEM_DOORBELL, /* -device ivshmem-doorbell */ QEMU_CAPS_QUERY_QMP_SCHEMA, /* query-qmp-schema command */ QEMU_CAPS_GLUSTER_DEBUG_LEVEL, /* -drive gluster.debug_level={0..9} */ + QEMU_CAPS_DEVICE_VHOST_SCSI, /* -device vhost-scsi-{ccw,pci} */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_1.5.3.x86_64.xml b/tests/qemucapabilitiesdata/caps_1.5.3.x86_64.xml index cc4ffef..2931418 100644 --- a/tests/qemucapabilitiesdata/caps_1.5.3.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_1.5.3.x86_64.xml @@ -139,6 +139,7 @@ <flag name='device-tray-moved-event'/> <flag name='nec-usb-xhci-ports'/> <flag name='display'/> + <flag name='vhost-scsi'/> <version>1005003</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_1.6.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_1.6.0.x86_64.xml index 8e0e697..15f2075 100644 --- a/tests/qemucapabilitiesdata/caps_1.6.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_1.6.0.x86_64.xml @@ -144,6 +144,7 @@ <flag name='device-tray-moved-event'/> <flag name='nec-usb-xhci-ports'/> <flag name='display'/> + <flag name='vhost-scsi'/> <version>1006000</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_1.7.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_1.7.0.x86_64.xml index 40acf62..0726443 100644 --- a/tests/qemucapabilitiesdata/caps_1.7.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_1.7.0.x86_64.xml @@ -146,6 +146,7 @@ <flag name='device-tray-moved-event'/> <flag name='nec-usb-xhci-ports'/> <flag name='display'/> + <flag name='vhost-scsi'/> <version>1007000</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_2.1.1.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.1.1.x86_64.xml index a8a79af..498e2d0 100644 --- a/tests/qemucapabilitiesdata/caps_2.1.1.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.1.1.x86_64.xml @@ -161,6 +161,7 @@ <flag name='name-guest'/> <flag name='drive-detect-zeroes'/> <flag name='display'/> + <flag name='vhost-scsi'/> <version>2001001</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml index 3162758..18594e6 100644 --- a/tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml @@ -181,6 +181,7 @@ <flag name='virtio-pci-disable-legacy'/> <flag name='machine-iommu'/> <flag name='virtio-vga'/> + <flag name='vhost-scsi'/> <version>2004000</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml index bea01c7..033894a 100644 --- a/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml @@ -187,6 +187,7 @@ <flag name='machine-iommu'/> <flag name='virtio-vga'/> <flag name='query-qmp-schema'/> + <flag name='vhost-scsi'/> <version>2005000</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml b/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml index b283444..24fb584 100644 --- a/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml @@ -162,6 +162,7 @@ <flag name='ivshmem-plain'/> <flag name='ivshmem-doorbell'/> <flag name='query-qmp-schema'/> + <flag name='vhost-scsi'/> <version>2006000</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml b/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml index 612a747..ecfe07e 100644 --- a/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml @@ -162,6 +162,7 @@ <flag name='ivshmem-plain'/> <flag name='ivshmem-doorbell'/> <flag name='query-qmp-schema'/> + <flag name='vhost-scsi'/> <version>2005094</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml b/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml index 5f22ed5..5fbc9af 100644 --- a/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml +++ b/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml @@ -159,6 +159,7 @@ <flag name='ivshmem-plain'/> <flag name='ivshmem-doorbell'/> <flag name='query-qmp-schema'/> + <flag name='vhost-scsi'/> <version>2006000</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml index e9bd5bb..2525d2d 100644 --- a/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml @@ -196,6 +196,7 @@ <flag name='ivshmem-plain'/> <flag name='ivshmem-doorbell'/> <flag name='query-qmp-schema'/> + <flag name='vhost-scsi'/> <version>2006000</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml index b6e34b0..f2a305f 100644 --- a/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml @@ -198,6 +198,7 @@ <flag name='ivshmem-doorbell'/> <flag name='query-qmp-schema'/> <flag name='gluster.debug_level'/> + <flag name='vhost-scsi'/> <version>2007000</version> <kvmVersion>0</kvmVersion> <package> (v2.7.0)</package> -- 1.9.1

On 11/21/2016 10:58 PM, Eric Farman wrote:
Do all the stuff for the vhost-scsi capability in QEMU, so it's in place for our checks later.
Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> Reviewed-by: Boris Fiuczynski <fiuczy@linux.vnet.ibm.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_1.5.3.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_1.6.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_1.7.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.1.1.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml | 1 + tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml | 1 + 13 files changed, 14 insertions(+)
ACK, John

We already have a "scsi" hostdev subsys 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 subsys type that will carry this. Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> --- src/conf/domain_conf.c | 11 ++++++++++- src/conf/domain_conf.h | 18 ++++++++++++++++++ src/qemu/qemu_cgroup.c | 7 +++++++ src/qemu/qemu_hotplug.c | 2 ++ src/security/security_apparmor.c | 4 ++++ src/security/security_dac.c | 8 ++++++++ src/security/security_selinux.c | 8 ++++++++ tests/domaincapsschemadata/full.xml | 1 + 8 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 6e008e2..3a4123d 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -647,7 +647,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, @@ -661,6 +662,11 @@ VIR_ENUM_IMPL(virDomainHostdevSubsysSCSIProtocol, "adapter", "iscsi") +VIR_ENUM_IMPL(virDomainHostdevSubsysSCSIHostProtocol, + VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_LAST, + "none", + "vhost") + VIR_ENUM_IMPL(virDomainHostdevCaps, VIR_DOMAIN_HOSTDEV_CAPS_TYPE_LAST, "storage", "misc", @@ -13016,6 +13022,7 @@ virDomainHostdevDefParseXML(virDomainXMLOptionPtr xmlopt, if (virXPathBoolean("boolean(./shareable)", ctxt)) def->shareable = true; break; + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: break; @@ -13899,6 +13906,8 @@ virDomainHostdevMatchSubsys(virDomainHostdevDefPtr a, return virDomainHostdevMatchSubsysSCSIiSCSI(a, b); else return virDomainHostdevMatchSubsysSCSIHost(a, b); + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: + /* Fall through for now */ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: return 0; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 541b600..3dfd780 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_SCSI_HOST, VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST } virDomainHostdevSubsysType; @@ -368,6 +369,22 @@ struct _virDomainHostdevSubsysSCSI { } u; }; +typedef enum { + VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_NONE, + VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_VHOST, + + VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_LAST, +} virDomainHostdevSubsysSCSIHostProtocolType; + +VIR_ENUM_DECL(virDomainHostdevSubsysSCSIHostProtocol) + +typedef struct _virDomainHostdevSubsysSCSIVHost virDomainHostdevSubsysSCSIVHost; +typedef virDomainHostdevSubsysSCSIVHost *virDomainHostdevSubsysSCSIVHostPtr; +struct _virDomainHostdevSubsysSCSIVHost { + int protocol; /* enum virDomainHostdevSubsysSCSIHostProtocolType */ + char *wwpn; +}; + typedef struct _virDomainHostdevSubsys virDomainHostdevSubsys; typedef virDomainHostdevSubsys *virDomainHostdevSubsysPtr; struct _virDomainHostdevSubsys { @@ -376,6 +393,7 @@ struct _virDomainHostdevSubsys { virDomainHostdevSubsysUSB usb; virDomainHostdevSubsysPCI pci; virDomainHostdevSubsysSCSI scsi; + virDomainHostdevSubsysSCSIVHost scsi_host; } u; }; diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index 1443f7e..5c26086 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -376,6 +376,10 @@ qemuSetupHostdevCgroup(virDomainObjPtr vm, break; } + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: { + break; + } + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: break; } @@ -440,6 +444,9 @@ qemuTeardownHostdevCgroup(virDomainObjPtr vm, case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: /* nothing to tear down for SCSI */ break; + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: + /* nothing to tear down for scsi_host */ + break; case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: break; } diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 6b3a068..0508c67 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -3645,6 +3645,8 @@ qemuDomainRemoveHostDevice(virQEMUDriverPtr driver, case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: qemuDomainRemoveSCSIHostDevice(driver, vm, hostdev); break; + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: + break; case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: break; } diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c index beddf6d..19085ec 100644 --- a/src/security/security_apparmor.c +++ b/src/security/security_apparmor.c @@ -909,6 +909,10 @@ AppArmorSetSecurityHostdevLabel(virSecurityManagerPtr mgr, break; } + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: { + /* Fall through for now */ + } + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: ret = 0; break; diff --git a/src/security/security_dac.c b/src/security/security_dac.c index fd74e8b..2803962 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -676,6 +676,10 @@ virSecurityDACSetHostdevLabel(virSecurityManagerPtr mgr, break; } + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: { + /* Fall through for now */ + } + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: ret = 0; break; @@ -805,6 +809,10 @@ virSecurityDACRestoreHostdevLabel(virSecurityManagerPtr mgr, break; } + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: { + /* Fall through for now */ + } + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: ret = 0; break; diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 89c93dc..9870b41 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -1498,6 +1498,10 @@ virSecuritySELinuxSetHostdevSubsysLabel(virSecurityManagerPtr mgr, break; } + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: { + /* Fall through for now */ + } + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: ret = 0; break; @@ -1700,6 +1704,10 @@ virSecuritySELinuxRestoreHostdevSubsysLabel(virSecurityManagerPtr mgr, break; } + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: { + /* Fall through for now */ + } + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: ret = 0; break; diff --git a/tests/domaincapsschemadata/full.xml b/tests/domaincapsschemadata/full.xml index eaf6eb6..6abd499 100644 --- a/tests/domaincapsschemadata/full.xml +++ b/tests/domaincapsschemadata/full.xml @@ -87,6 +87,7 @@ <value>usb</value> <value>pci</value> <value>scsi</value> + <value>scsi_host</value> </enum> <enum name='capsType'> <value>storage</value> -- 1.9.1

On 11/21/2016 10:58 PM, Eric Farman wrote:
We already have a "scsi" hostdev subsys 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 subsys type that will carry this.
Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> --- src/conf/domain_conf.c | 11 ++++++++++- src/conf/domain_conf.h | 18 ++++++++++++++++++ src/qemu/qemu_cgroup.c | 7 +++++++ src/qemu/qemu_hotplug.c | 2 ++ src/security/security_apparmor.c | 4 ++++ src/security/security_dac.c | 8 ++++++++ src/security/security_selinux.c | 8 ++++++++ tests/domaincapsschemadata/full.xml | 1 + 8 files changed, 58 insertions(+), 1 deletion(-)
ACK John

For a new hostdev type='scsi_host' we have a number of required functions for managing, adding, and removing the host device to/from guests. Provide the basic infrastructure for these tasks. The name "SCSIVHost" (and its variants) is chosen to avoid conflicts with existing code named "SCSIHost" to refer to a hostdev type='scsi' protcol='none'. Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> --- po/POTFILES.in | 1 + src/Makefile.am | 1 + src/libvirt_private.syms | 18 +++ src/util/virhostdev.c | 163 +++++++++++++++++++++++++++ src/util/virhostdev.h | 16 +++ src/util/virscsivhost.c | 288 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/virscsivhost.h | 65 +++++++++++ tests/qemuxml2argvmock.c | 9 ++ 8 files changed, 561 insertions(+) create mode 100644 src/util/virscsivhost.c create mode 100644 src/util/virscsivhost.h diff --git a/po/POTFILES.in b/po/POTFILES.in index 25867ae..bdff679 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -237,6 +237,7 @@ src/util/virqemu.c src/util/virrandom.c src/util/virrotatingfile.c src/util/virscsi.c +src/util/virscsivhost.c src/util/virsecret.c src/util/virsexpr.c src/util/virsocketaddr.c diff --git a/src/Makefile.am b/src/Makefile.am index aaba9e6..a0e5e92 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -163,6 +163,7 @@ UTIL_SOURCES = \ util/virrandom.h util/virrandom.c \ util/virrotatingfile.h util/virrotatingfile.c \ util/virscsi.c util/virscsi.h \ + util/virscsivhost.c util/virscsivhost.h \ util/virseclabel.c util/virseclabel.h \ util/virsecret.c util/virsecret.h \ util/virsexpr.c util/virsexpr.h \ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index baff82b..46b4e87 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1684,10 +1684,12 @@ virHostdevPCINodeDeviceReset; virHostdevPrepareDomainDevices; virHostdevPreparePCIDevices; virHostdevPrepareSCSIDevices; +virHostdevPrepareSCSIVHostDevices; virHostdevPrepareUSBDevices; virHostdevReAttachDomainDevices; virHostdevReAttachPCIDevices; virHostdevReAttachSCSIDevices; +virHostdevReAttachSCSIVHostDevices; virHostdevReAttachUSBDevices; virHostdevUpdateActiveDomainDevices; virHostdevUpdateActivePCIDevices; @@ -2305,6 +2307,22 @@ virSCSIDeviceNew; virSCSIDeviceSetUsedBy; +# util/virscsivhost.h +virSCSIVHostDeviceFileIterate; +virSCSIVHostDeviceFree; +virSCSIVHostDeviceGetName; +virSCSIVHostDeviceListAdd; +virSCSIVHostDeviceListCount; +virSCSIVHostDeviceListDel; +virSCSIVHostDeviceListFind; +virSCSIVHostDeviceListGet; +virSCSIVHostDeviceListNew; +virSCSIVHostDeviceListSteal; +virSCSIVHostDeviceNew; +virSCSIVHostDeviceSetUsedBy; +virSCSIVHostOpenVhostSCSI; + + # util/virseclabel.h virSecurityDeviceLabelDefFree; virSecurityDeviceLabelDefNew; diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index 9c2262e..ca4c339 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -146,6 +146,7 @@ virHostdevManagerDispose(void *obj) virObjectUnref(hostdevMgr->inactivePCIHostdevs); virObjectUnref(hostdevMgr->activeUSBHostdevs); virObjectUnref(hostdevMgr->activeSCSIHostdevs); + virObjectUnref(hostdevMgr->activeSCSIVHostHostdevs); VIR_FREE(hostdevMgr->stateDir); } @@ -170,6 +171,9 @@ virHostdevManagerNew(void) if (!(hostdevMgr->activeSCSIHostdevs = virSCSIDeviceListNew())) goto error; + if (!(hostdevMgr->activeSCSIVHostHostdevs = virSCSIVHostDeviceListNew())) + goto error; + if (privileged) { if (VIR_STRDUP(hostdevMgr->stateDir, HOSTDEV_STATE_DIR) < 0) goto error; @@ -1472,6 +1476,102 @@ virHostdevPrepareSCSIDevices(virHostdevManagerPtr mgr, return -1; } +int +virHostdevPrepareSCSIVHostDevices(virHostdevManagerPtr mgr, + const char *drv_name, + const char *dom_name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) +{ + size_t i, j; + int count; + virSCSIVHostDeviceListPtr list; + virSCSIVHostDevicePtr host, tmp; + + if (!nhostdevs) + return 0; + + /* To prevent situation where scsi_host device is assigned to two domains + * we need to keep a list of currently assigned scsi_host devices. + * This is done in several loops which cannot be joined into one big + * loop. See virHostdevPreparePCIDevices() + */ + if (!(list = virSCSIVHostDeviceListNew())) + goto cleanup; + + /* Loop 1: build temporary list */ + for (i = 0; i < nhostdevs; i++) { + virDomainHostdevDefPtr hostdev = hostdevs[i]; + virDomainHostdevSubsysSCSIVHostPtr hostsrc = &hostdev->source.subsys.u.scsi_host; + + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || + hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST) + continue; + + if (hostsrc->protocol != VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_VHOST) + continue; /* Not supported */ + + if (!(host = virSCSIVHostDeviceNew(hostsrc->wwpn))) + goto cleanup; + + if (virSCSIVHostDeviceListAdd(list, host) < 0) { + virSCSIVHostDeviceFree(host); + goto cleanup; + } + } + + /* Loop 2: Mark devices in temporary list as used by @name + * and add them to driver list. However, if something goes + * wrong, perform rollback. + */ + virObjectLock(mgr->activeSCSIVHostHostdevs); + count = virSCSIVHostDeviceListCount(list); + + for (i = 0; i < count; i++) { + host = virSCSIVHostDeviceListGet(list, i); + if ((tmp = virSCSIVHostDeviceListFind(mgr->activeSCSIVHostHostdevs, + host))) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("SCSI_host device %s is already in use by " + "another domain"), + virSCSIVHostDeviceGetName(tmp)); + goto error; + } else { + if (virSCSIVHostDeviceSetUsedBy(host, drv_name, dom_name) < 0) + goto error; + + VIR_DEBUG("Adding %s to activeSCSIVHostHostdevs", + virSCSIVHostDeviceGetName(host)); + + if (virSCSIVHostDeviceListAdd(mgr->activeSCSIVHostHostdevs, host) < 0) + goto error; + } + } + + virObjectUnlock(mgr->activeSCSIVHostHostdevs); + + /* Loop 3: Temporary list was successfully merged with + * driver list, so steal all items to avoid freeing them + * when freeing temporary list. + */ + while (virSCSIVHostDeviceListCount(list) > 0) { + tmp = virSCSIVHostDeviceListGet(list, 0); + virSCSIVHostDeviceListSteal(list, tmp); + } + + virObjectUnref(list); + return 0; + error: + for (j = 0; j < i; j++) { + tmp = virSCSIVHostDeviceListGet(list, i); + virSCSIVHostDeviceListSteal(mgr->activeSCSIVHostHostdevs, tmp); + } + virObjectUnlock(mgr->activeSCSIVHostHostdevs); + cleanup: + virObjectUnref(list); + return -1; +} + void virHostdevReAttachUSBDevices(virHostdevManagerPtr mgr, const char *drv_name, @@ -1604,6 +1704,69 @@ virHostdevReAttachSCSIDevices(virHostdevManagerPtr mgr, virObjectUnlock(mgr->activeSCSIHostdevs); } +void +virHostdevReAttachSCSIVHostDevices(virHostdevManagerPtr mgr, + const char *drv_name, + const char *dom_name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) +{ + size_t i; + virSCSIVHostDevicePtr host, tmp; + + + if (!nhostdevs) + return; + + virObjectLock(mgr->activeSCSIVHostHostdevs); + for (i = 0; i < nhostdevs; i++) { + virDomainHostdevDefPtr hostdev = hostdevs[i]; + virDomainHostdevSubsysSCSIVHostPtr hostsrc = &hostdev->source.subsys.u.scsi_host; + const char *usedby_drvname; + const char *usedby_domname; + + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || + hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST) + continue; + + if (hostsrc->protocol != VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_VHOST) + continue; /* Not supported */ + + if (!(host = virSCSIVHostDeviceNew(hostsrc->wwpn))) { + VIR_WARN("Unable to reattach SCSI_host device %s on domain %s", + hostsrc->wwpn, dom_name); + virObjectUnlock(mgr->activeSCSIVHostHostdevs); + return; + } + + /* Only delete the devices which are marked as being used by @name, + * because qemuProcessStart could fail half way through. */ + + if (!(tmp = virSCSIVHostDeviceListFind(mgr->activeSCSIVHostHostdevs, + host))) { + VIR_WARN("Unable to find device %s " + "in list of active SCSI_host devices", + hostsrc->wwpn); + virSCSIVHostDeviceFree(host); + virObjectUnlock(mgr->activeSCSIVHostHostdevs); + return; + } + + virSCSIVHostDeviceGetUsedBy(tmp, &usedby_drvname, &usedby_domname); + + if (STREQ_NULLABLE(drv_name, usedby_drvname) && + STREQ_NULLABLE(dom_name, usedby_domname)) { + VIR_DEBUG("Removing %s dom=%s from activeSCSIVHostHostdevs", + hostsrc->wwpn, dom_name); + + virSCSIVHostDeviceListDel(mgr->activeSCSIVHostHostdevs, tmp); + } + + virSCSIVHostDeviceFree(host); + } + virObjectUnlock(mgr->activeSCSIVHostHostdevs); +} + int virHostdevPCINodeDeviceDetach(virHostdevManagerPtr mgr, virPCIDevicePtr pci) diff --git a/src/util/virhostdev.h b/src/util/virhostdev.h index f2f51bd..1330cbc 100644 --- a/src/util/virhostdev.h +++ b/src/util/virhostdev.h @@ -30,6 +30,7 @@ # include "virpci.h" # include "virusb.h" # include "virscsi.h" +# include "virscsivhost.h" # include "domain_conf.h" typedef enum { @@ -53,6 +54,7 @@ struct _virHostdevManager { virPCIDeviceListPtr inactivePCIHostdevs; virUSBDeviceListPtr activeUSBHostdevs; virSCSIDeviceListPtr activeSCSIHostdevs; + virSCSIVHostDeviceListPtr activeSCSIVHostHostdevs; }; virHostdevManagerPtr virHostdevManagerGetDefault(void); @@ -87,6 +89,13 @@ virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr, virDomainHostdevDefPtr *hostdevs, int nhostdevs) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); +int +virHostdevPrepareSCSIVHostDevices(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, + const char *dom_name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); void virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr, const char *drv_name, @@ -109,6 +118,13 @@ virHostdevReAttachSCSIDevices(virHostdevManagerPtr hostdev_mgr, virDomainHostdevDefPtr *hostdevs, int nhostdevs) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); +void +virHostdevReAttachSCSIVHostDevices(virHostdevManagerPtr hostdev_mgr, + const char *drv_name, + const char *dom_name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); int virHostdevUpdateActivePCIDevices(virHostdevManagerPtr mgr, virDomainHostdevDefPtr *hostdevs, diff --git a/src/util/virscsivhost.c b/src/util/virscsivhost.c new file mode 100644 index 0000000..9d18b6e --- /dev/null +++ b/src/util/virscsivhost.c @@ -0,0 +1,288 @@ +/* + * virscsivhost.c: helper APIs for managing scsi_host devices + * + * Copyright (C) 2016 IBM Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Authors: + * Eric Farman <farman@linux.vnet.ibm.com> + */ + +#include <config.h> +#include <fcntl.h> + +#include "virscsivhost.h" +#include "virlog.h" +#include "viralloc.h" +#include "virerror.h" +#include "virfile.h" +#include "virstring.h" + +VIR_LOG_INIT("util.scsihost"); + +#define SYSFS_VHOST_SCSI_DEVICES "/sys/kernel/config/target/vhost/" +#define VHOST_SCSI_DEVICE "/dev/vhost-scsi" + +struct _virSCSIVHostDevice { + char *name; /* naa.<wwn> */ + char *path; + char *used_by_drvname; + char *used_by_domname; +}; + +struct _virSCSIVHostDeviceList { + virObjectLockable parent; + size_t count; + virSCSIVHostDevicePtr *devs; +}; + +static virClassPtr virSCSIVHostDeviceListClass; + +static void +virSCSIVHostDeviceListDispose(void *obj) +{ + virSCSIVHostDeviceListPtr list = obj; + size_t i; + + for (i = 0; i < list->count; i++) + virSCSIVHostDeviceFree(list->devs[i]); + + VIR_FREE(list->devs); +} + + +static int +virSCSIVHostOnceInit(void) +{ + if (!(virSCSIVHostDeviceListClass = virClassNew(virClassForObjectLockable(), + "virSCSIVHostDeviceList", + sizeof(virSCSIVHostDeviceList), + virSCSIVHostDeviceListDispose))) + return -1; + + return 0; +} + + +VIR_ONCE_GLOBAL_INIT(virSCSIVHost) + +/* For virReportOOMError() and virReportSystemError() */ +#define VIR_FROM_THIS VIR_FROM_NONE + + +int +virSCSIVHostOpenVhostSCSI(int *vhostfd) +{ + if (!virFileExists(VHOST_SCSI_DEVICE)) + goto error; + + *vhostfd = open(VHOST_SCSI_DEVICE, O_RDWR); + + if (*vhostfd < 0) { + virReportSystemError(errno, _("Failed to open %s"), VHOST_SCSI_DEVICE); + goto error; + } + + return 0; + + error: + VIR_FORCE_CLOSE(*vhostfd); + + return -1; +} + + +void +virSCSIVHostDeviceListDel(virSCSIVHostDeviceListPtr list, + virSCSIVHostDevicePtr dev) +{ + virSCSIVHostDevicePtr tmp = virSCSIVHostDeviceListSteal(list, dev); + virSCSIVHostDeviceFree(tmp); +} + + +static int +virSCSIVHostDeviceListFindIndex(virSCSIVHostDeviceListPtr list, + virSCSIVHostDevicePtr dev) +{ + size_t i; + + for (i = 0; i < list->count; i++) { + virSCSIVHostDevicePtr other = list->devs[i]; + if (STREQ_NULLABLE(other->name, dev->name)) + return i; + } + return -1; +} + + +virSCSIVHostDevicePtr +virSCSIVHostDeviceListGet(virSCSIVHostDeviceListPtr list, int idx) +{ + if (idx >= list->count || idx < 0) + return NULL; + + return list->devs[idx]; +} + + +size_t +virSCSIVHostDeviceListCount(virSCSIVHostDeviceListPtr list) +{ + return list->count; +} + + +virSCSIVHostDevicePtr +virSCSIVHostDeviceListSteal(virSCSIVHostDeviceListPtr list, + virSCSIVHostDevicePtr dev) +{ + virSCSIVHostDevicePtr ret = NULL; + size_t i; + + for (i = 0; i < list->count; i++) { + if (STREQ_NULLABLE(list->devs[i]->name, dev->name)) { + ret = list->devs[i]; + VIR_DELETE_ELEMENT(list->devs, i, list->count); + break; + } + } + + return ret; +} + + +virSCSIVHostDevicePtr +virSCSIVHostDeviceListFind(virSCSIVHostDeviceListPtr list, + virSCSIVHostDevicePtr dev) +{ + int idx; + + if ((idx = virSCSIVHostDeviceListFindIndex(list, dev)) >= 0) + return list->devs[idx]; + else + return NULL; +} + + +int +virSCSIVHostDeviceListAdd(virSCSIVHostDeviceListPtr list, + virSCSIVHostDevicePtr dev) +{ + if (virSCSIVHostDeviceListFind(list, dev)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Device %s is already in use"), dev->name); + return -1; + } + return VIR_APPEND_ELEMENT(list->devs, list->count, dev); +} + + +virSCSIVHostDeviceListPtr +virSCSIVHostDeviceListNew(void) +{ + if (virSCSIVHostInitialize() < 0) + return NULL; + + return virObjectLockableNew(virSCSIVHostDeviceListClass); +} + + +int +virSCSIVHostDeviceSetUsedBy(virSCSIVHostDevicePtr dev, + const char *drvname, + const char *domname) +{ + VIR_FREE(dev->used_by_drvname); + VIR_FREE(dev->used_by_domname); + if (VIR_STRDUP(dev->used_by_drvname, drvname) < 0) + return -1; + if (VIR_STRDUP(dev->used_by_domname, domname) < 0) + return -1; + + return 0; +} + + +void +virSCSIVHostDeviceGetUsedBy(virSCSIVHostDevicePtr dev, + const char **drv_name, + const char **dom_name) +{ + *drv_name = dev->used_by_drvname; + *dom_name = dev->used_by_domname; + } + + +int +virSCSIVHostDeviceFileIterate(virSCSIVHostDevicePtr dev, + virSCSIVHostDeviceFileActor actor, + void *opaque) +{ + return (actor)(dev, dev->path, opaque); +} + + +const char * +virSCSIVHostDeviceGetName(virSCSIVHostDevicePtr dev) +{ + return dev->name; +} + + +virSCSIVHostDevicePtr +virSCSIVHostDeviceNew(const char *name) +{ + virSCSIVHostDevicePtr dev; + + if (VIR_ALLOC(dev) < 0) + return NULL; + + if (VIR_STRDUP(dev->name, name) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("dev->name buffer overflow: %s"), + name); + goto error; + } + + if (virAsprintf(&dev->path, "%s/%s", + SYSFS_VHOST_SCSI_DEVICES, name) < 0) + goto cleanup; + + VIR_DEBUG("%s: initialized", dev->name); + + cleanup: + return dev; + + error: + virSCSIVHostDeviceFree(dev); + dev = NULL; + goto cleanup; +} + + +void +virSCSIVHostDeviceFree(virSCSIVHostDevicePtr dev) +{ + if (!dev) + return; + VIR_DEBUG("%s: freeing", dev->name); + VIR_FREE(dev->name); + VIR_FREE(dev->path); + VIR_FREE(dev->used_by_drvname); + VIR_FREE(dev->used_by_domname); + VIR_FREE(dev); +} diff --git a/src/util/virscsivhost.h b/src/util/virscsivhost.h new file mode 100644 index 0000000..1a52acf --- /dev/null +++ b/src/util/virscsivhost.h @@ -0,0 +1,65 @@ +/* + * virscsivhost.h: helper APIs for managing host scsi_host devices + * + * Copyright (C) 2016 IBM Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Authors: + * Eric Farman <farman@linux.vnet.ibm.com> + */ + +#ifndef __VIR_SCSIHOST_H__ +# define __VIR_SCSIHOST_H__ + +# include "internal.h" +# include "virobject.h" +# include "virutil.h" + +typedef struct _virSCSIVHostDevice virSCSIVHostDevice; +typedef virSCSIVHostDevice *virSCSIVHostDevicePtr; +typedef struct _virSCSIVHostDeviceList virSCSIVHostDeviceList; +typedef virSCSIVHostDeviceList *virSCSIVHostDeviceListPtr; + +typedef int (*virSCSIVHostDeviceFileActor)(virSCSIVHostDevicePtr dev, + const char *name, void *opaque); + +int virSCSIVHostDeviceFileIterate(virSCSIVHostDevicePtr dev, + virSCSIVHostDeviceFileActor actor, + void *opaque); +const char *virSCSIVHostDeviceGetName(virSCSIVHostDevicePtr dev); +virSCSIVHostDevicePtr virSCSIVHostDeviceListGet(virSCSIVHostDeviceListPtr list, + int idx); +size_t virSCSIVHostDeviceListCount(virSCSIVHostDeviceListPtr list); +virSCSIVHostDevicePtr virSCSIVHostDeviceListSteal(virSCSIVHostDeviceListPtr list, + virSCSIVHostDevicePtr dev); +virSCSIVHostDevicePtr virSCSIVHostDeviceListFind(virSCSIVHostDeviceListPtr list, + virSCSIVHostDevicePtr dev); +int virSCSIVHostDeviceListAdd(virSCSIVHostDeviceListPtr list, + virSCSIVHostDevicePtr dev); +void virSCSIVHostDeviceListDel(virSCSIVHostDeviceListPtr list, + virSCSIVHostDevicePtr dev); +virSCSIVHostDeviceListPtr virSCSIVHostDeviceListNew(void); +virSCSIVHostDevicePtr virSCSIVHostDeviceNew(const char *name); +int virSCSIVHostDeviceSetUsedBy(virSCSIVHostDevicePtr dev, + const char *drvname, + const char *domname); +void virSCSIVHostDeviceGetUsedBy(virSCSIVHostDevicePtr dev, + const char **drv_name, + const char **dom_name); +void virSCSIVHostDeviceFree(virSCSIVHostDevicePtr dev); +int virSCSIVHostOpenVhostSCSI(int *vhostfd); + +#endif /* __VIR_SCSIHOST_H__ */ diff --git a/tests/qemuxml2argvmock.c b/tests/qemuxml2argvmock.c index 78a224b..c501b59 100644 --- a/tests/qemuxml2argvmock.c +++ b/tests/qemuxml2argvmock.c @@ -31,6 +31,7 @@ #include "virnuma.h" #include "virrandom.h" #include "virscsi.h" +#include "virscsivhost.h" #include "virstring.h" #include "virtpm.h" #include "virutil.h" @@ -107,6 +108,14 @@ virSCSIDeviceGetSgName(const char *sysfs_prefix ATTRIBUTE_UNUSED, } int +virSCSIVHostOpenVhostSCSI(int *vhostfd) +{ + *vhostfd = STDERR_FILENO + 1; + + return 0; +} + +int virNetDevTapCreate(char **ifname, const char *tunpath ATTRIBUTE_UNUSED, int *tapfd, -- 1.9.1

[...]
+ +/* For virReportOOMError() and virReportSystemError() */ +#define VIR_FROM_THIS VIR_FROM_NONE +
Made a minor adjustment to move this above the VIR_LOG_INIT - it's just cosmetic... [...]
+virSCSIVHostDevicePtr +virSCSIVHostDeviceNew(const char *name) +{ + virSCSIVHostDevicePtr dev; + + if (VIR_ALLOC(dev) < 0) + return NULL; + + if (VIR_STRDUP(dev->name, name) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("dev->name buffer overflow: %s"), + name); + goto error; + } + + if (virAsprintf(&dev->path, "%s/%s", + SYSFS_VHOST_SCSI_DEVICES, name) < 0) + goto cleanup;
I believe this is goto error; (I can change before push) ACK John

Open /dev/vhost-scsi, and record the resulting file descriptor, so that the guest has access to the host device outside of the libvirt daemon. Pass this information, along with data parsed from the XML file, to build a device string for the qemu command line. That device string will be for either a vhost-scsi-ccw device in the case of an s390 machine, or vhost-scsi-pci for any others. Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> --- src/qemu/qemu_cgroup.c | 32 +++++++++++++++++ src/qemu/qemu_command.c | 80 ++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_command.h | 5 +++ src/qemu/qemu_domain_address.c | 14 ++++++-- src/qemu/qemu_hostdev.c | 41 ++++++++++++++++++++++ src/qemu/qemu_hostdev.h | 8 +++++ 6 files changed, 178 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index 5c26086..90f7ed4 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -277,6 +277,25 @@ qemuSetupHostSCSIDeviceCgroup(virSCSIDevicePtr dev ATTRIBUTE_UNUSED, return ret; } +static int +qemuSetupHostSCSIVHostDeviceCgroup(virSCSIVHostDevicePtr dev ATTRIBUTE_UNUSED, + const char *path, + void *opaque) +{ + virDomainObjPtr vm = opaque; + qemuDomainObjPrivatePtr priv = vm->privateData; + int ret; + + VIR_DEBUG("Process path '%s' for scsi_host device", path); + + ret = virCgroupAllowDevicePath(priv->cgroup, path, + VIR_CGROUP_DEVICE_RW, false); + + virDomainAuditCgroupPath(vm, priv->cgroup, "allow", path, "rw", ret == 0); + + return ret; +} + int qemuSetupHostdevCgroup(virDomainObjPtr vm, virDomainHostdevDefPtr dev) @@ -286,9 +305,11 @@ qemuSetupHostdevCgroup(virDomainObjPtr vm, virDomainHostdevSubsysUSBPtr usbsrc = &dev->source.subsys.u.usb; virDomainHostdevSubsysPCIPtr pcisrc = &dev->source.subsys.u.pci; virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi; + virDomainHostdevSubsysSCSIVHostPtr hostsrc = &dev->source.subsys.u.scsi_host; virPCIDevicePtr pci = NULL; virUSBDevicePtr usb = NULL; virSCSIDevicePtr scsi = NULL; + virSCSIVHostDevicePtr host = NULL; char *path = NULL; /* currently this only does something for PCI devices using vfio @@ -377,6 +398,16 @@ qemuSetupHostdevCgroup(virDomainObjPtr vm, } case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: { + if (hostsrc->protocol == + VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_VHOST) { + if (!(host = virSCSIVHostDeviceNew(hostsrc->wwpn))) + goto cleanup; + + if (virSCSIVHostDeviceFileIterate(host, + qemuSetupHostSCSIVHostDeviceCgroup, + vm) < 0) + goto cleanup; + } break; } @@ -390,6 +421,7 @@ qemuSetupHostdevCgroup(virDomainObjPtr vm, virPCIDeviceFree(pci); virUSBDeviceFree(usb); virSCSIDeviceFree(scsi); + virSCSIVHostDeviceFree(host); VIR_FREE(path); return ret; } diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 4a5fce3..5ff6a39 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4742,6 +4742,44 @@ qemuBuildSCSIiSCSIHostdevDrvStr(virDomainHostdevDefPtr dev) } char * +qemuBuildSCSIVHostHostdevDevStr(const virDomainDef *def, + virDomainHostdevDefPtr dev, + virQEMUCapsPtr qemuCaps, + char *vhostfdName) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + virDomainHostdevSubsysSCSIVHostPtr hostsrc = &dev->source.subsys.u.scsi_host; + + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VHOST_SCSI)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("This QEMU doesn't support vhost-scsi devices")); + goto cleanup; + } + + if (ARCH_IS_S390(def->os.arch)) + virBufferAddLit(&buf, "vhost-scsi-ccw"); + else + virBufferAddLit(&buf, "vhost-scsi-pci"); + + virBufferAsprintf(&buf, ",wwpn=%s,vhostfd=%s,id=%s", + hostsrc->wwpn, + vhostfdName, + dev->info->alias); + + if (qemuBuildDeviceAddressStr(&buf, def, dev->info, qemuCaps) < 0) + goto cleanup; + + if (virBufferCheckError(&buf) < 0) + goto cleanup; + + return virBufferContentAndReset(&buf); + + cleanup: + virBufferFreeAndReset(&buf); + return NULL; +} + +char * qemuBuildSCSIHostdevDrvStr(virDomainHostdevDefPtr dev) { virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -5222,6 +5260,48 @@ qemuBuildHostdevCommandLine(virCommandPtr cmd, return -1; } } + + /* SCSI_host */ + if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && + subsys->type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST) { + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_SCSI_GENERIC)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("SCSI passthrough is not supported by this " + "version of qemu")); + return -1; + } + + if (hostdev->source.subsys.u.scsi_host.protocol == + VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_VHOST) { + char *vhostfdName = NULL; + int vhostfd = -1; + + if (virSCSIVHostOpenVhostSCSI(&vhostfd) < 0) + return -1; + + if (virAsprintf(&vhostfdName, "%d", vhostfd) < 0) { + VIR_FORCE_CLOSE(vhostfd); + return -1; + } + + virCommandPassFD(cmd, vhostfd, + VIR_COMMAND_PASS_FD_CLOSE_PARENT); + + virCommandAddArg(cmd, "-device"); + if (!(devstr = qemuBuildSCSIVHostHostdevDevStr(def, + hostdev, + qemuCaps, + vhostfdName))) { + VIR_FREE(vhostfdName); + VIR_FORCE_CLOSE(vhostfd); + return -1; + } + virCommandAddArg(cmd, devstr); + + VIR_FREE(vhostfdName); + VIR_FREE(devstr); + } + } } return 0; diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index e0c84df..3bcfdc6 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -164,6 +164,11 @@ char *qemuBuildSCSIHostdevDrvStr(virDomainHostdevDefPtr dev); char *qemuBuildSCSIHostdevDevStr(const virDomainDef *def, virDomainHostdevDefPtr dev, virQEMUCapsPtr qemuCaps); +char * +qemuBuildSCSIVHostHostdevDevStr(const virDomainDef *def, + virDomainHostdevDefPtr dev, + virQEMUCapsPtr qemuCaps, + char *vhostfdName); char *qemuBuildRedirdevDevStr(const virDomainDef *def, virDomainRedirdevDefPtr dev, diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 30ecb4e..13f6702 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -312,6 +312,14 @@ qemuDomainPrimeVirtioDeviceAddresses(virDomainDefPtr def, } } + 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_SCSI_HOST && + 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) @@ -1594,8 +1602,10 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def, for (i = 0; i < def->nhostdevs; i++) { if (!virDeviceInfoPCIAddressWanted(def->hostdevs[i]->info)) continue; - if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || - def->hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) + if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) + continue; + if (def->hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI && + def->hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST) continue; if (qemuDomainPCIAddressReserveNextSlot(addrs, diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index dd3a3cf..a463d46 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -292,6 +292,17 @@ qemuHostdevPrepareSCSIDevices(virQEMUDriverPtr driver, name, hostdevs, nhostdevs); } +int +qemuHostdevPrepareSCSIVHostDevices(virQEMUDriverPtr driver, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) +{ + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; + + return virHostdevPrepareSCSIVHostDevices(hostdev_mgr, QEMU_DRIVER_NAME, + name, hostdevs, nhostdevs); +} int qemuHostdevPrepareDomainDevices(virQEMUDriverPtr driver, @@ -315,6 +326,10 @@ qemuHostdevPrepareDomainDevices(virQEMUDriverPtr driver, def->hostdevs, def->nhostdevs) < 0) return -1; + if (qemuHostdevPrepareSCSIVHostDevices(driver, def->name, + def->hostdevs, def->nhostdevs) < 0) + return -1; + return 0; } @@ -370,6 +385,29 @@ qemuHostdevReAttachSCSIDevices(virQEMUDriverPtr driver, } void +qemuHostdevReAttachSCSIVHostDevices(virQEMUDriverPtr driver, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) +{ + size_t i; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; + + for (i = 0; i < nhostdevs; i++) { + virDomainHostdevDefPtr hostdev = hostdevs[i]; + virDomainDeviceDef dev; + + dev.type = VIR_DOMAIN_DEVICE_HOSTDEV; + dev.data.hostdev = hostdev; + + ignore_value(qemuRemoveSharedDevice(driver, &dev, name)); + } + + virHostdevReAttachSCSIVHostDevices(hostdev_mgr, QEMU_DRIVER_NAME, + name, hostdevs, nhostdevs); +} + +void qemuHostdevReAttachDomainDevices(virQEMUDriverPtr driver, virDomainDefPtr def) { @@ -384,4 +422,7 @@ qemuHostdevReAttachDomainDevices(virQEMUDriverPtr driver, qemuHostdevReAttachSCSIDevices(driver, def->name, def->hostdevs, def->nhostdevs); + + qemuHostdevReAttachSCSIVHostDevices(driver, def->name, def->hostdevs, + def->nhostdevs); } diff --git a/src/qemu/qemu_hostdev.h b/src/qemu/qemu_hostdev.h index 0a3c715..74a7d4f 100644 --- a/src/qemu/qemu_hostdev.h +++ b/src/qemu/qemu_hostdev.h @@ -55,6 +55,10 @@ int qemuHostdevPrepareSCSIDevices(virQEMUDriverPtr driver, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs); +int qemuHostdevPrepareSCSIVHostDevices(virQEMUDriverPtr driver, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs); int qemuHostdevPrepareDomainDevices(virQEMUDriverPtr driver, virDomainDefPtr def, virQEMUCapsPtr qemuCaps, @@ -72,6 +76,10 @@ void qemuHostdevReAttachSCSIDevices(virQEMUDriverPtr driver, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs); +void qemuHostdevReAttachSCSIVHostDevices(virQEMUDriverPtr driver, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs); void qemuHostdevReAttachDomainDevices(virQEMUDriverPtr driver, virDomainDefPtr def); -- 1.9.1

[...]
void +qemuHostdevReAttachSCSIVHostDevices(virQEMUDriverPtr driver, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) +{ + size_t i; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; + + for (i = 0; i < nhostdevs; i++) { + virDomainHostdevDefPtr hostdev = hostdevs[i]; + virDomainDeviceDef dev; + + dev.type = VIR_DOMAIN_DEVICE_HOSTDEV; + dev.data.hostdev = hostdev; + + ignore_value(qemuRemoveSharedDevice(driver, &dev, name)); + }
This whole loop won't be necessary, true? Since this isn't shared (it does nothing for now). I can remove before pushing - just confirm my suspicion... ACK, John

On 11/22/2016 04:08 PM, John Ferlan wrote:
[...]
void +qemuHostdevReAttachSCSIVHostDevices(virQEMUDriverPtr driver, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) +{ + size_t i; + virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr; + + for (i = 0; i < nhostdevs; i++) { + virDomainHostdevDefPtr hostdev = hostdevs[i]; + virDomainDeviceDef dev; + + dev.type = VIR_DOMAIN_DEVICE_HOSTDEV; + dev.data.hostdev = hostdev; + + ignore_value(qemuRemoveSharedDevice(driver, &dev, name)); + }
This whole loop won't be necessary, true? Since this isn't shared (it does nothing for now).
I can remove before pushing - just confirm my suspicion...
Thank you for removing, you are correct.
ACK,
John

Adjust the device string that is built for vhost-scsi devices so that it can be invoked from hotplug.
From the QEMU command line, the file descriptors are expect to be numeric only. However, for hotplug, the file descriptors are expected to begin with at least one alphabetic character else this error occurs:
# virsh attach-device guest_0001 ~/vhost.xml error: Failed to attach device from /root/vhost.xml error: internal error: unable to execute QEMU command 'getfd': Parameter 'fdname' expects a name not starting with a digit We also close the file descriptor in this case, so that shutting down the guest cleans up the host cgroup entries and allows future guests to use vhost-scsi devices. (Otherwise the guest will silently end.) Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> --- src/qemu/qemu_hotplug.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 0508c67..02e248f 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -2443,6 +2443,126 @@ qemuDomainAttachHostSCSIDevice(virConnectPtr conn, goto cleanup; } +static int +qemuDomainAttachSCSIVHostDevice(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainHostdevDefPtr hostdev) +{ + int ret = -1; + qemuDomainObjPrivatePtr priv = vm->privateData; + virErrorPtr orig_err; + virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_HOSTDEV, + { .hostdev = hostdev } }; + virDomainCCWAddressSetPtr ccwaddrs = NULL; + char *vhostfdName = NULL; + int vhostfd = -1; + char *devstr = NULL; + bool teardowncgroup = false; + bool teardownlabel = false; + bool releaseaddr = false; + + if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_SCSI_GENERIC)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("SCSI passthrough is not supported by this version of qemu")); + goto cleanup; + } + + if (qemuHostdevPrepareSCSIVHostDevices(driver, vm->def->name, &hostdev, 1) < 0) { + virDomainHostdevSubsysSCSIVHostPtr hostsrc = &hostdev->source.subsys.u.scsi_host; + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to prepare scsi_host hostdev: %s"), + hostsrc->wwpn); + goto cleanup; + } + + if (qemuSetupHostdevCgroup(vm, hostdev) < 0) + goto cleanup; + teardowncgroup = true; + + if (virSecurityManagerSetHostdevLabel(driver->securityManager, + vm->def, hostdev, NULL) < 0) + goto cleanup; + teardownlabel = true; + + if (virSCSIVHostOpenVhostSCSI(&vhostfd) < 0) + goto cleanup; + + if (virAsprintf(&vhostfdName, "vhostfd-%d", vhostfd) < 0) + goto cleanup; + + if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { + if (qemuDomainMachineIsS390CCW(vm->def) && + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_CCW)) + hostdev->info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW; + } + + if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE || + hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { + if (qemuDomainEnsurePCIAddress(vm, &dev) < 0) + goto cleanup; + } else if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) { + if (!(ccwaddrs = qemuDomainCCWAddrSetCreateFromDomain(vm->def))) + goto cleanup; + if (virDomainCCWAddressAssign(hostdev->info, ccwaddrs, + !hostdev->info->addr.ccw.assigned) < 0) + goto cleanup; + } + releaseaddr = true; + + if (qemuAssignDeviceHostdevAlias(vm->def, &hostdev->info->alias, -1) < 0) + goto cleanup; + + if (!(devstr = qemuBuildSCSIVHostHostdevDevStr(vm->def, + hostdev, + priv->qemuCaps, + vhostfdName))) + goto cleanup; + + if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1) < 0) + goto cleanup; + + qemuDomainObjEnterMonitor(driver, vm); + + if (qemuMonitorAddDeviceWithFd(priv->mon, devstr, vhostfd, vhostfdName) < 0) + goto exit_monitor; + + if (qemuDomainObjExitMonitor(driver, vm) < 0) + goto audit; + + vm->def->hostdevs[vm->def->nhostdevs++] = hostdev; + ret = 0; + + audit: + virDomainAuditHostdev(vm, hostdev, "attach", (ret == 0)); + + cleanup: + virDomainCCWAddressSetFree(ccwaddrs); + + VIR_FORCE_CLOSE(vhostfd); + VIR_FREE(vhostfdName); + VIR_FREE(devstr); + return ret; + + exit_monitor: + orig_err = virSaveLastError(); + + if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0) + VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail"); + if (teardownlabel && + virSecurityManagerRestoreHostdevLabel(driver->securityManager, + vm->def, hostdev, NULL) < 0) + VIR_WARN("Unable to restore host device labelling on hotplug fail"); + if (releaseaddr) + qemuDomainReleaseDeviceAddress(vm, hostdev->info, NULL); + + if (orig_err) { + virSetError(orig_err); + virFreeError(orig_err); + } + + goto audit; +} + int qemuDomainAttachHostDevice(virConnectPtr conn, @@ -2476,6 +2596,11 @@ qemuDomainAttachHostDevice(virConnectPtr conn, goto error; break; + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: + if (qemuDomainAttachSCSIVHostDevice(driver, vm, hostdev) < 0) + goto error; + break; + default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("hostdev subsys type '%s' not supported"), @@ -3568,6 +3693,14 @@ qemuDomainRemoveSCSIHostDevice(virQEMUDriverPtr driver, qemuHostdevReAttachSCSIDevices(driver, vm->def->name, &hostdev, 1); } +static void +qemuDomainRemoveSCSIVHostDevice(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainHostdevDefPtr hostdev) +{ + qemuHostdevReAttachSCSIVHostDevices(driver, vm->def->name, &hostdev, 1); +} + static int qemuDomainRemoveHostDevice(virQEMUDriverPtr driver, virDomainObjPtr vm, @@ -3646,6 +3779,7 @@ qemuDomainRemoveHostDevice(virQEMUDriverPtr driver, qemuDomainRemoveSCSIHostDevice(driver, vm, hostdev); break; case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: + qemuDomainRemoveSCSIVHostDevice(driver, vm, hostdev); break; case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: break; @@ -4496,6 +4630,31 @@ qemuDomainDetachHostSCSIDevice(virQEMUDriverPtr driver, } static int +qemuDomainDetachSCSIVHostDevice(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainHostdevDefPtr detach) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; + int ret = -1; + + if (!detach->info->alias) { + virReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("device cannot be detached without a device alias")); + return -1; + } + + qemuDomainMarkDeviceForRemoval(vm, detach->info); + + qemuDomainObjEnterMonitor(driver, vm); + ret = qemuMonitorDelDevice(priv->mon, detach->info->alias); + + if (qemuDomainObjExitMonitor(driver, vm) < 0) + return -1; + + return ret; +} + +static int qemuDomainDetachThisHostDevice(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainHostdevDefPtr detach) @@ -4517,6 +4676,9 @@ qemuDomainDetachThisHostDevice(virQEMUDriverPtr driver, case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: ret = qemuDomainDetachHostSCSIDevice(driver, vm, detach); break; + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: + ret = qemuDomainDetachSCSIVHostDevice(driver, vm, detach); + break; default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("hostdev subsys type '%s' not supported"), @@ -4594,6 +4756,8 @@ int qemuDomainDetachHostDevice(virQEMUDriverPtr driver, } break; } + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: + break; default: virReportError(VIR_ERR_INTERNAL_ERROR, _("unexpected hostdev type %d"), subsys->type); -- 1.9.1

On 11/21/2016 10:58 PM, Eric Farman wrote:
Adjust the device string that is built for vhost-scsi devices so that it can be invoked from hotplug.
From the QEMU command line, the file descriptors are expect to be numeric only. However, for hotplug, the file descriptors are expected to begin with at least one alphabetic character else this error occurs:
# virsh attach-device guest_0001 ~/vhost.xml error: Failed to attach device from /root/vhost.xml error: internal error: unable to execute QEMU command 'getfd': Parameter 'fdname' expects a name not starting with a digit
We also close the file descriptor in this case, so that shutting down the guest cleans up the host cgroup entries and allows future guests to use vhost-scsi devices. (Otherwise the guest will silently end.)
Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> --- src/qemu/qemu_hotplug.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 0508c67..02e248f 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -2443,6 +2443,126 @@ qemuDomainAttachHostSCSIDevice(virConnectPtr conn, goto cleanup; }
+static int +qemuDomainAttachSCSIVHostDevice(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainHostdevDefPtr hostdev) +{ + int ret = -1; + qemuDomainObjPrivatePtr priv = vm->privateData; + virErrorPtr orig_err; + virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_HOSTDEV, + { .hostdev = hostdev } }; + virDomainCCWAddressSetPtr ccwaddrs = NULL; + char *vhostfdName = NULL; + int vhostfd = -1; + char *devstr = NULL; + bool teardowncgroup = false; + bool teardownlabel = false; + bool releaseaddr = false; + + if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_SCSI_GENERIC)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("SCSI passthrough is not supported by this version of qemu")); + goto cleanup; + } + + if (qemuHostdevPrepareSCSIVHostDevices(driver, vm->def->name, &hostdev, 1) < 0) { + virDomainHostdevSubsysSCSIVHostPtr hostsrc = &hostdev->source.subsys.u.scsi_host; + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to prepare scsi_host hostdev: %s"), + hostsrc->wwpn); + goto cleanup; + } + + if (qemuSetupHostdevCgroup(vm, hostdev) < 0) + goto cleanup; + teardowncgroup = true; + + if (virSecurityManagerSetHostdevLabel(driver->securityManager, + vm->def, hostdev, NULL) < 0) + goto cleanup; + teardownlabel = true; + + if (virSCSIVHostOpenVhostSCSI(&vhostfd) < 0) + goto cleanup; + + if (virAsprintf(&vhostfdName, "vhostfd-%d", vhostfd) < 0) + goto cleanup; + + if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { + if (qemuDomainMachineIsS390CCW(vm->def) && + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_CCW)) + hostdev->info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW; + } + + if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE || + hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { + if (qemuDomainEnsurePCIAddress(vm, &dev) < 0) + goto cleanup; + } else if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) { + if (!(ccwaddrs = qemuDomainCCWAddrSetCreateFromDomain(vm->def))) + goto cleanup; + if (virDomainCCWAddressAssign(hostdev->info, ccwaddrs, + !hostdev->info->addr.ccw.assigned) < 0) + goto cleanup; + } + releaseaddr = true; + + if (qemuAssignDeviceHostdevAlias(vm->def, &hostdev->info->alias, -1) < 0) + goto cleanup; + + if (!(devstr = qemuBuildSCSIVHostHostdevDevStr(vm->def, + hostdev, + priv->qemuCaps, + vhostfdName))) + goto cleanup; + + if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1) < 0) + goto cleanup; + + qemuDomainObjEnterMonitor(driver, vm); + + if (qemuMonitorAddDeviceWithFd(priv->mon, devstr, vhostfd, vhostfdName) < 0) + goto exit_monitor; + + if (qemuDomainObjExitMonitor(driver, vm) < 0) + goto audit; + + vm->def->hostdevs[vm->def->nhostdevs++] = hostdev; + ret = 0; + + audit: + virDomainAuditHostdev(vm, hostdev, "attach", (ret == 0)); + + cleanup: + virDomainCCWAddressSetFree(ccwaddrs);
Similar to AttachHost{PCI|USB|SCSI}Devices since qemuHostdevPrepareSCSIVHostDevices was called, we need to call virHostdevReAttachSCSIVHostDevices when ret < 0 I will adjust before pushing - most likely will follow PCI or USB (it's been a long term goal to make them all consistent). ACK - John [...]

With the QEMU components in place, provide the XML parsing to invoke that code when given the following XML snippet: <hostdev mode='subsystem' type='scsi_host'> <source protocol='vhost' wwpn='naa.501234567890abcd'/> </hostdev> An optional address element can be specified within the hostdev (pick CCW or PCI as necessary): <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0625'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> --- docs/schemas/domaincommon.rng | 23 +++++++++++ src/conf/domain_audit.c | 7 ++++ src/conf/domain_conf.c | 92 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 121 insertions(+), 1 deletion(-) diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 19d45fd..bb903ef 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -3974,6 +3974,7 @@ <ref name="hostdevsubsyspci"/> <ref name="hostdevsubsysusb"/> <ref name="hostdevsubsysscsi"/> + <ref name="hostdevsubsyshost"/> </choice> </define> @@ -4102,6 +4103,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 2decf02..2d9ff5e 100644 --- a/src/conf/domain_audit.c +++ b/src/conf/domain_audit.c @@ -392,6 +392,7 @@ virDomainAuditHostdev(virDomainObjPtr vm, virDomainHostdevDefPtr hostdev, 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))) { @@ -444,6 +445,12 @@ virDomainAuditHostdev(virDomainObjPtr vm, virDomainHostdevDefPtr hostdev, } 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); diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 3a4123d..618a214 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2323,6 +2323,9 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr def) } 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; } @@ -6094,6 +6097,58 @@ virDomainHostdevSubsysSCSIDefParseXML(xmlNodePtr sourcenode, 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, @@ -6218,6 +6273,11 @@ 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"), @@ -13023,6 +13083,15 @@ virDomainHostdevDefParseXML(virDomainXMLOptionPtr xmlopt, 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; @@ -13907,7 +13976,14 @@ virDomainHostdevMatchSubsys(virDomainHostdevDefPtr a, 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; } @@ -20814,9 +20890,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; + virDomainHostdevSubsysSCSIVHostPtr hostsrc = &def->source.subsys.u.scsi_host; virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host; virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi; @@ -20857,6 +20935,15 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf, 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); @@ -20910,6 +20997,8 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf, scsihostsrc->unit); } break; + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: + break; default: virReportError(VIR_ERR_INTERNAL_ERROR, _("unexpected hostdev type %d"), @@ -20925,6 +21014,7 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf, } virBufferAdjustIndent(buf, -2); + if (!closedSource) virBufferAddLit(buf, "</source>\n"); return 0; -- 1.9.1

On 11/21/2016 10:58 PM, Eric Farman wrote:
With the QEMU components in place, provide the XML parsing to invoke that code when given the following XML snippet:
<hostdev mode='subsystem' type='scsi_host'> <source protocol='vhost' wwpn='naa.501234567890abcd'/> </hostdev>
An optional address element can be specified within the hostdev (pick CCW or PCI as necessary):
<address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0625'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> --- docs/schemas/domaincommon.rng | 23 +++++++++++ src/conf/domain_audit.c | 7 ++++ src/conf/domain_conf.c | 92 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 121 insertions(+), 1 deletion(-)
Typically when we add rng we add the xml2xml in the same patch - I'll merge patch 8 into here to keep things "normal" and "familiar". Also also merge patch 9 into here since that too would be needed... Will move patch 7 to just before here, so that the conf will be the last patch.
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 19d45fd..bb903ef 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -3974,6 +3974,7 @@ <ref name="hostdevsubsyspci"/> <ref name="hostdevsubsysusb"/> <ref name="hostdevsubsysscsi"/> + <ref name="hostdevsubsyshost"/> </choice> </define>
@@ -4102,6 +4103,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 2decf02..2d9ff5e 100644 --- a/src/conf/domain_audit.c +++ b/src/conf/domain_audit.c @@ -392,6 +392,7 @@ virDomainAuditHostdev(virDomainObjPtr vm, virDomainHostdevDefPtr hostdev, 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))) { @@ -444,6 +445,12 @@ virDomainAuditHostdev(virDomainObjPtr vm, virDomainHostdevDefPtr hostdev, } break; } + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
Looks like a missed spot from the already pushed patch (no big deal, just making a mental note). The default: exists so so I see why.
+ 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); diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 3a4123d..618a214 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2323,6 +2323,9 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr def) } 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; } @@ -6094,6 +6097,58 @@ virDomainHostdevSubsysSCSIDefParseXML(xmlNodePtr sourcenode, 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, @@ -6218,6 +6273,11 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, goto error; break;
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
Yet another spot were the default is used...
+ if (virDomainHostdevSubsysSCSIVHostDefParseXML(sourcenode, def) < 0) + goto error; + break; + default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("address type='%s' not supported in hostdev interfaces"), @@ -13023,6 +13083,15 @@ virDomainHostdevDefParseXML(virDomainXMLOptionPtr xmlopt, 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; @@ -13907,7 +13976,14 @@ virDomainHostdevMatchSubsys(virDomainHostdevDefPtr a, 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; } @@ -20814,9 +20890,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; + virDomainHostdevSubsysSCSIVHostPtr hostsrc = &def->source.subsys.u.scsi_host; virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host; virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi;
@@ -20857,6 +20935,15 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf, 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); @@ -20910,6 +20997,8 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf, scsihostsrc->unit); } break; + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: + break; default: virReportError(VIR_ERR_INTERNAL_ERROR, _("unexpected hostdev type %d"), @@ -20925,6 +21014,7 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf, }
virBufferAdjustIndent(buf, -2); + if (!closedSource) virBufferAddLit(buf, "</source>\n");
I'll reindent this... ACK John
return 0;

On 11/22/2016 04:12 PM, John Ferlan wrote:
On 11/21/2016 10:58 PM, Eric Farman wrote:
With the QEMU components in place, provide the XML parsing to invoke that code when given the following XML snippet:
<hostdev mode='subsystem' type='scsi_host'> <source protocol='vhost' wwpn='naa.501234567890abcd'/> </hostdev>
An optional address element can be specified within the hostdev (pick CCW or PCI as necessary):
<address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0625'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> --- docs/schemas/domaincommon.rng | 23 +++++++++++ src/conf/domain_audit.c | 7 ++++ src/conf/domain_conf.c | 92 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 121 insertions(+), 1 deletion(-)
Typically when we add rng we add the xml2xml in the same patch - I'll merge patch 8 into here to keep things "normal" and "familiar". Also also merge patch 9 into here since that too would be needed... Will move patch 7 to just before here, so that the conf will be the last patch.
Much obliged.
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 19d45fd..bb903ef 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -3974,6 +3974,7 @@ <ref name="hostdevsubsyspci"/> <ref name="hostdevsubsysusb"/> <ref name="hostdevsubsysscsi"/> + <ref name="hostdevsubsyshost"/> </choice> </define>
@@ -4102,6 +4103,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 2decf02..2d9ff5e 100644 --- a/src/conf/domain_audit.c +++ b/src/conf/domain_audit.c @@ -392,6 +392,7 @@ virDomainAuditHostdev(virDomainObjPtr vm, virDomainHostdevDefPtr hostdev, 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))) { @@ -444,6 +445,12 @@ virDomainAuditHostdev(virDomainObjPtr vm, virDomainHostdevDefPtr hostdev, } break; } + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: Looks like a missed spot from the already pushed patch (no big deal, just making a mental note). The default: exists so so I see why.
If memory serves me right, these cases are guarded by earlier code. But, in the interest of the "hey, look over here when adding a thing!" mentality, I will send a fixup for them. Thanks, - Eric
+ 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); diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 3a4123d..618a214 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2323,6 +2323,9 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr def) } 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; } @@ -6094,6 +6097,58 @@ virDomainHostdevSubsysSCSIDefParseXML(xmlNodePtr sourcenode, 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, @@ -6218,6 +6273,11 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, goto error; break;
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: Yet another spot were the default is used...
+ if (virDomainHostdevSubsysSCSIVHostDefParseXML(sourcenode, def) < 0) + goto error; + break; + default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("address type='%s' not supported in hostdev interfaces"), @@ -13023,6 +13083,15 @@ virDomainHostdevDefParseXML(virDomainXMLOptionPtr xmlopt, 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; @@ -13907,7 +13976,14 @@ virDomainHostdevMatchSubsys(virDomainHostdevDefPtr a, 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; } @@ -20814,9 +20890,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; + virDomainHostdevSubsysSCSIVHostPtr hostsrc = &def->source.subsys.u.scsi_host; virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host; virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi;
@@ -20857,6 +20935,15 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf, 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); @@ -20910,6 +20997,8 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf, scsihostsrc->unit); } break; + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: + break; default: virReportError(VIR_ERR_INTERNAL_ERROR, _("unexpected hostdev type %d"), @@ -20925,6 +21014,7 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf, }
virBufferAdjustIndent(buf, -2); + if (!closedSource) virBufferAddLit(buf, "</source>\n"); I'll reindent this...
ACK
John
return 0;

Ensure that the vhost-scsi wwpn information is passed to the different security policies. Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> --- src/security/security_apparmor.c | 20 ++++++++++++++++- src/security/security_dac.c | 46 ++++++++++++++++++++++++++++++++++++++-- src/security/security_selinux.c | 43 +++++++++++++++++++++++++++++++++++-- 3 files changed, 104 insertions(+), 5 deletions(-) diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c index 19085ec..2c33abb 100644 --- a/src/security/security_apparmor.c +++ b/src/security/security_apparmor.c @@ -44,6 +44,7 @@ #include "viruuid.h" #include "virpci.h" #include "virusb.h" +#include "virscsivhost.h" #include "virfile.h" #include "configmake.h" #include "vircommand.h" @@ -357,6 +358,13 @@ AppArmorSetSecuritySCSILabel(virSCSIDevicePtr dev ATTRIBUTE_UNUSED, return AppArmorSetSecurityHostdevLabelHelper(file, opaque); } +static int +AppArmorSetSecurityHostLabel(virSCSIVHostDevicePtr dev ATTRIBUTE_UNUSED, + const char *file, void *opaque) +{ + return AppArmorSetSecurityHostdevLabelHelper(file, opaque); +} + /* Called on libvirtd startup to see if AppArmor is available */ static int AppArmorSecurityManagerProbe(const char *virtDriver ATTRIBUTE_UNUSED) @@ -831,6 +839,7 @@ AppArmorSetSecurityHostdevLabel(virSecurityManagerPtr mgr, virDomainHostdevSubsysUSBPtr usbsrc = &dev->source.subsys.u.usb; virDomainHostdevSubsysPCIPtr pcisrc = &dev->source.subsys.u.pci; virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi; + virDomainHostdevSubsysSCSIVHostPtr hostsrc = &dev->source.subsys.u.scsi_host; if (!secdef) return -1; @@ -910,7 +919,16 @@ AppArmorSetSecurityHostdevLabel(virSecurityManagerPtr mgr, } case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: { - /* Fall through for now */ + virSCSIVHostDevicePtr host = virSCSIVHostDeviceNew(hostsrc->wwpn); + + if (!host) + goto done; + + ret = virSCSIVHostDeviceFileIterate(host, + AppArmorSetSecurityHostLabel, + ptr); + virSCSIVHostDeviceFree(host); + break; } case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: diff --git a/src/security/security_dac.c b/src/security/security_dac.c index 2803962..649219e 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -36,6 +36,7 @@ #include "virpci.h" #include "virusb.h" #include "virscsi.h" +#include "virscsivhost.h" #include "virstoragefile.h" #include "virstring.h" #include "virutil.h" @@ -582,6 +583,15 @@ virSecurityDACSetSCSILabel(virSCSIDevicePtr dev ATTRIBUTE_UNUSED, static int +virSecurityDACSetHostLabel(virSCSIVHostDevicePtr dev ATTRIBUTE_UNUSED, + const char *file, + void *opaque) +{ + return virSecurityDACSetHostdevLabelHelper(file, opaque); +} + + +static int virSecurityDACSetHostdevLabel(virSecurityManagerPtr mgr, virDomainDefPtr def, virDomainHostdevDefPtr dev, @@ -592,6 +602,7 @@ virSecurityDACSetHostdevLabel(virSecurityManagerPtr mgr, virDomainHostdevSubsysUSBPtr usbsrc = &dev->source.subsys.u.usb; virDomainHostdevSubsysPCIPtr pcisrc = &dev->source.subsys.u.pci; virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi; + virDomainHostdevSubsysSCSIVHostPtr hostsrc = &dev->source.subsys.u.scsi_host; int ret = -1; if (!priv->dynamicOwnership) @@ -677,7 +688,16 @@ virSecurityDACSetHostdevLabel(virSecurityManagerPtr mgr, } case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: { - /* Fall through for now */ + virSCSIVHostDevicePtr host = virSCSIVHostDeviceNew(hostsrc->wwpn); + + if (!host) + goto done; + + ret = virSCSIVHostDeviceFileIterate(host, + virSecurityDACSetHostLabel, + &cbdata); + virSCSIVHostDeviceFree(host); + break; } case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: @@ -724,6 +744,17 @@ virSecurityDACRestoreSCSILabel(virSCSIDevicePtr dev ATTRIBUTE_UNUSED, static int +virSecurityDACRestoreHostLabel(virSCSIVHostDevicePtr dev ATTRIBUTE_UNUSED, + const char *file, + void *opaque) +{ + virSecurityManagerPtr mgr = opaque; + virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr); + return virSecurityDACRestoreFileLabel(priv, file); +} + + +static int virSecurityDACRestoreHostdevLabel(virSecurityManagerPtr mgr, virDomainDefPtr def, virDomainHostdevDefPtr dev, @@ -735,6 +766,7 @@ virSecurityDACRestoreHostdevLabel(virSecurityManagerPtr mgr, virDomainHostdevSubsysUSBPtr usbsrc = &dev->source.subsys.u.usb; virDomainHostdevSubsysPCIPtr pcisrc = &dev->source.subsys.u.pci; virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi; + virDomainHostdevSubsysSCSIVHostPtr hostsrc = &dev->source.subsys.u.scsi_host; int ret = -1; secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME); @@ -810,7 +842,17 @@ virSecurityDACRestoreHostdevLabel(virSecurityManagerPtr mgr, } case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: { - /* Fall through for now */ + virSCSIVHostDevicePtr host = virSCSIVHostDeviceNew(hostsrc->wwpn); + + if (!host) + goto done; + + ret = virSCSIVHostDeviceFileIterate(host, + virSecurityDACRestoreHostLabel, + mgr); + virSCSIVHostDeviceFree(host); + + break; } case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 9870b41..1776a63 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -39,6 +39,7 @@ #include "virpci.h" #include "virusb.h" #include "virscsi.h" +#include "virscsivhost.h" #include "virstoragefile.h" #include "virfile.h" #include "virhash.h" @@ -1416,6 +1417,13 @@ virSecuritySELinuxSetSCSILabel(virSCSIDevicePtr dev, } static int +virSecuritySELinuxSetHostLabel(virSCSIVHostDevicePtr dev ATTRIBUTE_UNUSED, + const char *file, void *opaque) +{ + return virSecuritySELinuxSetHostdevLabelHelper(file, opaque); +} + +static int virSecuritySELinuxSetHostdevSubsysLabel(virSecurityManagerPtr mgr, virDomainDefPtr def, virDomainHostdevDefPtr dev, @@ -1425,6 +1433,7 @@ virSecuritySELinuxSetHostdevSubsysLabel(virSecurityManagerPtr mgr, virDomainHostdevSubsysUSBPtr usbsrc = &dev->source.subsys.u.usb; virDomainHostdevSubsysPCIPtr pcisrc = &dev->source.subsys.u.pci; virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi; + virDomainHostdevSubsysSCSIVHostPtr hostsrc = &dev->source.subsys.u.scsi_host; virSecuritySELinuxCallbackData data = {.mgr = mgr, .def = def}; int ret = -1; @@ -1499,7 +1508,16 @@ virSecuritySELinuxSetHostdevSubsysLabel(virSecurityManagerPtr mgr, } case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: { - /* Fall through for now */ + virSCSIVHostDevicePtr host = virSCSIVHostDeviceNew(hostsrc->wwpn); + + if (!host) + goto done; + + ret = virSCSIVHostDeviceFileIterate(host, + virSecuritySELinuxSetHostLabel, + &data); + virSCSIVHostDeviceFree(host); + break; } case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: @@ -1627,6 +1645,16 @@ virSecuritySELinuxRestoreSCSILabel(virSCSIDevicePtr dev, } static int +virSecuritySELinuxRestoreHostLabel(virSCSIVHostDevicePtr dev ATTRIBUTE_UNUSED, + const char *file, + void *opaque) +{ + virSecurityManagerPtr mgr = opaque; + + return virSecuritySELinuxRestoreFileLabel(mgr, file); +} + +static int virSecuritySELinuxRestoreHostdevSubsysLabel(virSecurityManagerPtr mgr, virDomainHostdevDefPtr dev, const char *vroot) @@ -1635,6 +1663,7 @@ virSecuritySELinuxRestoreHostdevSubsysLabel(virSecurityManagerPtr mgr, virDomainHostdevSubsysUSBPtr usbsrc = &dev->source.subsys.u.usb; virDomainHostdevSubsysPCIPtr pcisrc = &dev->source.subsys.u.pci; virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi; + virDomainHostdevSubsysSCSIVHostPtr hostsrc = &dev->source.subsys.u.scsi_host; int ret = -1; /* Like virSecuritySELinuxRestoreImageLabelInt() for a networked @@ -1705,7 +1734,17 @@ virSecuritySELinuxRestoreHostdevSubsysLabel(virSecurityManagerPtr mgr, } case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: { - /* Fall through for now */ + virSCSIVHostDevicePtr host = virSCSIVHostDeviceNew(hostsrc->wwpn); + + if (!host) + goto done; + + ret = virSCSIVHostDeviceFileIterate(host, + virSecuritySELinuxRestoreHostLabel, + mgr); + virSCSIVHostDeviceFree(host); + + break; } case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: -- 1.9.1

On 11/21/2016 10:58 PM, Eric Farman wrote:
Ensure that the vhost-scsi wwpn information is passed to the different security policies.
Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> --- src/security/security_apparmor.c | 20 ++++++++++++++++- src/security/security_dac.c | 46 ++++++++++++++++++++++++++++++++++++++-- src/security/security_selinux.c | 43 +++++++++++++++++++++++++++++++++++-- 3 files changed, 104 insertions(+), 5 deletions(-)
Going to swap the order of this - put it after qemu and before conf, making conf the "last" patch ACK John

These tests were cloned from hostdev-scsi-virtio-scsi in both xml2argv and xml2xml We add ones for both vhost-scsi-ccw and vhost-scsi-pci since the syntaxes are slightly different between them. Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> Reviewed-by: Boris Fiuczynski <fiuczy@linux.vnet.ibm.com> --- .../qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.args | 23 ++++++++++++ .../qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.xml | 34 ++++++++++++++++++ .../qemuxml2argv-hostdev-scsi-vhost-scsi-pci.args | 24 +++++++++++++ .../qemuxml2argv-hostdev-scsi-vhost-scsi-pci.xml | 42 ++++++++++++++++++++++ tests/qemuxml2argvtest.c | 6 ++++ .../qemuxml2xmlout-hostdev-scsi-vhost-scsi-ccw.xml | 1 + .../qemuxml2xmlout-hostdev-scsi-vhost-scsi-pci.xml | 1 + tests/qemuxml2xmltest.c | 6 ++++ 8 files changed, 137 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.xml create mode 120000 tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-ccw.xml create mode 120000 tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-pci.xml diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.args b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.args new file mode 100644 index 0000000..25e7bd4 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.args @@ -0,0 +1,23 @@ +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 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.xml b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.xml new file mode 100644 index 0000000..e428518 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.xml @@ -0,0 +1,34 @@ +<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> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.args b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.args new file mode 100644 index 0000000..7071e62 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.args @@ -0,0 +1,24 @@ +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 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.xml b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.xml new file mode 100644 index 0000000..aea6f7f --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.xml @@ -0,0 +1,42 @@ +<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> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 985f45d..1954696 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -2034,6 +2034,12 @@ mymain(void) 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); diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-ccw.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-ccw.xml new file mode 120000 index 0000000..adea6e5 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-ccw.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.xml \ No newline at end of file diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-pci.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-pci.xml new file mode 120000 index 0000000..891aaf9 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-pci.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.xml \ No newline at end of file diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index e22b63f..4c7f147 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -858,6 +858,12 @@ mymain(void) 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); -- 1.9.1

On 11/21/2016 10:58 PM, Eric Farman wrote:
These tests were cloned from hostdev-scsi-virtio-scsi in both xml2argv and xml2xml
We add ones for both vhost-scsi-ccw and vhost-scsi-pci since the syntaxes are slightly different between them.
Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> Reviewed-by: Boris Fiuczynski <fiuczy@linux.vnet.ibm.com> --- .../qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.args | 23 ++++++++++++ .../qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.xml | 34 ++++++++++++++++++ .../qemuxml2argv-hostdev-scsi-vhost-scsi-pci.args | 24 +++++++++++++ .../qemuxml2argv-hostdev-scsi-vhost-scsi-pci.xml | 42 ++++++++++++++++++++++ tests/qemuxml2argvtest.c | 6 ++++ .../qemuxml2xmlout-hostdev-scsi-vhost-scsi-ccw.xml | 1 + .../qemuxml2xmlout-hostdev-scsi-vhost-scsi-pci.xml | 1 + tests/qemuxml2xmltest.c | 6 ++++ 8 files changed, 137 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.xml create mode 120000 tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-ccw.xml create mode 120000 tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-pci.xml
Merging w/ patch 6 (conf changes)...
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.args b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.args new file mode 100644 index 0000000..25e7bd4 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.args @@ -0,0 +1,23 @@ +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 \
syntax-check complains about above 2 lines being too long - fixed before push.
+-device virtio-balloon-ccw,id=balloon0,devno=fe.0.0003 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.xml b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.xml new file mode 100644 index 0000000..e428518 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.xml @@ -0,0 +1,34 @@ +<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> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.args b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.args new file mode 100644 index 0000000..7071e62 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.args @@ -0,0 +1,24 @@ +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 \
Likewise, line too long - fixed before push. ACK w/ adjustments (I'll make them) John
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.xml b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.xml new file mode 100644 index 0000000..aea6f7f --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.xml @@ -0,0 +1,42 @@ +<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> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 985f45d..1954696 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -2034,6 +2034,12 @@ mymain(void) 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); diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-ccw.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-ccw.xml new file mode 120000 index 0000000..adea6e5 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-ccw.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-ccw.xml \ No newline at end of file diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-pci.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-pci.xml new file mode 120000 index 0000000..891aaf9 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-hostdev-scsi-vhost-scsi-pci.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/qemuxml2argv-hostdev-scsi-vhost-scsi-pci.xml \ No newline at end of file diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index e22b63f..4c7f147 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -858,6 +858,12 @@ mymain(void) 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);

Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> --- docs/formatdomain.html.in | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 4e40aa1..6bd02cc 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3694,6 +3694,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 @@ -3732,6 +3743,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.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 @@ -3795,6 +3812,13 @@ 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> -- 1.9.1

On 11/21/2016 10:58 PM, Eric Farman wrote:
Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> --- docs/formatdomain.html.in | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
This will get squashed in with the conf patch. I'll also generate the news.html.in entry: <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> ACK - I'll push these in a bit, just seeing what I get on my test system... Of course I'm also curious what would happen if I try to pass through a vHBA ;-)... John
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 4e40aa1..6bd02cc 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3694,6 +3694,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 @@ -3732,6 +3743,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.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 @@ -3795,6 +3812,13 @@ 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>

On 11/22/2016 04:16 PM, John Ferlan wrote:
On 11/21/2016 10:58 PM, Eric Farman wrote:
Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> --- docs/formatdomain.html.in | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
This will get squashed in with the conf patch. I'll also generate the news.html.in entry:
<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>
ACK -
I'll push these in a bit, just seeing what I get on my test system... Of course I'm also curious what would happen if I try to pass through a vHBA ;-)...
Many thanks, John! And let me know if that bubbles up your list; I'm curious what would happen too. :-) - Eric
John
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 4e40aa1..6bd02cc 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3694,6 +3694,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 @@ -3732,6 +3743,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.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 @@ -3795,6 +3812,13 @@ 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>

On 11/22/2016 02:16 PM, John Ferlan wrote:
On 11/21/2016 10:58 PM, Eric Farman wrote:
Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> --- docs/formatdomain.html.in | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
This will get squashed in with the conf patch. I'll also generate the news.html.in entry:
<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>
ACK -
I'll push these in a bit, just seeing what I get on my test system... Of course I'm also curious what would happen if I try to pass through a vHBA ;-)...
I have unsuccessfully tried it, but not sure how to correctly specify the vHBA in domXML. First, create a vHBA: cat vhba.xml <device> <parent_wwpn>2100001b32847342</parent_wwpn> <parent_wwnn>2000001b32847342</parent_wwnn> <capability type='scsi_host'> <capability type='fc_host'> <wwnn>9990100000000001</wwnn> <wwpn>9990000000000001</wwpn> </capability> </capability> </device> virsh nodedev-create vhba.xml (@John: Notice I'm using your "Allow creation of vHBA by parent_wwnn/wwpn or fabric_name" series. I'll try to respond with review comments on that series tomorrow.) Add the vHBA to domain config using a variant of Eric's example: <hostdev mode='subsystem' type='scsi_host'> <source protocol='vhost' wwpn='naa.9990000000000001'/> <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x1000'/> </hostdev> Start the VM: virsh start test error: Failed to start domain test error: Path '/sys/kernel/config/target/vhost//naa.5001405df3e54061' is not accessible: No such file or directory It looks like this patch series only handles scsi_host created with targetcli, but I didn't look at all the patches closely. Is it possible to use vhost-scsi with NPIV vport (vHBA)? If so, any pointers on how to specify the vHBA in <hostdev> element? Regards, Jim

On 12/07/2016 08:16 PM, Jim Fehlig wrote:
On 11/22/2016 02:16 PM, John Ferlan wrote:
On 11/21/2016 10:58 PM, Eric Farman wrote:
Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> --- docs/formatdomain.html.in | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
This will get squashed in with the conf patch. I'll also generate the news.html.in entry:
<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>
ACK -
I'll push these in a bit, just seeing what I get on my test system... Of course I'm also curious what would happen if I try to pass through a vHBA ;-)...
I have unsuccessfully tried it, but not sure how to correctly specify the vHBA in domXML.
First, create a vHBA: cat vhba.xml <device> <parent_wwpn>2100001b32847342</parent_wwpn> <parent_wwnn>2000001b32847342</parent_wwnn> <capability type='scsi_host'> <capability type='fc_host'> <wwnn>9990100000000001</wwnn> <wwpn>9990000000000001</wwpn> </capability> </capability> </device> virsh nodedev-create vhba.xml
(@John: Notice I'm using your "Allow creation of vHBA by parent_wwnn/wwpn or fabric_name" series. I'll try to respond with review comments on that series tomorrow.)
(@John: Me too :)
Add the vHBA to domain config using a variant of Eric's example: <hostdev mode='subsystem' type='scsi_host'> <source protocol='vhost' wwpn='naa.9990000000000001'/> <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x1000'/> </hostdev>
Start the VM: virsh start test error: Failed to start domain test error: Path '/sys/kernel/config/target/vhost//naa.5001405df3e54061' is not accessible: No such file or directory
Eh? Where did "5001..." come from? Given the above hostdev snippet, I would've expected this to show "99900..." Also, if you're not using an s390 machine, the address should probably be type='pci' or omitted altogether.
It looks like this patch series only handles scsi_host created with targetcli, but I didn't look at all the patches closely.
Today, yes. But more specifically, it's only handling scsi_host that connects to the vhost_scsi target, thus the "/sys/kernel/config/target/vhost/" prefix. The NPIV vport is at a different locale.
Is it possible to use vhost-scsi with NPIV vport (vHBA)? If so, any pointers on how to specify the vHBA in <hostdev> element?
This vhost-scsi series had to do some trickery rather than relying on virsh nodedev-list for data. Looking at John's series, I suspect there's some additional work necessary for the vport-capable sysfs entries than what exists with this series. Some of which I deferred from an earlier review comment. - Eric
Regards, Jim

Eric Farman wrote:
On 12/07/2016 08:16 PM, Jim Fehlig wrote:
On 11/22/2016 02:16 PM, John Ferlan wrote:
On 11/21/2016 10:58 PM, Eric Farman wrote:
Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> --- docs/formatdomain.html.in | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
This will get squashed in with the conf patch. I'll also generate the news.html.in entry:
<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>
ACK -
I'll push these in a bit, just seeing what I get on my test system... Of course I'm also curious what would happen if I try to pass through a vHBA ;-)...
I have unsuccessfully tried it, but not sure how to correctly specify the vHBA in domXML.
First, create a vHBA: cat vhba.xml <device> <parent_wwpn>2100001b32847342</parent_wwpn> <parent_wwnn>2000001b32847342</parent_wwnn> <capability type='scsi_host'> <capability type='fc_host'> <wwnn>9990100000000001</wwnn> <wwpn>9990000000000001</wwpn> </capability> </capability> </device> virsh nodedev-create vhba.xml
(@John: Notice I'm using your "Allow creation of vHBA by parent_wwnn/wwpn or fabric_name" series. I'll try to respond with review comments on that series tomorrow.)
(@John: Me too :)
Add the vHBA to domain config using a variant of Eric's example: <hostdev mode='subsystem' type='scsi_host'> <source protocol='vhost' wwpn='naa.9990000000000001'/> <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x1000'/> </hostdev>
Start the VM: virsh start test error: Failed to start domain test error: Path '/sys/kernel/config/target/vhost//naa.5001405df3e54061' is not accessible: No such file or directory
Eh? Where did "5001..." come from? Given the above hostdev snippet, I would've expected this to show "99900..."
Also, if you're not using an s390 machine, the address should probably be type='pci' or omitted altogether.
Sorry, too much copy and paste between your example and the various configs I tried. Also too hasty in trying to get the mail out before knocking off for the day. The actual hostdev config is <hostdev mode='subsystem' type='scsi_host'> <source protocol='vhost' wwpn='naa.9990000000000001'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x0b' function='0x0'/> </hostdev> and the error error: Path '/sys/kernel/config/target/vhost//naa.9990000000000001' is not accessible: No such file or directory
It looks like this patch series only handles scsi_host created with targetcli, but I didn't look at all the patches closely.
Today, yes. But more specifically, it's only handling scsi_host that connects to the vhost_scsi target, thus the "/sys/kernel/config/target/vhost/" prefix. The NPIV vport is at a different locale.
Is it possible to use vhost-scsi with NPIV vport (vHBA)? If so, any pointers on how to specify the vHBA in <hostdev> element?
This vhost-scsi series had to do some trickery rather than relying on virsh nodedev-list for data. Looking at John's series, I suspect there's some additional work necessary for the vport-capable sysfs entries than what exists with this series. Some of which I deferred from an earlier review comment.
Ok, thanks. I'll see if I can figure out how to make the vports work with vhost-scsi. Regards, Jim

On 12/07/2016 08:16 PM, Jim Fehlig wrote:
On 11/22/2016 02:16 PM, John Ferlan wrote:
On 11/21/2016 10:58 PM, Eric Farman wrote:
Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com> --- docs/formatdomain.html.in | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
This will get squashed in with the conf patch. I'll also generate the news.html.in entry:
<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>
ACK -
I'll push these in a bit, just seeing what I get on my test system... Of course I'm also curious what would happen if I try to pass through a vHBA ;-)...
I have unsuccessfully tried it, but not sure how to correctly specify the vHBA in domXML.
First, create a vHBA: cat vhba.xml <device> <parent_wwpn>2100001b32847342</parent_wwpn> <parent_wwnn>2000001b32847342</parent_wwnn> <capability type='scsi_host'> <capability type='fc_host'> <wwnn>9990100000000001</wwnn> <wwpn>9990000000000001</wwpn> </capability> </capability> </device> virsh nodedev-create vhba.xml
(@John: Notice I'm using your "Allow creation of vHBA by parent_wwnn/wwpn or fabric_name" series. I'll try to respond with review comments on that series tomorrow.)
Add the vHBA to domain config using a variant of Eric's example: <hostdev mode='subsystem' type='scsi_host'> <source protocol='vhost' wwpn='naa.9990000000000001'/> <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x1000'/> </hostdev>
Start the VM: virsh start test error: Failed to start domain test error: Path '/sys/kernel/config/target/vhost//naa.5001405df3e54061' is not accessible: No such file or directory
It looks like this patch series only handles scsi_host created with targetcli, but I didn't look at all the patches closely. Is it possible to use vhost-scsi with NPIV vport (vHBA)? If so, any pointers on how to specify the vHBA in <hostdev> element?
I've been buried by other things, but didn't want to ignore completely... Unfortunately I haven't found a way to use configure w/ vHBA either - I really was really hoping something could be done. It would have been so nice to just use XML that would include the scsi_hostN of the vHBA. I need to find the time to work through what targetcli does - I think it creates another scsi_hostN which is essentially what is used. That'd be similar enough to what vport_create does. Then it would be (hah!) just a matter of some code ;-) perhaps... The example Eric has in the cover used multipath which is not something I generally configure/use. I found some example using google to not use multipath, but didn't spend too much time with it. I got it to do something, but then got pinged to work on something else (you know how that goes!). John

On Mon, 2016-11-21 at 22:58 -0500, Eric Farman wrote:
This patch series provides a libvirt implementation of the vhost-scsi interface in QEMU.
Can you please provide a release notes entry briefly describing this change? You can look at existing entries in docs/news.html.in to see how it should look. Thanks! -- Andrea Bolognani / Red Hat / Virtualization

On 11/25/2016 05:50 AM, Andrea Bolognani wrote:
On Mon, 2016-11-21 at 22:58 -0500, Eric Farman wrote:
This patch series provides a libvirt implementation of the vhost-scsi interface in QEMU.
Can you please provide a release notes entry briefly describing this change? You can look at existing entries in docs/news.html.in to see how it should look. Thanks!
More than what I put in my reply to 9/9? ... I'll also generate the news.html.in entry: <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> John
-- Andrea Bolognani / Red Hat / Virtualization
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

On Fri, 2016-11-25 at 07:30 -0500, John Ferlan wrote:
This patch series provides a libvirt implementation of the vhost-scsi interface in QEMU.
Can you please provide a release notes entry briefly describing this change? You can look at existing entries in docs/news.html.in to see how it should look. Thanks!
More than what I put in my reply to 9/9?
... I'll also generate the news.html.in entry:
<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>
Nope, just missed it :) -- Andrea Bolognani / Red Hat / Virtualization
participants (4)
-
Andrea Bolognani
-
Eric Farman
-
Jim Fehlig
-
John Ferlan