[libvirt] [PATCH 04/25] qemu: Build qemu command line for scsi host device
John Ferlan
jferlan at redhat.com
Mon May 6 17:37:55 UTC 2013
On 05/03/2013 02:07 PM, Osier Yang wrote:
> From: Han Cheng <hanc.fnst at cn.fujitsu.com>
>
> Except the scsi host device's controller is "lsilogic", mapping
> between the libvirt attributes and scsi-generic properties is:
>
> libvirt qemu
> -----------------------------------------
> controller bus ($libvirt_controller.0)
> bus channel
> target scsi-id
> unit lun
>
> For scsi host device with "lsilogic" controller, the mapping is:
> ('target (libvirt)' must be 0, as it's not used; 'unit (libvirt)
> must <= 7).
>
> libvirt qemu
> ----------------------------------------------------------
> controller && bus bus ($libvirt_controller.$libvirt_bus)
> unit scsi-id
>
Might be nice to include this mapping in the code comments especially
for those looking for this type of information some day that may not
think to look in a git commit log...
> It's not good to hardcode/hard-check limits of these attributes,
> and even worse, these limits are not documented, one has to find
> out by either testing or reading the qemu code, I'm looking forward
> to qemu expose limits like these one day). For example, exposing
> "max_target", "max_lun" for megasas:
>
> static const struct SCSIBusInfo megasas_scsi_info = {
> .tcq = true,
> .max_target = MFI_MAX_LD,
> .max_lun = 255,
>
> .transfer_data = megasas_xfer_complete,
> .get_sg_list = megasas_get_sg_list,
> .complete = megasas_command_complete,
> .cancel = megasas_command_cancel,
> };
>
> Example of the qemu command line (lsilogic controller):
>
> -drive file=/dev/sg2,if=none,id=drive-hostdev-scsi_host7-0-0-0 \
> -device scsi-generic,bus=scsi0.0,scsi-id=8,\
> drive=drive-hostdev-scsi_host7-0-0-0,id=hostdev-scsi_host7-0-0-0
>
> Example of the qemu command line (virtio-scsi controller):
>
> -drive file=/dev/sg2,if=none,id=drive-hostdev-scsi_host7-0-0-0 \
> -device scsi-generic,bus=scsi0.0,channel=0,scsi-id=128,lun=128,\
> drive=drive-hostdev-scsi_host7-0-0-0,id=hostdev-scsi_host7-0-0-0
>
> Signed-off-by: Han Cheng <hanc.fnst at cn.fujitsu.com>
> Signed-off-by: Osier Yang <jyang at redhat.com>
>
> ---
> v3 - v4:
> * Remove checking for "bug == 0"
> * Split "bootindex" and "readonly" support into another patch
>
> v2.5 - v3:
> * Add support for all other controllers, but not only virtio-scsi
> * Add checking for "bus == 0"
> * Add checking for "target == 0" && "unit <= 7" for scsi host device
> which is on "lsilogic" controller.
> * Integrate xml2argv test from 10/10 of v2.5 into this patch
> ---
> src/qemu/qemu_command.c | 132 ++++++++++++++++++++-
> src/qemu/qemu_command.h | 6 +
> .../qemuxml2argv-hostdev-scsi-lsi.args | 9 ++
> .../qemuxml2argv-hostdev-scsi-lsi.xml | 35 ++++++
> .../qemuxml2argv-hostdev-scsi-virtio-scsi.args | 9 ++
> ...l => qemuxml2argv-hostdev-scsi-virtio-scsi.xml} | 0
> tests/qemuxml2argvtest.c | 9 ++
> tests/qemuxml2xmltest.c | 3 +-
> 8 files changed, 199 insertions(+), 4 deletions(-)
> create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi.args
> create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi.xml
> create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-scsi.args
> rename tests/qemuxml2argvdata/{qemuxml2argv-hostdev-scsi.xml => qemuxml2argv-hostdev-scsi-virtio-scsi.xml} (100%)
>
> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index 575dce1..df896aa 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -48,6 +48,7 @@
> #include "device_conf.h"
> #include "virstoragefile.h"
> #include "virtpm.h"
> +#include "virscsi.h"
> #if defined(__linux__)
> # include <linux/capability.h>
> #endif
> @@ -745,7 +746,16 @@ qemuAssignDeviceHostdevAlias(virDomainDefPtr def, virDomainHostdevDefPtr hostdev
> }
> }
>
> - if (virAsprintf(&hostdev->info->alias, "hostdev%d", idx) < 0) {
> + if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) {
> + if (virAsprintf(&hostdev->info->alias, "hostdev-%s-%d-%d-%d",
> + hostdev->source.subsys.u.scsi.adapter,
> + hostdev->source.subsys.u.scsi.bus,
> + hostdev->source.subsys.u.scsi.target,
> + hostdev->source.subsys.u.scsi.unit) < 0) {
> + virReportOOMError();
> + return -1;
> + }
> + } else if (virAsprintf(&hostdev->info->alias, "hostdev%d", idx) < 0) {
> virReportOOMError();
> return -1;
> }
> @@ -4673,7 +4683,96 @@ qemuBuildUSBHostdevUsbDevStr(virDomainHostdevDefPtr dev)
> return ret;
> }
>
> +char *
> +qemuBuildSCSIHostdevDrvStr(virDomainHostdevDefPtr dev,
> + virQEMUCapsPtr qemuCaps ATTRIBUTE_UNUSED)
> +{
> + virBuffer buf = VIR_BUFFER_INITIALIZER;
> + char *sg = NULL;
> +
> + if (!(sg = virSCSIDeviceGetDevStr(dev->source.subsys.u.scsi.adapter,
> + dev->source.subsys.u.scsi.bus,
> + dev->source.subsys.u.scsi.target,
> + dev->source.subsys.u.scsi.unit))) {
> + goto error;
> + }
> +
> + virBufferAsprintf(&buf, "file=/dev/%s,if=none", sg);
> + virBufferAsprintf(&buf, ",id=%s-%s",
> + virDomainDeviceAddressTypeToString(dev->info->type),
> + dev->info->alias);
> +
> + if (virBufferError(&buf)) {
> + virReportOOMError();
> + goto error;
> + }
> +
VIR_FREE(sg);
No comments on remainder. I assume the test config is good - at least
it's there!
ACK
John
> + return virBufferContentAndReset(&buf);
> +error:
> + VIR_FREE(sg);
> + virBufferFreeAndReset(&buf);
> + return NULL;
> +}
> +
> +char *
> +qemuBuildSCSIHostdevDevStr(virDomainDefPtr def,
> + virDomainHostdevDefPtr dev,
> + virQEMUCapsPtr qemuCaps)
> +{
> + virBuffer buf = VIR_BUFFER_INITIALIZER;
> + int model = -1;
> +
> + model = virDomainDeviceFindControllerModel(def, dev->info,
> + VIR_DOMAIN_CONTROLLER_TYPE_SCSI);
> +
> + if (qemuSetScsiControllerModel(def, qemuCaps, &model) < 0)
> + goto error;
> +
> + if (model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC) {
> + if (dev->info->addr.drive.target != 0) {
> + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> + _("target must be 0 for scsi host device "
> + "if its controller model is 'lsilogic'"));
> + goto error;
> + }
> +
> + if (dev->info->addr.drive.unit > 7) {
> + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> + _("unit must be not more than 7 for scsi host "
> + "device if its controller model is 'lsilogic'"));
> + goto error;
> + }
> + }
> +
> + virBufferAsprintf(&buf, "scsi-generic");
> +
> + if (model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC) {
> + virBufferAsprintf(&buf, ",bus=scsi%d.%d,scsi-id=%d",
> + dev->info->addr.drive.controller,
> + dev->info->addr.drive.bus,
> + dev->info->addr.drive.unit);
> + } else {
> + virBufferAsprintf(&buf, ",bus=scsi%d.0,channel=%d,scsi-id=%d,lun=%d",
> + dev->info->addr.drive.controller,
> + dev->info->addr.drive.bus,
> + dev->info->addr.drive.target,
> + dev->info->addr.drive.unit);
> + }
>
> + virBufferAsprintf(&buf, ",drive=%s-%s,id=%s",
> + virDomainDeviceAddressTypeToString(dev->info->type),
> + dev->info->alias, dev->info->alias);
> +
> + if (virBufferError(&buf)) {
> + virReportOOMError();
> + goto error;
> + }
> +
> + return virBufferContentAndReset(&buf);
> +error:
> + virBufferFreeAndReset(&buf);
> + return NULL;
> +}
>
> /* This function outputs a -chardev command line option which describes only the
> * host side of the character device */
> @@ -7927,10 +8026,11 @@ qemuBuildCommandLine(virConnectPtr conn,
> if (hostdev->info->bootIndex) {
> if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
> (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
> - hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)) {
> + hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB &&
> + hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI)) {
> virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> _("booting from assigned devices is only "
> - "supported for PCI and USB devices"));
> + "supported for PCI, USB and SCSI devices"));
> goto error;
> } else {
> if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
> @@ -8039,6 +8139,32 @@ qemuBuildCommandLine(virConnectPtr conn,
> goto error;
> }
> }
> +
> + /* SCSI */
> + if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
> + hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) {
> + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE) &&
> + virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE) &&
> + virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_SCSI_GENERIC)) {
> + char *drvstr;
> +
> + virCommandAddArg(cmd, "-drive");
> + if (!(drvstr = qemuBuildSCSIHostdevDrvStr(hostdev, qemuCaps)))
> + goto error;
> + virCommandAddArg(cmd, drvstr);
> + VIR_FREE(drvstr);
> +
> + virCommandAddArg(cmd, "-device");
> + if (!(devstr = qemuBuildSCSIHostdevDevStr(def, hostdev, qemuCaps)))
> + goto error;
> + virCommandAddArg(cmd, devstr);
> + VIR_FREE(devstr);
> + } else {
> + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> + _("SCSI passthrough is not supported by this version of qemu"));
> + goto error;
> + }
> + }
> }
>
> /* Migration is very annoying due to wildly varying syntax &
> diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
> index a706942..9e4975d 100644
> --- a/src/qemu/qemu_command.h
> +++ b/src/qemu/qemu_command.h
> @@ -138,6 +138,12 @@ char * qemuBuildUSBHostdevUsbDevStr(virDomainHostdevDefPtr dev);
> char * qemuBuildUSBHostdevDevStr(virDomainHostdevDefPtr dev,
> virQEMUCapsPtr qemuCaps);
>
> +char * qemuBuildSCSIHostdevDrvStr(virDomainHostdevDefPtr dev,
> + virQEMUCapsPtr qemuCaps);
> +char * qemuBuildSCSIHostdevDevStr(virDomainDefPtr def,
> + virDomainHostdevDefPtr dev,
> + virQEMUCapsPtr qemuCaps);
> +
> char * qemuBuildHubDevStr(virDomainHubDefPtr dev, virQEMUCapsPtr qemuCaps);
> char * qemuBuildRedirdevDevStr(virDomainDefPtr def,
> virDomainRedirdevDefPtr dev,
> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi.args b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi.args
> new file mode 100644
> index 0000000..06f7938
> --- /dev/null
> +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi.args
> @@ -0,0 +1,9 @@
> +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc \
> +-m 214 -smp 1 -nographic -nodefaults -monitor \
> +unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
> +-device lsi,id=scsi0,bus=pci.0,addr=0x3 -usb \
> +-drive file=/dev/HostVG/QEMUGuest2,if=none,id=drive-ide0-0-0 \
> +-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
> +-drive file=/dev/sg0,if=none,id=drive-hostdev-scsi_host0-0-0-0 \
> +-device scsi-generic,bus=scsi0.0,scsi-id=7,drive=drive-hostdev-scsi_host0-0-0-0,id=hostdev-scsi_host0-0-0-0 \
> +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4
> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi.xml b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi.xml
> new file mode 100644
> index 0000000..98c469c
> --- /dev/null
> +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-lsi.xml
> @@ -0,0 +1,35 @@
> +<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'/>
> + <controller type='usb' index='0'/>
> + <controller type='ide' index='0'/>72ae3d932c0119a3e0f8a9175b8e46977cae046a
> + <controller type='pci' index='0' model='pci-root'/>
> + <hostdev mode='subsystem' type='scsi' managed='yes'>
> + <source>
> + <adapter name='scsi_host0'/>
> + <address bus='0' target='0' unit='0'/>
> + </source>
> + <address type='drive' controller='0' bus='0' target='0' unit='7'/>
> + </hostdev>
> + <memballoon model='virtio'/>
> + </devices>
> +</domain>
> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-scsi.args b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-scsi.args
> new file mode 100644
> index 0000000..b92afc7
> --- /dev/null
> +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-scsi.args
> @@ -0,0 +1,9 @@
> +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \
> +pc -m 214 -smp 1 -nographic -nodefaults -monitor \
> +unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
> +-device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x3 -usb \
> +-drive file=/dev/HostVG/QEMUGuest2,if=none,id=drive-ide0-0-0 \
> +-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
> +-drive file=/dev/sg0,if=none,id=drive-hostdev-scsi_host0-0-0-0 \
> +-device scsi-generic,bus=scsi0.0,channel=0,scsi-id=4,lun=8,drive=drive-hostdev-scsi_host0-0-0-0,id=hostdev-scsi_host0-0-0-0 \
> +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4
> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi.xml b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-scsi.xml
> similarity index 100%
> rename from tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi.xml
> rename to tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-virtio-scsi.xml
> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
> index 1286273..abe04b3 100644
> --- a/tests/qemuxml2argvtest.c
> +++ b/tests/qemuxml2argvtest.c
> @@ -974,6 +974,15 @@ mymain(void)
> DO_TEST("pci-autoadd-addr", QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE);
> DO_TEST("pci-autoadd-idx", QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE);
>
> + DO_TEST("hostdev-scsi-lsi", QEMU_CAPS_DRIVE,
> + QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE,
> + QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_SCSI_LSI,
> + QEMU_CAPS_DEVICE_SCSI_GENERIC);
> + DO_TEST("hostdev-scsi-virtio-scsi", QEMU_CAPS_DRIVE,
> + QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE,
> + QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_VIRTIO_SCSI,
> + QEMU_CAPS_DEVICE_SCSI_GENERIC);
> +
> virObjectUnref(driver.config);
> virObjectUnref(driver.caps);
> virObjectUnref(driver.xmlopt);
> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
> index 1ca1f7e..08c3eeb 100644
> --- a/tests/qemuxml2xmltest.c
> +++ b/tests/qemuxml2xmltest.c
> @@ -285,7 +285,8 @@ mymain(void)
> DO_TEST_DIFFERENT("pci-autoadd-addr");
> DO_TEST_DIFFERENT("pci-autoadd-idx");
>
> - DO_TEST("hostdev-scsi");
> + DO_TEST("hostdev-scsi-lsi");
> + DO_TEST("hostdev-scsi-virtio-scsi");
>
> virObjectUnref(driver.caps);
> virObjectUnref(driver.xmlopt);
>
More information about the libvir-list
mailing list