[PATCH nvme-cli v2] fabrics: Use corresponding hostid when hostnqn is generated

Shin'ichiro Kawasaki shinichiro.kawasaki at wdc.com
Thu Aug 3 04:21:39 PDT 2023


After the kernel commit ae8bd606e09b ("nvme-fabrics: prevent overriding
of existing host"), kernel ensures hostid and hostnqn maintain 1:1
mapping and "non 1:1 mapping will be rejected". This makes 'nvme
discover' and 'nvme connect' commands fail when they generate hostnqn,
since it does not use corresponding hostid.

To avoid the failures, prepare and use corresponding hostid to the
generated hostnqn, taking the hostid from the hostnqn string. Also add
checks for prepared hostnqn and hostid. If the hostid taken from the
generated hostnqn is different from the hostid from file, print a
warning message. Also, if the prepared hostnqn are inconsistent with the
prepared hostid, print a warning.

Link: https://lore.kernel.org/linux-nvme/l7vk7fnzltpmvkwujsbf2btrzip6wh7ug62iwa3totqcda25l6@siqx7tj6lt3l/
Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki at wdc.com>
---
Changes from v1:
* Moved the step to check hostnqn and hostid per review comment

 fabrics.c | 47 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 45 insertions(+), 2 deletions(-)

diff --git a/fabrics.c b/fabrics.c
index 14a91cc6..40aef693 100644
--- a/fabrics.c
+++ b/fabrics.c
@@ -689,6 +689,43 @@ static int nvme_read_volatile_config(nvme_root_t r)
 	return ret;
 }
 
+char *nvmf_hostid_from_hostnqn(const char *hostnqn)
+{
+	const char *uuid;
+
+	if (!hostnqn)
+		return NULL;
+
+	uuid = strstr(hostnqn, "uuid:");
+	if (!uuid)
+		return NULL;
+
+	return strdup(uuid + strlen("uuid:"));
+}
+
+void nvmf_check_hostid_and_hostnqn(const char *hostid, const char *hostnqn)
+{
+	char *hostid_from_file, *hostid_from_hostnqn;
+
+	if (!hostid)
+		return;
+
+	hostid_from_file = nvmf_hostid_from_file();
+	if (hostid_from_file && strcmp(hostid_from_file, hostid)) {
+		fprintf(stderr, "warning: use generated hostid instead of hostid file\n");
+		free(hostid_from_file);
+	}
+
+	if (!hostnqn)
+		return;
+
+	hostid_from_hostnqn = nvmf_hostid_from_hostnqn(hostnqn);
+	if (hostid_from_hostnqn && strcmp(hostid_from_hostnqn, hostid)) {
+		fprintf(stderr, "warning: use hostid which does not match uuid in hostnqn\n");
+		free(hostid_from_hostnqn);
+	}
+}
+
 int nvmf_discover(const char *desc, int argc, char **argv, bool connect)
 {
 	char *subsysnqn = NVME_DISC_SUBSYS_NAME;
@@ -765,10 +802,13 @@ int nvmf_discover(const char *desc, int argc, char **argv, bool connect)
 	hostid_arg = hostid;
 	if (!hostnqn)
 		hostnqn = hnqn = nvmf_hostnqn_from_file();
-	if (!hostnqn)
+	if (!hostnqn) {
 		hostnqn = hnqn = nvmf_hostnqn_generate();
+		hostid = hid = nvmf_hostid_from_hostnqn(hostnqn);
+	}
 	if (!hostid)
 		hostid = hid = nvmf_hostid_from_file();
+	nvmf_check_hostid_and_hostnqn(hostid, hostnqn);
 	h = nvme_lookup_host(r, hostnqn, hostid);
 	if (!h) {
 		ret = ENOMEM;
@@ -978,10 +1018,13 @@ int nvmf_connect(const char *desc, int argc, char **argv)
 
 	if (!hostnqn)
 		hostnqn = hnqn = nvmf_hostnqn_from_file();
-	if (!hostnqn)
+	if (!hostnqn) {
 		hostnqn = hnqn = nvmf_hostnqn_generate();
+		hostid = hid = nvmf_hostid_from_hostnqn(hostnqn);
+	}
 	if (!hostid)
 		hostid = hid = nvmf_hostid_from_file();
+	nvmf_check_hostid_and_hostnqn(hostid, hostnqn);
 	h = nvme_lookup_host(r, hostnqn, hostid);
 	if (!h) {
 		errno = ENOMEM;
-- 
2.40.1




More information about the Linux-nvme mailing list