[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

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



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.
+ */
+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;
+
+    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;
+
+    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];
+
+        VIR_FREE(buf);
+        buf = NULL;
+    }
+
+    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:
-- 
1.8.1.4


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]