[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

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



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 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,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]