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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list