diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 5940f05013..9ee9b44a5e 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4808,11 +4808,52 @@ bool virDomainSCSIDriveAddressIsUsed(const virDomainDef *def, const virDomainDeviceDriveAddress *addr) { - /* In current implementation, the maximum unit number of a controller - * is either 16 or 7 (narrow SCSI bus), and if the maximum unit number - * is 16, the controller itself is on unit 7 */ - if (addr->unit == 7) - return true; + const virDomainControllerDef *cont; + + cont = virDomainDeviceFindSCSIController(def, addr); + if (cont) { + int max = -1; + int reserved = -1; + + /* Different controllers have different limits. These limits here are + * taken from QEMU source code, but nevertheless they should apply to + * other hypervisors too. */ + switch ((virDomainControllerModelSCSI) cont->model) { + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI: + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_TRANSITIONAL: + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_NON_TRANSITIONAL: + max = 16383; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI: + max = 31; + reserved = 7; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1068: + max = 1; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1078: + max = 255; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC: + reserved = 7; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VMPVSCSI: + reserved = 7; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_BUSLOGIC: + reserved = 7; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_DEFAULT: + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_AUTO: + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST: + break; + } + + if (max != -1 && addr->unit >= max) + return true; + if (reserved != -1 && addr->unit == reserved) + return true; + } if (virDomainDriveAddressIsUsedByDisk(def, VIR_DOMAIN_DISK_BUS_SCSI, addr) ||