[libvirt] [PATCH v2 3/6] qemu: add usb-bot support from disks points of view

Guannan Ren gren at redhat.com
Tue Sep 10 09:26:10 UTC 2013


usb-bot only supports 16 luns(0~15) and they must be contiguous,
(using lun 0 and 2 without 1 doesn't work). In this case qemu
doesn't throw an error, we can not find the lun 2 in guests. So
Adding a checking function in libvirt to prevent from this case.
---
 src/conf/domain_conf.c   | 59 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/conf/domain_conf.h   |  4 ++++
 src/libvirt_private.syms |  1 +
 src/qemu/qemu_command.c  | 32 ++++++++++++++++++++++++++
 4 files changed, 96 insertions(+)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 7fd9422..7a4969e 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -4302,6 +4302,65 @@ virDomainDiskDefAssignAddress(virDomainXMLOptionPtr xmlopt,
     return 0;
 }
 
+bool
+virDomainDiskAttachedToUsbbotLunIsContiguous(virDomainDefPtr def)
+{
+    size_t i;
+    int controllerModel;
+    virBitmapPtr units = NULL;
+    bool is_set = false;
+    bool ret = false;
+
+    if (!(units = virBitmapNew(SCSI_CONTROLLER_USB_BOT_MODEL_MAX_LUNS)))
+        goto cleanup;
+
+    for (i = 0; i < def->ndisks; i++) {
+        virDomainDiskDefPtr disk = def->disks[i];
+        int unitValue = disk->info.addr.drive.unit;
+
+        if (disk->bus != VIR_DOMAIN_DISK_BUS_SCSI)
+            continue;
+
+        controllerModel =
+            virDomainDeviceFindControllerModel(def, &disk->info,
+                                               VIR_DOMAIN_CONTROLLER_TYPE_SCSI);
+        if (controllerModel != VIR_DOMAIN_CONTROLLER_MODEL_SCSI_USB_BOT)
+            continue;
+
+        /* usb-bot only supports 16 luns */
+        if (unitValue & ~0xf) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("The address unit value of disk '%s' is too big"),
+                           disk->src);
+            goto cleanup;
+        }
+
+        if (virBitmapGetBit(units, unitValue, &is_set) == 0 && is_set) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("The address unit value of disk '%s' is already used"),
+                           disk->src);
+            goto cleanup;
+        }
+
+        if (unitValue > 0) {
+            if (virBitmapGetBit(units, unitValue - 1, &is_set) == 0 && !is_set) {
+                virReportError(VIR_ERR_XML_ERROR, "%s",
+                               _("The address unit value of disk "
+                                 "attached to usb-bot controller is not contiguous"));
+                goto cleanup;
+            }
+        }
+
+        ignore_value(virBitmapSetBit(units, unitValue));
+    }
+
+    ret = true;
+
+cleanup:
+    virBitmapFree(units);
+    return ret;
+}
+
 static virSecurityLabelDefPtr
 virSecurityLabelDefParseXML(xmlXPathContextPtr ctxt,
                             unsigned int flags)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 11ed18a..cea979f 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -781,6 +781,8 @@ typedef enum {
     VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST
 } virDomainControllerModelPCI;
 
+# define SCSI_CONTROLLER_USB_BOT_MODEL_MAX_LUNS 16
+
 enum virDomainControllerModelSCSI {
     VIR_DOMAIN_CONTROLLER_MODEL_SCSI_AUTO,
     VIR_DOMAIN_CONTROLLER_MODEL_SCSI_BUSLOGIC,
@@ -2365,6 +2367,8 @@ void virDomainDiskInsertPreAlloced(virDomainDefPtr def,
 int virDomainDiskDefAssignAddress(virDomainXMLOptionPtr xmlopt,
                                   virDomainDiskDefPtr def);
 
+bool virDomainDiskAttachedToUsbbotLunIsContiguous(virDomainDefPtr def);
+
 virDomainDiskDefPtr
 virDomainDiskRemove(virDomainDefPtr def, size_t i);
 virDomainDiskDefPtr
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 35f0f1b..c1f7da5 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -179,6 +179,7 @@ virDomainDeviceFindControllerModel;
 virDomainDeviceInfoCopy;
 virDomainDeviceInfoIterate;
 virDomainDeviceTypeToString;
+virDomainDiskAttachedToUsbbotLunIsContiguous;
 virDomainDiskBusTypeToString;
 virDomainDiskCacheTypeFromString;
 virDomainDiskCacheTypeToString;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index f40c050..1a6accd 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4316,6 +4316,32 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
                               disk->info.addr.drive.controller,
                               disk->info.addr.drive.bus,
                               disk->info.addr.drive.unit);
+        } else if (controllerModel == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_USB_BOT) {
+            if (disk->info.addr.drive.target != 0) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                               _("target must be 0 for controller "
+                                 "model 'usb-bot'"));
+                goto error;
+            }
+
+            if (disk->device != VIR_DOMAIN_DISK_DEVICE_LUN) {
+                if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_CD)) {
+                    if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
+                        virBufferAddLit(&opt, "scsi-cd");
+                    else
+                        virBufferAddLit(&opt, "scsi-hd");
+                } else {
+                    virBufferAddLit(&opt, "scsi-disk");
+                }
+            } else {
+                virBufferAddLit(&opt, "scsi-block");
+            }
+
+            virBufferAsprintf(&opt, ",bus=scsi%d.0,channel=%d,scsi-id=%d,lun=%d",
+                              disk->info.addr.drive.controller,
+                              disk->info.addr.drive.bus,
+                              disk->info.addr.drive.target,
+                              disk->info.addr.drive.unit);
         } else {
             if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_DISK_CHANNEL)) {
                 if (disk->info.addr.drive.target > 7) {
@@ -8149,6 +8175,12 @@ qemuBuildCommandLine(virConnectPtr conn,
         }
     }
 
+    /* For disks attached to SCSI usb-bot controller, their
+     * unit value must be contiguous.
+     */
+    if (!virDomainDiskAttachedToUsbbotLunIsContiguous(def))
+        goto error;
+
     if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) {
         for (j = 0; j < ARRAY_CARDINALITY(contOrder); j++) {
             for (i = 0; i < def->ncontrollers; i++) {
-- 
1.8.3.1




More information about the libvir-list mailing list