
On 20/06/13 02:53, John Ferlan wrote:
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.
Yes, will add
+ */ +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...
Hm, stupid mistake... Thanks. Osier