]> www.infradead.org Git - users/sagi/libnvme.git/commitdiff
Fix reading of system UUID on Debian
authorMartin Belanger <martin.belanger@dell.com>
Tue, 2 Nov 2021 19:21:50 +0000 (15:21 -0400)
committerDaniel Wagner <dwagner@suse.de>
Wed, 3 Nov 2021 12:38:40 +0000 (13:38 +0100)
The system UUID can be read from the sysfs in two different locations:

1) /sys/class/dmi/id/product_uuid
2) /sys/firmware/dmi/entries

Location 1) is present on all the systems I've tested: SUSE, Red Hat,
Fedora, and Ubuntu. Unfortunately, location 2) does not exist on
Debian-based systems.

Currently, uuid_from_dmi() only reads from location 2), which fails
on Debian.

This patch adds code that reads from location 1) first, and will
only try location 2) if reading from 1) fails.

Signed-off-by: Martin Belanger <martin.belanger@dell.com>
[dwagner: Updated return value from -1 to -ENXIO]
Signed-off-by: Daniel Wagner <dwagner@suse.de>
src/nvme/fabrics.c

index 94cecd0614915b8a196c7199838a82cb603a3591..21bcf2ab3d05ea25487d3807f2816301c5179592 100644 (file)
@@ -781,7 +781,7 @@ static int uuid_from_device_tree(char *system_uuid)
 
 #define PATH_DMI_ENTRIES       "/sys/firmware/dmi/entries"
 
-static int uuid_from_dmi(char *system_uuid)
+static int uuid_from_dmi_entries(char *system_uuid)
 {
        int f;
        DIR *d;
@@ -838,6 +838,66 @@ static int uuid_from_dmi(char *system_uuid)
        return strlen(system_uuid) ? 0 : -ENXIO;
 }
 
+/**
+ * @brief Get system UUID from /sys/class/dmi/id/product_uuid and fix
+ *        endianess.
+ *
+ * @param system_uuid - Where to save the system UUID.
+ *
+ * @return 0 on success, -ENXIO otherwise.
+ */
+#define PATH_DMI_PROD_UUID  "/sys/class/dmi/id/product_uuid"
+static int uuid_from_product_uuid(char *system_uuid)
+{
+       FILE *stream = NULL;
+       int   ret    = -ENXIO;
+
+       system_uuid[0] = '\0';
+
+       if ((stream = fopen(PATH_DMI_PROD_UUID, "re")) != NULL) {
+               char    *line  = NULL;
+               size_t   len   = 0;
+               ssize_t  nread = getline(&line, &len, stream);
+
+               if (nread == UUID_SIZE) {
+                       /* Per "DMTF SMBIOS 3.0 Section 7.2.1 System UUID", the
+                        * UUID retrieved from the DMI has the wrong endianess.
+                        * The following copies "line" to "system_uuid" while
+                        * swapping from little-endian to network-endian. */
+                       static const int swaptbl[] = {
+                               6,7,4,5,2,3,0,1,8,11,12,9,10,13,16,17,14,15,18,19,
+                               20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,
+                               -1 /* sentinel */
+                       };
+                       for (unsigned int i = 0; swaptbl[i] != -1; i++)
+                               system_uuid[i] = line[swaptbl[i]];
+                       system_uuid[UUID_SIZE-1] = '\0';
+                       ret = 0;
+               }
+
+               free(line);
+               fclose(stream);
+       }
+
+       return ret;
+}
+
+/**
+ * @brief The system UUID can be read from two different locations:
+ *
+ *     1) /sys/class/dmi/id/product_uuid
+ *     2) /sys/firmware/dmi/entries
+ *
+ * Note that the second location is not present on Debian-based systems.
+ */
+static int uuid_from_dmi(char *system_uuid)
+{
+       int ret = uuid_from_product_uuid(system_uuid);
+       if (ret != 0)
+               ret = uuid_from_dmi_entries(system_uuid);
+       return ret;
+}
+
 char *nvmf_hostnqn_generate()
 {
        char *hostnqn;