[libvirt] [PATCH 4/6] qemu: add usb scsi controller support

Guannan Ren gren at redhat.com
Mon Jan 14 09:04:23 UTC 2013


UAS(usb attached scsi) works like other scsi HBA emulation
(lsi, virtio). For now only usb2.0 transport is supported.
It only provides one scsi target with up to 256 luns.

For usb scsi controller, the <address> subelment become
mandatory rather than optional. Because each of them needs a
usb port on usb controller with usb2.0, when there are multiple
usb-scsi controllers with some of them having <address> and some of
them not having <address>, it is hard to validate address info
or pick up a valid port for them that doesn't have <address>
subelement automatically.

libvirt XML snip
 <devices>
   <controller type='usb' index='2' model='ehci'>
   </controller>
   <controller type='scsi' index='0' model='usb-scsi'>
     <address type='usb' bus='2' port='1'/>
   </controller>
 </devices>

qemu commandline:
qemu ${other_vm_args}              \
     -device usb-ehci,id=usb2,bus=pci.0,addr=0x8 \
     -device usb-uas,id=scsi0,bus=usb2.0,port=1
---
 docs/formatdomain.html.in |  25 ++++++++++-
 src/conf/domain_conf.c    | 112 ++++++++++++++++++++++++++++++++++++++++++++--
 src/conf/domain_conf.h    |   1 +
 src/qemu/qemu_command.c   |  10 +++++
 src/vmx/vmx.c             |   3 +-
 5 files changed, 146 insertions(+), 5 deletions(-)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index bb0b199..89dc766 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -2055,7 +2055,30 @@
       control how many devices can be connected through the
       controller.  A "scsi" controller has an optional
       attribute <code>model</code>, which is one of "auto", "buslogic",
-      "ibmvscsi", "lsilogic", "lsias1068", "virtio-scsi" or "vmpvscsi".
+      "ibmvscsi", "lsilogic", "lsias1068", "virtio-scsi", "vmpvscsi",
+      "usb-scsi". usb-scsi <span class="since">(since 1.0.2)</span> is
+      a pure UAS (usb attached scsi) emulation which works like any other
+      scsi controller. It provides a single scsi target with up to 256
+      luns. usb-scsi is a USB2.0 device, so it also needs a usb controller
+      (Described below) which supports usb 2.0 transport, like model "ehci",
+      "nec-xhci". The <code><address></code>
+      <a href="#elementsAddress">documented above</a> can be used for
+      usb-scsi scsi controller to attach to USB2.0 controller. Note that
+      the <code><address></code> is mandatory.
+    </p>
+
+<pre>
+  ...
+  <devices>
+    <controller type='usb' index='1' model='ehci'/>
+    <controller type='scsi' index='0' model='usb-scsi'>
+      <address type='usb' bus='1' port='1'/>
+    </controller>
+    ...
+  </devices>
+  ...</pre>
+
+    <p>
       A "usb" controller has an optional attribute <code>model</code>,
       which is one of "piix3-uhci", "piix4-uhci", "ehci",
       "ich9-ehci1", "ich9-uhci1", "ich9-uhci2", "ich9-uhci3",
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index a0946cc..8b4e7e6 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -278,7 +278,8 @@ VIR_ENUM_IMPL(virDomainControllerModelSCSI, VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAS
               "lsisas1068",
               "vmpvscsi",
               "ibmvscsi",
-              "virtio-scsi");
+              "virtio-scsi",
+              "usb-scsi");
 
 VIR_ENUM_IMPL(virDomainControllerModelUSB, VIR_DOMAIN_CONTROLLER_MODEL_USB_LAST,
               "piix3-uhci",
@@ -4556,6 +4557,15 @@ virDomainControllerDefParseXML(xmlNodePtr node,
         goto error;
 
     switch (def->type) {
+    case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
+        if (def->model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_USB_UAS &&
+            def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("usb scsi model of scsi controller requires "
+                             "<address> subelement with type 'usb'"));
+            goto error;
+        }
+        break;
     case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL: {
         char *ports = virXMLPropString(node, "ports");
         if (ports) {
@@ -4618,9 +4628,10 @@ virDomainControllerDefParseXML(xmlNodePtr node,
     if (def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
         def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO &&
         def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390 &&
-        def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+        def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI &&
+        def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                       _("Controllers must use the 'pci' address type"));
+                       _("Controllers have incorrect address type"));
         goto error;
     }
 
@@ -8917,6 +8928,98 @@ cleanup:
     return ret;
 }
 
+static int
+virDomainSCSIControllerUASRequireUSB20(virDomainDefPtr def)
+{
+    size_t i, j;
+    size_t nuass = 0, nusbs = 0;
+    int ret = -1;
+    virDomainControllerDefPtr *uas = NULL, *usb = NULL;
+    virDomainControllerDefPtr temp;
+
+    /* Filter out uas scsi controllers and usb controllers
+     * which support USB2.0 Spec.
+     */
+    for (i = 0; i < def->ncontrollers; i++) {
+        temp = def->controllers[i];
+        if (temp->type != VIR_DOMAIN_CONTROLLER_TYPE_USB &&
+            temp->type != VIR_DOMAIN_CONTROLLER_TYPE_SCSI)
+            continue;
+
+        if (temp->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
+            if (temp->model != VIR_DOMAIN_CONTROLLER_MODEL_SCSI_USB_UAS)
+                continue;
+
+            if (VIR_REALLOC_N(uas, nuass + 1) < 0) {
+                virReportOOMError();
+                goto cleanup;
+            }
+            uas[nuass++] = temp;
+        }
+
+        if (temp->type == VIR_DOMAIN_CONTROLLER_TYPE_USB) {
+            if (temp->model < 0 ||
+                !(temp->data.usb.spec & VIR_DOMAIN_USB_SPEC_2_0))
+                continue;
+
+            if (VIR_REALLOC_N(usb, nusbs + 1) < 0) {
+                virReportOOMError();
+                goto cleanup;
+            }
+            usb[nusbs++] = temp;
+        }
+    }
+
+    if (!nuass) {
+        ret = 0;
+        goto cleanup;
+    }
+
+    if (!nusbs) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("usb-scsi model of SCSI controller requires "
+                         "at least one USB2.0 controller"));
+        goto cleanup;
+    }
+
+    for (i = 0; i < nuass; i++) {
+        bool found = false;
+        if (uas[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("usb-scsi model of SCSI controller "
+                             "doesn't have bus info"));
+            goto cleanup;
+        }
+
+        for (j = 0; j < nusbs; j++) {
+            if (uas[i]->info.addr.usb.bus == usb[j]->idx)
+                found = true;
+        }
+
+        if (!found) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("The address info of usb-scsi controller "
+                             "does not refer to USB2.0 controller"));
+            goto cleanup;
+        }
+    }
+    ret = 0;
+
+cleanup:
+    VIR_FREE(uas);
+    VIR_FREE(usb);
+    return ret;
+}
+
+static int
+virDomainControllerCheckConsistency(virDomainDefPtr def)
+{
+
+   if (virDomainSCSIControllerUASRequireUSB20(def) < 0)
+       return -1;
+
+   return 0;
+}
 
 static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
                                             xmlDocPtr xml,
@@ -9856,6 +9959,9 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
     }
     VIR_FREE(nodes);
 
+    if (virDomainControllerCheckConsistency(def) < 0)
+        goto error;
+
     if (def->virtType == VIR_DOMAIN_VIRT_QEMU ||
         def->virtType == VIR_DOMAIN_VIRT_KQEMU ||
         def->virtType == VIR_DOMAIN_VIRT_KVM)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 67143a5..9801dbf 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -674,6 +674,7 @@ enum virDomainControllerModelSCSI {
     VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VMPVSCSI,
     VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI,
     VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI,
+    VIR_DOMAIN_CONTROLLER_MODEL_SCSI_USB_UAS,
 
     VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST
 };
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 78276b5..d459be0 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -506,6 +506,13 @@ qemuSetScsiControllerModel(virDomainDefPtr def,
                 return -1;
             }
             break;
+        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_USB_UAS:
+            if (!qemuCapsGet(caps, QEMU_CAPS_DEVICE_USB_UAS)) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                               _("This QEMU doesn't support "
+                                 "usb-scsi controller"));
+                return -1;
+            }
         case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI:
             /*TODO: need checking work here if necessary */
             break;
@@ -3068,6 +3075,9 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef,
         case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI:
             virBufferAddLit(&buf, "spapr-vscsi");
             break;
+        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_USB_UAS:
+            virBufferAddLit(&buf, "usb-uas");
+            break;
         default:
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                            _("Unsupported controller model: %s"),
diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c
index c604bd2..65efa2d 100644
--- a/src/vmx/vmx.c
+++ b/src/vmx/vmx.c
@@ -511,7 +511,8 @@ VIR_ENUM_IMPL(virVMXControllerModelSCSI, VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST,
               "lsisas1068",
               "pvscsi",
               "UNUSED ibmvscsi",
-              "UNUSED virtio-scsi");
+              "UNUSED virtio-scsi",
+              "UNUSED usb-scsi");
 
 
 
-- 
1.7.11.4




More information about the libvir-list mailing list