[libvirt] [PATCH 09/11] storage_scsi: Allow the direct PCI address for 'parent'

Osier Yang jyang at redhat.com
Fri Jun 7 17:16:51 UTC 2013


On 08/06/13 01:03, Osier Yang wrote:
> To be more flexible, except allowing to specify 'parent' with name
> produced by node device udev/HAL backends, this supports to specify
> 'parent' with PCI address directly (e.g.  0000:00:1f:2). The specified
> address will be padded if it's not consistent with what sysfs exposed.
> (e.g 0:0:2:2 will be padded to 0000:00:02:2).
> ---
>   src/storage/storage_backend_scsi.c | 117 +++++++++++++++++++++++++++++--------
>   1 file changed, 93 insertions(+), 24 deletions(-)
>
> diff --git a/src/storage/storage_backend_scsi.c b/src/storage/storage_backend_scsi.c
> index a77b9ae..5635f73 100644
> --- a/src/storage/storage_backend_scsi.c
> +++ b/src/storage/storage_backend_scsi.c
> @@ -604,51 +604,120 @@ out:
>   static char *
>   getScsiHostParentAddress(const char *parent)
>   {
> +    virBuffer buf = VIR_BUFFER_INITIALIZER;
>       char **tokens = NULL;
>       char *vendor = NULL;
>       char *product = NULL;
>       char *ret = NULL;
> -    int len;
> +    int length;
> +    int i;
>   
> -    if (!strchr(parent, '_')) {
> +    if (!strchr(parent, '_') &&
> +        !strchr(parent, ':')) {
>           virReportError(VIR_ERR_XML_ERROR, "%s",
> -                       _("'parent' of scsi_host adapter must "
> -                         "be consistent with name of node device"));
> +                       _("'parent' of scsi_host adapter must be "
> +                         "either consistent with name of mode "
> +                         "device, or in domain:bus:slot:function "
> +                         "format"));
>           return NULL;
>       }
>   
> -    if (!(tokens = virStringSplit(parent, "_", 0)))
> -        return NULL;
> +    if (strchr(parent, '_')) {
> +        if (!(tokens = virStringSplit(parent, "_", 0)))
> +            return NULL;
>   
> -    len = virStringListLength(tokens);
> +        length = virStringListLength(tokens);
> +
> +        switch (length) {
> +        case 4:
> +            if (!(ret = virStringJoin((const char **)(&tokens[1]), ":")))
> +                goto cleanup;
> +            break;
>   
> -    switch (len) {
> -    case 4:
> -        if (!(ret = virStringJoin((const char **)(&tokens[1]), ":")))
> +        case 2:
> +            vendor = tokens[1];
> +            product = tokens[2];
> +            if (!(ret = virFindPCIDeviceByVPD(NULL, vendor, product))) {
> +                virReportError(VIR_ERR_INTERNAL_ERROR,
> +                               _("Unable to find PCI device with vendor '%s' "
> +                                 "product '%s'"), vendor, product);
> +                goto cleanup;
> +            }
> +
> +            break;
> +        default:
> +            virReportError(VIR_ERR_XML_ERROR, "%s",
> +                       _("'parent' of scsi_host adapter must be "
> +                         "either consistent with name of mode "
> +                         "device, or in domain:bus:slot:function "
> +                         "format"));
>               goto cleanup;
> -        break;
> +        }
> +    } else if (strchr(parent, ':')) {
> +        char *padstr = NULL;
> +
> +        if (!(tokens = virStringSplit(parent, ":", 0)))
> +            return NULL;
>   
> -    case 2:
> -        vendor = tokens[1];
> -        product = tokens[2];
> -        if (!(ret = virFindPCIDeviceByVPD(NULL, vendor, product))) {
> -            virReportError(VIR_ERR_INTERNAL_ERROR,
> -                           _("Unable to find PCI device with vendor '%s' "
> -                             "product '%s'"), vendor, product);
> +        length = virStringListLength(tokens);
> +
> +        if (length != 4) {
> +            virReportError(VIR_ERR_XML_ERROR,
> +                           _("invalid PCI address for scsi_host "
> +                             "'parent' '%s'"), parent);
>               goto cleanup;
>           }
>   
> -        break;
> -    default:
> -        virReportError(VIR_ERR_XML_ERROR, "%s",
> -                       _("'parent' of scsi_host adapter must "
> -                         "be consistent with name of node device"));
> -        goto cleanup;
> +        for (i = 0; i < length; i++) {
> +            if (strlen(tokens[i]) == 0) {
> +                virReportError(VIR_ERR_XML_ERROR,
> +                               _("invalid PCI address for scsi_host "
> +                                 "'parent' '%s'"), parent);
> +                goto cleanup;
> +            }
> +        }
> +
> +        /* sysfs always exposes the PCI address like "0000:00:1f:2",
> +         * this do the padding if the address prodived by user is
> +         * not padded (e.g. 0:0:2:0).
> +         */
> +        if (strlen(tokens[0]) != 4) {
> +            if (!(padstr = virStringPad(tokens[0], '0', 4, false)))
> +                goto cleanup;
> +
> +            virBufferAsprintf(&buf, "%s", padstr);
> +            VIR_FREE(padstr);
> +        } else {
> +            virBufferAsprintf(&buf, "%s", tokens[0]);
> +        }
> +
> +        for (i = 1; i < 3; i++) {
> +            if (strlen(tokens[i]) != 2) {
> +                if (!(padstr = virStringPad(tokens[i], '0', 2, false)))
> +                    goto error;
> +                virBufferAsprintf(&buf, "%s", padstr);
With the attached diff squashed in:

-------------- next part --------------
diff --git a/src/storage/storage_backend_scsi.c b/src/storage/storage_backend_scsi.c
index da6a5dd..05af408 100644
--- a/src/storage/storage_backend_scsi.c
+++ b/src/storage/storage_backend_scsi.c
@@ -695,13 +695,15 @@ getScsiHostParentAddress(const char *parent)
             if (strlen(tokens[i]) != 2) {
                 if (!(padstr = virStringPad(tokens[i], '0', 2, false)))
                     goto error;
-                virBufferAsprintf(&buf, "%s", padstr);
+                virBufferAsprintf(&buf, ":%s", padstr);
                 VIR_FREE(padstr);
             } else {
-                virBufferAsprintf(&buf, "%s", tokens[i]);
+                virBufferAsprintf(&buf, ":%s", tokens[i]);
             }
         }
 
+        virBufferAsprintf(&buf, ":%s", tokens[3]);
+
         if (virBufferError(&buf)) {
             virBufferFreeAndReset(&buf);
             virReportOOMError();


More information about the libvir-list mailing list