Skip to content

Commit c54a616

Browse files
dwsuseigaw
authored andcommitted
tree: add helper to lookup hostnqn/hostid
There are several places where the default hostnqn/hostid could be stored. Add a helper which ensures a canonical way to lookup these values. Also this function warns if the hostnqn/hostid do not match as the Linux kernel enforces this. Signed-off-by: Daniel Wagner <[email protected]>
1 parent ceafafd commit c54a616

3 files changed

Lines changed: 126 additions & 7 deletions

File tree

src/libnvme.map

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ LIBNVME_1.10 {
44
nvme_free_uri;
55
nvme_get_ana_log_atomic;
66
nvme_get_ana_log_len_from_id_ctrl;
7+
nvme_host_get_ids;
78
nvme_init_default_logging;
89
nvme_parse_uri;
910
nvme_revoke_tls_key;

src/nvme/tree.c

Lines changed: 88 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,16 +117,99 @@ static void cleanup_dirents(struct dirents *ents)
117117

118118
#define _cleanup_dirents_ __cleanup__(cleanup_dirents)
119119

120+
static char *nvme_hostid_from_hostnqn(const char *hostnqn)
121+
{
122+
const char *uuid;
123+
124+
uuid = strstr(hostnqn, "uuid:");
125+
if (!uuid)
126+
return NULL;
127+
128+
return strdup(uuid + strlen("uuid:"));
129+
}
130+
131+
int nvme_host_get_ids(nvme_root_t r,
132+
char *hostnqn_arg, char *hostid_arg,
133+
char **hostnqn, char **hostid)
134+
{
135+
_cleanup_free_ char *nqn = NULL;
136+
_cleanup_free_ char *hid = NULL;
137+
_cleanup_free_ char *hnqn = NULL;
138+
nvme_host_t h;
139+
140+
/* command line argumments */
141+
if (hostid_arg)
142+
hid = strdup(hostid_arg);
143+
if (hostnqn_arg)
144+
hnqn = strdup(hostnqn_arg);
145+
146+
/* JSON config: assume the first entry is the default host */
147+
h = nvme_first_host(r);
148+
if (h) {
149+
if (!hid)
150+
hid = strdup(nvme_host_get_hostid(h));
151+
if (!hnqn)
152+
hnqn = strdup(nvme_host_get_hostnqn(h));
153+
}
154+
155+
/* /etc/nvme/hostid and/or /etc/nvme/hostnqn */
156+
if (!hid)
157+
hid = nvmf_hostid_from_file();
158+
if (!hnqn)
159+
hnqn = nvmf_hostnqn_from_file();
160+
161+
/* incomplete configuration, thus derive hostid from hostnqn */
162+
if (!hid && hnqn)
163+
hid = nvme_hostid_from_hostnqn(hnqn);
164+
165+
/*
166+
* fallback to use either DMI information or device-tree. If all
167+
* fails generate one
168+
*/
169+
if (!hid) {
170+
hid = nvmf_hostid_generate();
171+
if (!hid) {
172+
errno = -ENOMEM;
173+
return -1;
174+
}
175+
176+
nvme_msg(r, LOG_DEBUG,
177+
"warning: using auto generated hostid and hostnqn\n");
178+
}
179+
180+
/* incomplete configuration, thus derive hostnqn from hostid */
181+
if (!hnqn) {
182+
hnqn = nvmf_hostnqn_generate_from_hostid(hid);
183+
if (!hnqn) {
184+
errno = -ENOMEM;
185+
return -1;
186+
}
187+
}
188+
189+
/* sanity checks */
190+
nqn = nvme_hostid_from_hostnqn(hnqn);
191+
if (nqn && strcmp(nqn, hid)) {
192+
nvme_msg(r, LOG_DEBUG,
193+
"warning: use hostid '%s' which does not match uuid in hostnqn '%s'\n",
194+
hid, hnqn);
195+
}
196+
197+
*hostid = hid;
198+
*hostnqn = hnqn;
199+
hid = NULL;
200+
hnqn = NULL;
201+
202+
return 0;
203+
}
204+
120205
nvme_host_t nvme_default_host(nvme_root_t r)
121206
{
122-
struct nvme_host *h;
123207
_cleanup_free_ char *hostnqn = NULL;
124208
_cleanup_free_ char *hostid = NULL;
209+
struct nvme_host *h;
125210

126-
hostnqn = nvmf_hostnqn_from_file();
127-
if (!hostnqn)
128-
hostnqn = nvmf_hostnqn_generate();
129-
hostid = nvmf_hostid_from_file();
211+
if (nvme_host_get_ids(r, NULL, NULL, &hostnqn, &hostid))
212+
return NULL;
130213

131214
h = nvme_lookup_host(r, hostnqn, hostid);
132215

src/nvme/tree.h

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,13 +169,48 @@ bool nvme_host_is_pdc_enabled(nvme_host_t h, bool fallback);
169169
* nvme_default_host() - Initializes the default host
170170
* @r: &nvme_root_t object
171171
*
172-
* Initializes the default host object based on the values in
173-
* /etc/nvme/hostnqn and /etc/nvme/hostid and attaches it to @r.
172+
* Initializes the default host object based on the hostnqn/hostid
173+
* values returned by nvme_host_get_ids() and attaches it to @r.
174174
*
175175
* Return: &nvme_host_t object
176176
*/
177177
nvme_host_t nvme_default_host(nvme_root_t r);
178178

179+
/**
180+
* nvme_host_get_ids - Retrieve host ids from various sources
181+
*
182+
* @r: &nvme_root_t object
183+
* @hostnqn_arg: Input hostnqn (command line) argument
184+
* @hostid_arg: Input hostid (command line) argument
185+
* @hostnqn: Output hostnqn
186+
* @hostid: Output hostid
187+
*
188+
* nvme_host_get_ids figures out which hostnqn/hostid is to be used.
189+
* There are several sources where this information can be retrieved.
190+
*
191+
* The order is:
192+
*
193+
* - Start with informartion from DMI or device-tree
194+
* - Override hostnqn and hostid from /etc/nvme files
195+
* - Override hostnqn or hostid with values from JSON
196+
* configuration file. The first host entry in the file is
197+
* considered the default host.
198+
* - Override hostnqn or hostid with values from the command line
199+
* (@hostnqn_arg, @hostid_arg).
200+
*
201+
* If the IDs are still NULL after the lookup algorithm, the function
202+
* will generate random IDs.
203+
*
204+
* The function also verifies that hostnqn and hostid matches. The Linux
205+
* NVMe implementation expects a 1:1 matching between the IDs.
206+
*
207+
* Return: 0 on success (@hostnqn and @hostid contain valid strings
208+
* which the caller needs to free), -1 otherwise and errno is set.
209+
*/
210+
int nvme_host_get_ids(nvme_root_t r,
211+
char *hostnqn_arg, char *hostid_arg,
212+
char **hostnqn, char **hostid);
213+
179214
/**
180215
* nvme_first_subsystem() - Start subsystem iterator
181216
* @h: &nvme_host_t object

0 commit comments

Comments
 (0)