[libvirt] [PATCH 10/10] conf: Generate address for scsi host device automatically
Paolo Bonzini
pbonzini at redhat.com
Fri Apr 26 22:07:20 UTC 2013
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;
>
>
More information about the libvir-list
mailing list