[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