[libvirt] [PATCH 10/11] util: Add a util to guess the scsi host name with specified "parent"

John Ferlan jferlan at redhat.com
Wed Jun 19 18:53:49 UTC 2013


On 06/07/2013 01:03 PM, Osier Yang wrote:
> Not really guessing, it returns host name of the scsi host which has
> smallest unique_id.
> ---
>  src/libvirt_private.syms |   1 +
>  src/util/virutil.c       | 122 +++++++++++++++++++++++++++++++++++++++++++++++
>  src/util/virutil.h       |   4 ++
>  tests/utiltest.c         |  27 +++++++++++
>  4 files changed, 154 insertions(+)
> 
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 27fb0b5..ec85079 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -1948,6 +1948,7 @@ virGetUserDirectory;
>  virGetUserID;
>  virGetUserName;
>  virGetUserRuntimeDirectory;
> +virGuessStableScsiHostName;
>  virHexToBin;
>  virIndexToDiskName;
>  virIsCapableFCHost;
> diff --git a/src/util/virutil.c b/src/util/virutil.c
> index a80574f..7f36e27 100644
> --- a/src/util/virutil.c
> +++ b/src/util/virutil.c
> @@ -2256,6 +2256,120 @@ cleanup:
>      }
>      return ret;
>  }
> +
> +static int
> +virGuessStableScsiHostNameCallback(const char *fpath,
> +                                   void *opaque)
> +{
> +    const char *filename = opaque;
> +    char *p = NULL;
> +
> +    p = strrchr(fpath, '/');
> +    p++;
> +
> +    if (STREQ(p, filename))
> +        return 0;
> +    return -1;
> +}
> +
> +/**
> + * virGuessStableScsiHostName:
> + * @sysfs_prefix: The directory path where starts to traverse, defaults
> + *                to SYSFS_BUS_PCI_DEVICES.
> + * @addr: The parent's PCI address
> + *
> + * Returns the host name (e.g. host10) of the scsi host whose parent
> + * has address @addr, and "unique_id" has the smallest value on success.
> + * Or NULL on failure.

It is up to the caller to free the memory returned.

> + */
> +char *
> +virGuessStableScsiHostName(const char *sysfs_prefix,
> +                           const char *address)
> +{
> +    const char *prefix = sysfs_prefix ? sysfs_prefix : SYSFS_BUS_PCI_DEVICES;
> +    unsigned int flags = 0;
> +    char **paths = NULL;
> +    int npaths = 0;
> +    char *smallest_path = NULL;
> +    unsigned int smallest;
> +    char *dir = NULL;
> +    char *buf = NULL;
> +    char *p1 = NULL;
> +    char *p2 = NULL;
> +    char *ret = NULL;
> +    int i;
> +
> +    const char *filename = "unique_id";
> +
> +    if (virAsprintf(&dir, "%s/%s", prefix, address) < 0) {
> +        virReportOOMError();
> +        return NULL;
> +    }
> +
> +    flags |= (VIR_TRAVERSE_DIRECTORY_IGNORE_HIDDEN_FILES |
> +              VIR_TRAVERSE_DIRECTORY_FALL_THROUGH);
> +
> +    if ((npaths = virTraverseDirectory(dir, 4, flags,
> +                                       virGuessStableScsiHostNameCallback,
> +                                       NULL, (void *)filename, &paths)) < 0)
> +        goto cleanup;
> +

>From here...

> +    smallest_path = paths[0];
> +    if (virFileReadAll(paths[0], 1024, &buf) < 0)
> +        goto cleanup;
> +
> +    if ((p1 = strchr(buf, '\n')))
> +        *p1 = '\0';
> +
> +    if (virStrToLong_ui(buf, NULL, 10, &smallest) < 0)
> +        goto cleanup;
> +
> +    VIR_FREE(buf);
> +    buf = NULL;
...to here isn't necessary... and if you keep it, then the loop below
goes from 1 to npaths since 0 is already covered...

> +
> +    for (i = 0; i < npaths; i++) {
> +        unsigned int rc;
> +
> +        if (virFileReadAll(paths[i], 1024, &buf) < 0)
> +            goto cleanup;
> +
> +        if ((p1 = strchr(buf, '\n')))
> +            *p1 = '\0';
> +
> +        if (virStrToLong_ui(buf, NULL, 10, &rc) < 0)
> +            goto cleanup;
> +
> +        if (rc < smallest)
> +            smallest_path = paths[i];

           if (!smallest_path || (rc < smallest)) {
               smallest_path = paths[i];
               smallest = rc
           }

The (!smallest_path) is only necessary if you cut as noted above, but
the resetting of smallest to rc would seem to be required in either case.

> +
> +        VIR_FREE(buf);
> +        buf = NULL;

The buf = NULL is superfluous

John

> +    }
> +
> +    if (!(p1 = strstr(smallest_path, "scsi_host"))) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("Unexpected path '%s' for PCI address "
> +                         "'%s' unique_id '%u'"), smallest_path,
> +                         address, smallest);
> +        goto cleanup;
> +    }
> +
> +    p1 += strlen("scsi_host");
> +    p2 = strrchr(p1, '/');
> +
> +    if (VIR_STRNDUP(ret, p1 + 1, p2 - p1 -1) < 0)
> +        goto cleanup;
> +
> +cleanup:
> +    VIR_FREE(dir);
> +    VIR_FREE(buf);
> +    if (npaths > 0) {
> +        for (i = 0; i < npaths; i++)
> +            VIR_FREE(paths[i]);
> +        VIR_FREE(paths);
> +    }
> +    return ret;
> +}
>  #else
>  int
>  virReadFCHost(const char *sysfs_prefix ATTRIBUTE_UNUSED,
> @@ -2326,6 +2440,14 @@ virParseStableScsiHostAddress(const char *sysfs_prefix,
>      virReportSystemError(ENOSYS, "%s", _("Not supported on this platform"));
>      return NULL;
>  }
> +
> +char *
> +virGuessStableScsiHostName(const char *sysfs_prefix,
> +                           const char *address)
> +{
> +    virReportSystemError(ENOSYS, "%s", _("Not supported on this platform"));
> +    return NULL;
> +}
>  #endif /* __linux__ */
>  
>  /**
> diff --git a/src/util/virutil.h b/src/util/virutil.h
> index 2747cf1..10b3f6f 100644
> --- a/src/util/virutil.h
> +++ b/src/util/virutil.h
> @@ -226,7 +226,11 @@ char *virFindPCIDeviceByVPD(const char *sysfs_prefix,
>  char *virParseStableScsiHostAddress(const char *sysfs_prefix,
>                                      const char *address,
>                                      unsigned int unique_id)
> +    ATTRIBUTE_NONNULL(2);
>  
> +char *
> +virGuessStableScsiHostName(const char *sysfs_prefix,
> +                           const char *address)
>      ATTRIBUTE_NONNULL(2);
>  
>  #endif /* __VIR_UTIL_H__ */
> diff --git a/tests/utiltest.c b/tests/utiltest.c
> index d567ecc..0cfcead 100644
> --- a/tests/utiltest.c
> +++ b/tests/utiltest.c
> @@ -226,6 +226,32 @@ cleanup:
>  }
>  
>  static int
> +testGuessStableScsiHostName(const void *data ATTRIBUTE_UNUSED)
> +{
> +    const char *addr = "0000:00:1f.2";
> +    char *dir = NULL;
> +    char *rc = NULL;
> +    int ret = -1;
> +
> +    if (virAsprintf(&dir, "%s/%s", TEST_SYSFS, "bus/pci/devices") < 0) {
> +        virReportOOMError();
> +        return -1;
> +    }
> +
> +    if (!(rc = virGuessStableScsiHostName(dir, addr)))
> +        goto cleanup;
> +
> +    if (STRNEQ(rc, "host2"))
> +        goto cleanup;
> +
> +    ret = 0;
> +cleanup:
> +    VIR_FREE(dir);
> +    VIR_FREE(rc);
> +    return ret;
> +}
> +
> +static int
>  testStringPad(const void *data ATTRIBUTE_UNUSED)
>  {
>      const char *str = "1ff2";
> @@ -278,6 +304,7 @@ mymain(void)
>      DO_TEST(ParseVersionString);
>      DO_TEST(FindPCIDeviceByVPD);
>      DO_TEST(ParseStableScsiHostAddress);
> +    DO_TEST(GuessStableScsiHostName);
>      DO_TEST(StringPad);
>  
>  cleanup:
> 




More information about the libvir-list mailing list