From: Hannes Reinecke Date: Wed, 24 Mar 2021 07:22:28 +0000 (+0100) Subject: Read system UUID from DMI and merge hostnqn generation functions X-Git-Tag: v1.14~32 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=3e0520ecad13b768519ca6b402d8be86e2a48c6b;p=users%2Fsagi%2Fnvme-cli.git Read system UUID from DMI and merge hostnqn generation functions Both fabrics.c and the 'gen-hostnqn' command contain functions to generate a default host NQN. Needless to say, both are different. _And_ we have the script 'nvme-gen-hostnqn' to read the host nqn from the system UUID, implement yet another way. This patch merges all of these functions, and implements a hierarchy in generating host NQNs: - Try reading system UUID from /sys/firmware/dmi/entries - Try reading systemd-generated UUID - Generate a random UUID Signed-off-by: Hannes Reinecke --- diff --git a/fabrics.c b/fabrics.c index 1615901e..ea8380a4 100644 --- a/fabrics.c +++ b/fabrics.c @@ -818,6 +818,18 @@ static char *hostnqn_generate_systemd(void) #endif } +static char *hostnqn_read_dmi(void) +{ + char uuid[16]; + char *ret = NULL; + + if (uuid_from_dmi(uuid) < 0) + return NULL; + if (asprintf(&ret, "nqn.2014-08.org.nvmexpress:uuid:%s", uuid) == -1) + return NULL; + return ret; +} + /* returns an allocated string or NULL */ char *hostnqn_read(void) { @@ -827,6 +839,10 @@ char *hostnqn_read(void) if (ret) return ret; + ret = hostnqn_read_dmi(); + if (ret) + return ret; + ret = hostnqn_generate_systemd(); if (ret) return ret; diff --git a/nvme-topology.c b/nvme-topology.c index 63e433d7..db0714f7 100644 --- a/nvme-topology.c +++ b/nvme-topology.c @@ -696,3 +696,76 @@ void *mmap_registers(const char *dev) return membase; } +#define PATH_DMI_ENTRIES "/sys/firmware/dmi/entries" + +int uuid_from_dmi(char *system_uuid) +{ + int f; + DIR *d; + struct dirent *de; + char buf[512]; + + system_uuid[0] = '\0'; + d = opendir(PATH_DMI_ENTRIES); + if (!d) + return -ENXIO; + while ((de = readdir(d))) { + char filename[PATH_MAX]; + int len, type; + + if (de->d_name[0] == '.') + continue; + sprintf(filename, "%s/%s/type", PATH_DMI_ENTRIES, de->d_name); + f = open(filename, O_RDONLY); + if (f < 0) + continue; + len = read(f, buf, 512); + close(f); + if (len < 0) + continue; + if (sscanf(buf, "%d", &type) != 1) + continue; + if (type != 1) + continue; + sprintf(filename, "%s/%s/raw", PATH_DMI_ENTRIES, de->d_name); + f = open(filename, O_RDONLY); + if (f < 0) + continue; + len = read(f, buf, 512); + close(f); + if (len < 0) + continue; + /* Sigh. https://en.wikipedia.org/wiki/Overengineering */ + /* DMTF SMBIOS 3.0 Section 7.2.1 System UUID */ + sprintf(system_uuid, + "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-" + "%02x%02x%02x%02x%02x%02x", + (uint8_t)buf[8 + 3], (uint8_t)buf[8 + 2], + (uint8_t)buf[8 + 1], (uint8_t)buf[8 + 0], + (uint8_t)buf[8 + 5], (uint8_t)buf[8 + 4], + (uint8_t)buf[8 + 7], (uint8_t)buf[8 + 6], + (uint8_t)buf[8 + 8], (uint8_t)buf[8 + 9], + (uint8_t)buf[8 + 10], (uint8_t)buf[8 + 11], + (uint8_t)buf[8 + 12], (uint8_t)buf[8 + 13], + (uint8_t)buf[8 + 14], (uint8_t)buf[8 + 15]); + break; + } + closedir(d); + return strlen(system_uuid) ? 0 : -ENXIO; +} + +int uuid_from_systemd(char *systemd_uuid) +{ +#ifdef HAVE_SYSTEMD + sd_id128_t id; + char *ret; + + if (sd_id128_get_machine_app_specific(NVME_HOSTNQN_ID, &id) < 0) + return -ENXIO; + + sprintf(systemd_uuid, SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id)); + return 0; +#else + return -ENOTSUP; +#endif +} diff --git a/nvme.c b/nvme.c index 8751ffd4..5e77e3f6 100644 --- a/nvme.c +++ b/nvme.c @@ -5581,25 +5581,32 @@ static int admin_passthru(int argc, char **argv, struct command *cmd, struct plu return passthru(argc, argv, NVME_IOCTL_ADMIN_CMD, 1, desc, cmd); } -#ifdef LIBUUID static int gen_hostnqn_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) { - uuid_t uuid; + int ret; char uuid_str[37]; /* e.g. 1b4e28ba-2fa1-11d2-883f-0016d3cca427 + \0 */ +#ifdef LIBUUID + uuid_t uuid; +#endif - uuid_generate_random(uuid); - uuid_unparse_lower(uuid, uuid_str); + ret = uuid_from_dmi(uuid_str); + if (ret < 0) + ret = uuid_from_systemd(uuid_str); +#ifdef LIBUUID + if (ret < 0) { + uuid_generate_random(uuid); + uuid_unparse_lower(uuid, uuid_str); + ret = 0; + } +#endif + if (ret < 0) { + fprintf(stderr, "\"%s\" not supported. Install lib uuid and rebuild.\n", + command->name); + return -ENOTSUP; + } printf("nqn.2014-08.org.nvmexpress:uuid:%s\n", uuid_str); return 0; } -#else -static int gen_hostnqn_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) -{ - fprintf(stderr, "\"%s\" not supported. Install lib uuid and rebuild.\n", - command->name); - return -ENOTSUP; -} -#endif static int show_hostnqn_cmd(int argc, char **argv, struct command *command, struct plugin *plugin) { diff --git a/nvme.h b/nvme.h index 1ffbb1f6..9d772857 100644 --- a/nvme.h +++ b/nvme.h @@ -139,6 +139,9 @@ char *nvme_get_ctrl_attr(char *path, const char *attr); void *nvme_alloc(size_t len, bool *huge); void nvme_free(void *p, bool huge); +int uuid_from_dmi(char *uuid); +int uuid_from_systemd(char *uuid); + unsigned long long elapsed_utime(struct timeval start_time, struct timeval end_time); #endif /* _NVME_H */