[PATCH nvme-7.3 3/4] nvme-fabrics: add helpers for subsystem and host identity options

raoxu raoxu at uniontech.com
Thu Aug 20 23:25:28 PDT 2026


From: Xu Rao <raoxu at uniontech.com>

The nqn, hostnqn and hostid options also start with match_strdup(), but
unlike the direct string replacements handled by nvmf_parse_string_option()
they perform option-specific validation or conversion before parsing is
complete.

Move each lifetime into a helper whose name identifies the value being
parsed:

  nvmf_parse_subsysnqn() handles NVMF_OPT_NQN.  It replaces
  opts->subsysnqn, checks NVMF_NQN_SIZE and updates discovery_nqn.  Using
  subsysnqn in the helper name distinguishes the subsystem NQN from the
  host NQN at the call site.

  nvmf_parse_hostnqn() handles the hostnqn option.  It keeps the existing
  host-assignment check, validates the temporary NQN, copies it to the
  hostnqn buffer and frees the temporary allocation before returning.

  nvmf_parse_hostid() handles the hostid option.  It converts the temporary
  string to uuid_t and frees the duplicated string on both success and
  failure paths.

These three helpers are grouped because they parse non-sensitive identity
values that require validation or conversion rather than a simple owned
string replacement.  Preserve the existing validation and ownership
ordering while moving the code.

No functional change is intended.

Suggested-by: Christoph Hellwig <hch at lst.de>
Signed-off-by: Xu Rao <raoxu at uniontech.com>
---
 drivers/nvme/host/fabrics.c | 118 +++++++++++++++++++++---------------
 1 file changed, 69 insertions(+), 49 deletions(-)

diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c
index aab3fd279d0e..120e57964cdd 100644
--- a/drivers/nvme/host/fabrics.c
+++ b/drivers/nvme/host/fabrics.c
@@ -725,13 +725,75 @@ static int nvmf_parse_string_option(substring_t *args, char **dst)
 	return 0;
 }
 
+static int nvmf_parse_subsysnqn(struct nvmf_ctrl_options *opts, substring_t *args)
+{
+	char *nqn;
+
+	nqn = match_strdup(args);
+	if (!nqn)
+		return -ENOMEM;
+
+	kfree(opts->subsysnqn);
+	opts->subsysnqn = nqn;
+	if (strlen(opts->subsysnqn) >= NVMF_NQN_SIZE) {
+		pr_err("%s needs to be < %d bytes\n",
+		       opts->subsysnqn, NVMF_NQN_SIZE);
+		return -EINVAL;
+	}
+
+	opts->discovery_nqn = !strcmp(opts->subsysnqn, NVME_DISC_SUBSYS_NAME);
+	return 0;
+}
+
+static int nvmf_parse_hostnqn(struct nvmf_ctrl_options *opts,
+			      substring_t *args, char *hostnqn)
+{
+	char *nqn;
+
+	if (opts->host) {
+		pr_err("hostnqn already user-assigned: %s\n", opts->host->nqn);
+		return -EADDRINUSE;
+	}
+
+	nqn = match_strdup(args);
+	if (!nqn)
+		return -ENOMEM;
+
+	if (strlen(nqn) >= NVMF_NQN_SIZE) {
+		pr_err("%s needs to be < %d bytes\n", nqn, NVMF_NQN_SIZE);
+		kfree(nqn);
+		return -EINVAL;
+	}
+
+	strscpy(hostnqn, nqn, NVMF_NQN_SIZE);
+	kfree(nqn);
+	return 0;
+}
+
+static int nvmf_parse_hostid(substring_t *args, uuid_t *hostid)
+{
+	char *id;
+	int ret;
+
+	id = match_strdup(args);
+	if (!id)
+		return -ENOMEM;
+
+	ret = uuid_parse(id, hostid);
+	if (ret) {
+		pr_err("Invalid hostid %s\n", id);
+		ret = -EINVAL;
+	}
+	kfree(id);
+	return ret;
+}
+
 static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
 		const char *buf)
 {
 	substring_t args[MAX_OPT_ARGS];
 	char *options, *o, *option, *p;
 	int token, ret = 0;
-	size_t nqnlen  = 0;
 	int ctrl_loss_tmo = NVMF_DEF_CTRL_LOSS_TMO, key_id;
 	uuid_t hostid;
 	char hostnqn[NVMF_NQN_SIZE];
@@ -773,23 +835,9 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
 				goto out;
 			break;
 		case NVMF_OPT_NQN:
-			p = match_strdup(args);
-			if (!p) {
-				ret = -ENOMEM;
-				goto out;
-			}
-			kfree(opts->subsysnqn);
-			opts->subsysnqn = p;
-			nqnlen = strlen(opts->subsysnqn);
-			if (nqnlen >= NVMF_NQN_SIZE) {
-				pr_err("%s needs to be < %d bytes\n",
-					opts->subsysnqn, NVMF_NQN_SIZE);
-				ret = -EINVAL;
+			ret = nvmf_parse_subsysnqn(opts, args);
+			if (ret)
 				goto out;
-			}
-			opts->discovery_nqn =
-				!(strcmp(opts->subsysnqn,
-					 NVME_DISC_SUBSYS_NAME));
 			break;
 		case NVMF_OPT_TRADDR:
 			ret = nvmf_parse_string_option(args, &opts->traddr);
@@ -873,27 +921,9 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
 			opts->fast_io_fail_tmo = token;
 			break;
 		case NVMF_OPT_HOSTNQN:
-			if (opts->host) {
-				pr_err("hostnqn already user-assigned: %s\n",
-				       opts->host->nqn);
-				ret = -EADDRINUSE;
-				goto out;
-			}
-			p = match_strdup(args);
-			if (!p) {
-				ret = -ENOMEM;
-				goto out;
-			}
-			nqnlen = strlen(p);
-			if (nqnlen >= NVMF_NQN_SIZE) {
-				pr_err("%s needs to be < %d bytes\n",
-					p, NVMF_NQN_SIZE);
-				kfree(p);
-				ret = -EINVAL;
+			ret = nvmf_parse_hostnqn(opts, args, hostnqn);
+			if (ret)
 				goto out;
-			}
-			strscpy(hostnqn, p, NVMF_NQN_SIZE);
-			kfree(p);
 			break;
 		case NVMF_OPT_RECONNECT_DELAY:
 			if (match_int(args, &token)) {
@@ -918,19 +948,9 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
 				goto out;
 			break;
 		case NVMF_OPT_HOST_ID:
-			p = match_strdup(args);
-			if (!p) {
-				ret = -ENOMEM;
-				goto out;
-			}
-			ret = uuid_parse(p, &hostid);
-			if (ret) {
-				pr_err("Invalid hostid %s\n", p);
-				ret = -EINVAL;
-				kfree(p);
+			ret = nvmf_parse_hostid(args, &hostid);
+			if (ret)
 				goto out;
-			}
-			kfree(p);
 			break;
 		case NVMF_OPT_DUP_CONNECT:
 			opts->duplicate_connect = true;
-- 
2.50.1




More information about the Linux-nvme mailing list