From: Martin Belanger Date: Tue, 2 Nov 2021 19:21:50 +0000 (-0400) Subject: Fix reading of system UUID on Debian X-Git-Tag: v1.0-rc0~62 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=d63abf207959b9fb7c0bbbae1ead5e46c433e5e8;p=users%2Fsagi%2Flibnvme.git Fix reading of system UUID on Debian 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 [dwagner: Updated return value from -1 to -ENXIO] Signed-off-by: Daniel Wagner --- diff --git a/src/nvme/fabrics.c b/src/nvme/fabrics.c index 94cecd06..21bcf2ab 100644 --- a/src/nvme/fabrics.c +++ b/src/nvme/fabrics.c @@ -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;