[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