[libvirt] [PATCH v2 06/10] qemu: Build qemu command line for scsi-generic

Osier Yang jyang at redhat.com
Wed Apr 3 09:19:25 UTC 2013


On 01/04/13 20:00, Han Cheng wrote:
> For scsi-generic, the command line will be like:
>
>    -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
>
> The relationship between the libvirt address attrs and the qdev
> properties are(channel should always be 0):
>    bus=scsi<controller>.0
>    scsi-id=<target>
>    lun=<unit>
>
> Signed-off-by: Han Cheng <hanc.fnst at cn.fujitsu.com>
> ---
>   src/qemu/qemu_command.c |  133 +++++++++++++++++++++++++++++++++++++++++++++--
>   src/qemu/qemu_command.h |    6 ++
>   2 files changed, 134 insertions(+), 5 deletions(-)
>
> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index eac72c2..e1af64f 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -557,7 +557,7 @@ qemuAssignDeviceDiskAliasCustom(virDomainDefPtr def,
>       if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
>           if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) {
>               controllerModel =
> -                virDomainInfoFindControllerModel(def, &disk->info,
> +                virDomainDeviceFindControllerModel(def, &disk->info,
>                                                    VIR_DOMAIN_CONTROLLER_TYPE_SCSI);

Indention.

>   
>               if ((qemuSetScsiControllerModel(def, qemuCaps, &controllerModel)) < 0)
> @@ -659,7 +659,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;
>       }
> @@ -3179,7 +3188,7 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
>           }
>   
>           controllerModel =
> -            virDomainInfoFindControllerModel(def, &disk->info,
> +            virDomainDeviceFindControllerModel(def, &disk->info,
>                                                VIR_DOMAIN_CONTROLLER_TYPE_SCSI);

And this.

>           if ((qemuSetScsiControllerModel(def, qemuCaps, &controllerModel)) < 0)
>               goto error;
> @@ -4370,6 +4379,86 @@ qemuBuildUSBHostdevUsbDevStr(virDomainHostdevDefPtr dev)
>       return ret;
>   }
>   
> +char *
> +qemuBuildSCSIHostdevDrvStr(virDomainHostdevDefPtr dev, virQEMUCapsPtr qemuCaps)
> +{
> +    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))) {

Indentions?

> +        goto error;
> +    }
> +
> +    virBufferAsprintf(&buf, "file=/dev/%s,if=none", sg);
> +    virBufferAsprintf(&buf, ",id=%s-%s",
> +                      virDomainDeviceAddressTypeToString(dev->info->type),
> +                      dev->info->alias);
> +    if (dev->readonly &&
> +        virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_READONLY))
> +        virBufferAsprintf(&buf, ",readonly=on");
> +    if (virBufferError(&buf)) {
> +        virReportOOMError();
> +        goto error;
> +    }
> +    VIR_FREE(sg);

Like what I commented in 5/10 for the frees. This can be simplified.

> +
> +    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 controllerModel = -1;
> +
> +    controllerModel = virDomainDeviceFindControllerModel(def, dev->info,
> +                                                         VIR_DOMAIN_CONTROLLER_TYPE_SCSI);
> +    if (qemuSetScsiControllerModel(def, qemuCaps, &controllerModel) < 0)
> +        goto error;
> +    /* TODO: deal with lsi or ibm controller */
> +    if (controllerModel == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI) {
> +        virBufferAsprintf(&buf, "scsi-generic");
> +        if (dev->info->addr.drive.bus != 0) {
> +            virReportError(VIR_ERR_XML_ERROR,
> +                           "%s", _("SCSI controller only supports 1 bus"));
> +            goto error;
> +        }
> +        /* TODO: deal with early version qemu which does not support bus... */
> +        virBufferAsprintf(&buf,
> +                          ",bus=scsi%d.0,channel=0,scsi-id=%d,lun=%d",
> +                          dev->info->addr.drive.controller,
> +                          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 (dev->info->bootIndex)
> +            virBufferAsprintf(&buf, ",bootindex=%d", dev->info->bootIndex);
> +    } else {
> +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                       _("unknown controller"));

Improper error:

_("Unsupport controller model '%s'"), 
virDomainControllerModelSCSITypeToString(controllerModel))

> +        goto error;
> +    }
> +    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
> @@ -7433,10 +7522,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 &&
> @@ -7453,6 +7543,39 @@ qemuBuildCommandLine(virConnectPtr conn,
>                                        " supported with this version of qemu"));
>                       goto error;
>                   }
> +                if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI &&
> +                    !virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_GENERIC_BOOTINDEX)) {
> +                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                                   _("booting from assigned SCSI devices is not"
> +                                     " supported with this version of qemu"));
> +                    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_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;
>               }
>           }
>   
> diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
> index 17687f4..188f899 100644
> --- a/src/qemu/qemu_command.h
> +++ b/src/qemu/qemu_command.h
> @@ -139,6 +139,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,




More information about the libvir-list mailing list