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 545c157..84dfe25 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -4287,6 +4287,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 3e69f84..9e2f477 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -778,6 +778,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,
@@ -2362,6 +2364,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 5f08a72..f38e98f 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4257,6 +4257,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) {
@@ -8040,6 +8066,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