[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