Il 26/04/2013 22:15, Osier Yang ha scritto: > With unknown good reasons, the attribute "bus" of scsi device > address is always set to 0, same for attribute "target". (See > virDomainDiskDefAssignAddress). The target is not always equal to zero... > Though we might need to change the algrithom to honor "bus" > and "target" too, it's another story. The address generator > for scsi host device in this patch just follows the unknown > good reasons, only considering the "controller" and "unit". > It walks through all scsi controllers and their units, to see > if the address $controller:0:0:$unit can be used, ... and $controller:0:0:$target:0 is preferrable to $controller:0:0:$unit. But having a different algorithm for disks vs. hostdevs would be worse, so this looks ok. Paolo > if found > one, it sits on it, otherwise, it creates a new controller > (actually the controller is created implicitly by someone > else), and sits on $new_controller:0:0:0 instead. > > --- > Since it needs to add the controllers for "drive" type address > implicitly, I add the generator in domain_conf.c instead of > the specific the driver, e.g. qemu. > --- > src/conf/domain_conf.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 138 insertions(+), 4 deletions(-) > > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c > index edbed89..8ab306f 100644 > --- a/src/conf/domain_conf.c > +++ b/src/conf/domain_conf.c > @@ -8556,8 +8556,141 @@ error: > return NULL; > } > > +/* Check if a drive type address $controller:0:0:$unit is already > + * taken by a disk or not. > + */ > +static bool > +virDomainDriveAddressIsUsedByDisk(virDomainDefPtr def, > + enum virDomainDiskBus type, > + unsigned int controller, > + unsigned int unit) > +{ > + virDomainDiskDefPtr disk; > + int i; > + > + for (i = 0; i < def->ndisks; i++) { > + disk = def->disks[i]; > + > + if (disk->bus != type || > + disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) > + continue; > + > + if (disk->info.addr.drive.controller == controller && > + disk->info.addr.drive.unit == unit && > + disk->info.addr.drive.bus == 0 && > + disk->info.addr.drive.target == 0) > + return true; > + } > + > + return false; > +} > + > +/* Check if a drive type address $controller:0:0:$unit is already > + * taken by a host device or not. > + */ > +static bool > +virDomainDriveAddressIsUsedByHostdev(virDomainDefPtr def, > + enum virDomainHostdevSubsysType type, > + unsigned int controller, > + unsigned int unit) > +{ > + virDomainHostdevDefPtr hostdev; > + int i; > + > + for (i = 0; i < def->nhostdevs; i++) { > + hostdev = def->hostdevs[i]; > + > + if (hostdev->source.subsys.type != type) > + continue; > + > + if (hostdev->info->addr.drive.controller == controller && > + hostdev->info->addr.drive.unit == unit && > + hostdev->info->addr.drive.bus == 0 && > + hostdev->info->addr.drive.target == 0) > + return true; > + } > + > + return false; > +} > + > +/* Find out the next usable "unit" of a specific controller */ > +static int > +virDomainControllerSCSINextUnit(virDomainDefPtr def, > + unsigned int max_unit, > + unsigned int controller) > +{ > + int i; > + > + for (i = 0; i < max_unit; i++) { > + /* The controller itself is on unit 7 */ > + if (max_unit == 16 && i == 7) > + continue; > + > + if (!virDomainDriveAddressIsUsedByDisk(def, > + VIR_DOMAIN_DISK_BUS_SCSI, controller, i) && > + !virDomainDriveAddressIsUsedByHostdev(def, > + VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI, controller, i)) > + return i; > + } > + > + return -1; > +} > + > +static int > +virDomainHostdevAssignAddress(virDomainXMLOptionPtr xmlopt, > + virDomainDefPtr def, > + virDomainHostdevDefPtr hostdev) > +{ > + unsigned int max_unit; > + int next_unit; > + unsigned nscsi_controllers; > + bool found; > + int i; > + > + if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) > + return -1; > + > + /* See comments in virDomainDiskDefAssignAddress */ > + if (xmlopt->config.hasWideScsiBus) > + max_unit = 16; > + else > + max_unit = 7; > + > + for (i = 0; i < def->ncontrollers; i++) { > + if (def->controllers[i]->type != VIR_DOMAIN_CONTROLLER_TYPE_SCSI) > + continue; > + > + nscsi_controllers++; > + next_unit = virDomainControllerSCSINextUnit(def, max_unit, > + def->controllers[i]->idx); > + if (next_unit >= 0) { > + found = true; > + break; > + } > + } > + > + hostdev->info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE; > + > + if (found) { > + hostdev->info->addr.drive.controller = def->controllers[i]->idx; > + hostdev->info->addr.drive.bus = 0; > + hostdev->info->addr.drive.target = 0; > + hostdev->info->addr.drive.unit = next_unit; > + } else { > + hostdev->info->addr.drive.controller = nscsi_controllers + 1; > + hostdev->info->addr.drive.bus = 0; > + hostdev->info->addr.drive.target = 0; > + hostdev->info->addr.drive.unit = 0; > + } > + > + return 0; > +} > + > + > static virDomainHostdevDefPtr > -virDomainHostdevDefParseXML(const xmlNodePtr node, > +virDomainHostdevDefParseXML(virDomainXMLOptionPtr xmlopt, > + virDomainDefPtr vmdef, > + const xmlNodePtr node, > xmlXPathContextPtr ctxt, > virHashTablePtr bootHash, > unsigned int flags) > @@ -8619,7 +8752,8 @@ virDomainHostdevDefParseXML(const xmlNodePtr node, > > break; > case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: > - if (def->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { > + if (def->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && > + virDomainHostdevAssignAddress(xmlopt, vmdef, def) < 0) { > virReportError(VIR_ERR_XML_ERROR, "%s", > _("SCSI host devices must have address specified")); > goto error; > @@ -9036,7 +9170,7 @@ virDomainDeviceDefParse(const char *xmlStr, > goto error; > } else if (xmlStrEqual(node->name, BAD_CAST "hostdev")) { > dev->type = VIR_DOMAIN_DEVICE_HOSTDEV; > - if (!(dev->data.hostdev = virDomainHostdevDefParseXML(node, ctxt, NULL, > + if (!(dev->data.hostdev = virDomainHostdevDefParseXML(xmlopt, def, node, ctxt, NULL, > flags))) > goto error; > } else if (xmlStrEqual(node->name, BAD_CAST "controller")) { > @@ -11374,7 +11508,7 @@ virDomainDefParseXML(xmlDocPtr xml, > for (i = 0 ; i < n ; i++) { > virDomainHostdevDefPtr hostdev; > > - hostdev = virDomainHostdevDefParseXML(nodes[i], ctxt, bootHash, flags); > + hostdev = virDomainHostdevDefParseXML(xmlopt, def, nodes[i], ctxt, bootHash, flags); > if (!hostdev) > goto error; > > -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list