diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 9999a054d9..56943d51dd 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -469,19 +469,58 @@ static int qemuAssignDeviceDiskAliasFixed(virDomainDiskDefPtr disk) } static int -qemuDefaultScsiControllerModel(virDomainDefPtr def) { - if (STREQ(def->os.arch, "ppc64") && - STREQ(def->os.machine, "pseries")) { - return VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI; +qemuCheckScsiControllerModel(virDomainDefPtr def, + virBitmapPtr qemuCaps, + int *model) +{ + if (*model > 0) { + switch (*model) { + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC: + if (!qemuCapsGet(qemuCaps, QEMU_CAPS_SCSI_LSI)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("This QEMU doesn't support " + "lsi scsi controller")); + return -1; + } + break; + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI: + if (!qemuCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_SCSI_PCI)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("This QEMU doesn't support " + "virtio scsi controller")); + return -1; + } + break; + case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI: + /*TODO: need checking work here if necessary */ + break; + default: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unsupported controller model: %s"), + virDomainControllerModelSCSITypeToString(*model)); + return -1; + } } else { - return VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC; + if (STREQ(def->os.arch, "ppc64") && + STREQ(def->os.machine, "pseries")) { + *model = VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI; + } else if (qemuCapsGet(qemuCaps, QEMU_CAPS_SCSI_LSI)) { + *model = VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC; + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to determine model for scsi controller")); + return -1; + } } + + return 0; } /* Our custom -drive naming scheme used with id= */ static int qemuAssignDeviceDiskAliasCustom(virDomainDefPtr def, - virDomainDiskDefPtr disk) + virDomainDiskDefPtr disk, + virBitmapPtr qemuCaps) { const char *prefix = virDomainDiskBusTypeToString(disk->bus); int controllerModel = -1; @@ -491,11 +530,10 @@ qemuAssignDeviceDiskAliasCustom(virDomainDefPtr def, controllerModel = virDomainDiskFindControllerModel(def, disk, VIR_DOMAIN_CONTROLLER_TYPE_SCSI); - } - if (controllerModel == -1 || - controllerModel == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_AUTO) - controllerModel = qemuDefaultScsiControllerModel(def); + if ((qemuCheckScsiControllerModel(def, qemuCaps, &controllerModel)) < 0) + return -1; + } if (disk->bus != VIR_DOMAIN_DISK_BUS_SCSI || controllerModel == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC) { @@ -533,7 +571,7 @@ qemuAssignDeviceDiskAlias(virDomainDefPtr vmdef, { if (qemuCapsGet(qemuCaps, QEMU_CAPS_DRIVE)) { if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) - return qemuAssignDeviceDiskAliasCustom(vmdef, def); + return qemuAssignDeviceDiskAliasCustom(vmdef, def, qemuCaps); else return qemuAssignDeviceDiskAliasFixed(def); } else { @@ -850,13 +888,24 @@ qemuAssignSpaprVIOAddress(virDomainDefPtr def, virDomainDeviceInfoPtr info, return 0; } -int qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def) +int qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def, + virBitmapPtr qemuCaps) { - int i, rc; + int i, rc = -1; int model; + virBitmapPtr localCaps = NULL; /* Default values match QEMU. See spapr_(llan|vscsi|vty).c */ + if (!qemuCaps) { + /* need to get information from real environment */ + if (qemuCapsExtractVersionInfo(def->emulator, def->os.arch, + false, NULL, + &localCaps) < 0) + goto cleanup; + qemuCaps = localCaps; + } + for (i = 0 ; i < def->nnets; i++) { if (def->nets[i]->model && STREQ(def->nets[i]->model, "spapr-vlan")) @@ -864,21 +913,24 @@ int qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def) rc = qemuAssignSpaprVIOAddress(def, &def->nets[i]->info, 0x1000ul); if (rc) - return rc; + goto cleanup; } for (i = 0 ; i < def->ncontrollers; i++) { model = def->controllers[i]->model; - if (model == -1 && - def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) - model = qemuDefaultScsiControllerModel(def); + if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) { + rc = qemuCheckScsiControllerModel(def, qemuCaps, &model); + if (rc) + goto cleanup; + } + if (model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI && def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO; rc = qemuAssignSpaprVIOAddress(def, &def->controllers[i]->info, 0x2000ul); if (rc) - return rc; + goto cleanup; } for (i = 0 ; i < def->nserials; i++) { @@ -890,12 +942,16 @@ int qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def) rc = qemuAssignSpaprVIOAddress(def, &def->serials[i]->info, 0x30000000ul); if (rc) - return rc; + goto cleanup; } /* No other devices are currently supported on spapr-vio */ - return 0; + rc = 0; + +cleanup: + qemuCapsFree(localCaps); + return rc; } #define QEMU_PCI_ADDRESS_LAST_SLOT 31 @@ -1059,7 +1115,7 @@ int qemuDomainAssignAddresses(virDomainDefPtr def, { int rc; - rc = qemuDomainAssignSpaprVIOAddresses(def); + rc = qemuDomainAssignSpaprVIOAddresses(def, qemuCaps); if (rc) return rc; @@ -2433,9 +2489,8 @@ qemuBuildDriveDevStr(virDomainDefPtr def, controllerModel = virDomainDiskFindControllerModel(def, disk, VIR_DOMAIN_CONTROLLER_TYPE_SCSI); - if (controllerModel == -1 || - controllerModel == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_AUTO) - controllerModel = qemuDefaultScsiControllerModel(def); + if ((qemuCheckScsiControllerModel(def, qemuCaps, &controllerModel)) < 0) + goto error; if (controllerModel == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC) { if (disk->info.addr.drive.target != 0) { @@ -2764,10 +2819,9 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef, switch (def->type) { case VIR_DOMAIN_CONTROLLER_TYPE_SCSI: model = def->model; - if (model == -1 || - model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_AUTO) { - model = qemuDefaultScsiControllerModel(domainDef); - } + if ((qemuCheckScsiControllerModel(domainDef, qemuCaps, &model)) < 0) + return NULL; + switch (model) { case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI: virBufferAddLit(&buf, "virtio-scsi-pci"); diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index 946a7acd04..e999bc79b6 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -180,7 +180,8 @@ virDomainDefPtr qemuParseCommandLinePid(virCapsPtr caps, int qemuDomainAssignAddresses(virDomainDefPtr def, virBitmapPtr qemuCaps, virDomainObjPtr); -int qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def); +int qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def, + virBitmapPtr qemuCaps); int qemuDomainAssignPCIAddresses(virDomainDefPtr def, virBitmapPtr qemuCaps, diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 3a08c5bcdf..df4a016040 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3120,7 +3120,8 @@ qemuProcessReconnect(void *opaque) } if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) - qemuDomainAssignAddresses(obj->def, priv->qemuCaps, obj); + if ((qemuDomainAssignAddresses(obj->def, priv->qemuCaps, obj)) < 0) + goto error; if (virSecurityManagerReserveLabel(driver->securityManager, obj->def, obj->pid) < 0) goto error; @@ -3585,7 +3586,8 @@ int qemuProcessStart(virConnectPtr conn, */ if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) { VIR_DEBUG("Assigning domain PCI addresses"); - qemuDomainAssignAddresses(vm->def, priv->qemuCaps, vm); + if ((qemuDomainAssignAddresses(vm->def, priv->qemuCaps, vm)) < 0) + goto cleanup; } VIR_DEBUG("Building emulator command line"); @@ -4267,7 +4269,8 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED, */ if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) { VIR_DEBUG("Assigning domain PCI addresses"); - qemuDomainAssignAddresses(vm->def, priv->qemuCaps, vm); + if ((qemuDomainAssignAddresses(vm->def, priv->qemuCaps, vm)) < 0) + goto cleanup; } if ((timestamp = virTimeStringNow()) == NULL) { diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 1adba78e98..f8d8db56f1 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -458,16 +458,19 @@ mymain(void) DO_TEST("disk-usb-device", QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG); DO_TEST("disk-scsi-device", - QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG); + QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_SCSI_LSI); DO_TEST("disk-scsi-device-auto", - QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG); + QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_SCSI_LSI); DO_TEST("disk-scsi-disk-split", QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, - QEMU_CAPS_SCSI_CD); + QEMU_CAPS_SCSI_CD, QEMU_CAPS_SCSI_LSI, QEMU_CAPS_VIRTIO_SCSI_PCI); DO_TEST("disk-scsi-vscsi", QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG); DO_TEST("disk-scsi-virtio-scsi", - QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG); + QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_VIRTIO_SCSI_PCI); DO_TEST("disk-sata-device", QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_ICH9_AHCI); @@ -497,7 +500,8 @@ mymain(void) DO_TEST("disk-scsi-lun-passthrough", QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, - QEMU_CAPS_SCSI_BLOCK, QEMU_CAPS_VIRTIO_BLK_SG_IO); + QEMU_CAPS_SCSI_BLOCK, QEMU_CAPS_VIRTIO_BLK_SG_IO, + QEMU_CAPS_SCSI_LSI, QEMU_CAPS_VIRTIO_SCSI_PCI); DO_TEST("graphics-vnc", NONE); DO_TEST("graphics-vnc-socket", NONE); @@ -757,7 +761,7 @@ mymain(void) DO_TEST("multifunction-pci-device", QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, - QEMU_CAPS_PCI_MULTIFUNCTION); + QEMU_CAPS_PCI_MULTIFUNCTION, QEMU_CAPS_SCSI_LSI); DO_TEST("monitor-json", QEMU_CAPS_DEVICE, QEMU_CAPS_CHARDEV, QEMU_CAPS_MONITOR_JSON, QEMU_CAPS_NODEFCONFIG);