xref: /spdk/lib/nvmf/subsystem.c (revision 1fc4165fe9bf8512483356ad8e6d27f793f2e3db)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/stdinc.h"
35 
36 #include "nvmf_internal.h"
37 #include "transport.h"
38 
39 #include "spdk/event.h"
40 #include "spdk/likely.h"
41 #include "spdk/string.h"
42 #include "spdk/trace.h"
43 #include "spdk/nvmf_spec.h"
44 #include "spdk/uuid.h"
45 
46 #include "spdk/bdev_module.h"
47 #include "spdk_internal/log.h"
48 #include "spdk_internal/utf.h"
49 
50 /*
51  * States for parsing valid domains in NQNs according to RFC 1034
52  */
53 enum spdk_nvmf_nqn_domain_states {
54 	/* First character of a domain must be a letter */
55 	SPDK_NVMF_DOMAIN_ACCEPT_LETTER = 0,
56 
57 	/* Subsequent characters can be any of letter, digit, or hyphen */
58 	SPDK_NVMF_DOMAIN_ACCEPT_LDH = 1,
59 
60 	/* A domain label must end with either a letter or digit */
61 	SPDK_NVMF_DOMAIN_ACCEPT_ANY = 2
62 };
63 
64 /* Returns true if is a valid ASCII string as defined by the NVMe spec */
65 static bool
66 spdk_nvmf_valid_ascii_string(const void *buf, size_t size)
67 {
68 	const uint8_t *str = buf;
69 	size_t i;
70 
71 	for (i = 0; i < size; i++) {
72 		if (str[i] < 0x20 || str[i] > 0x7E) {
73 			return false;
74 		}
75 	}
76 
77 	return true;
78 }
79 
80 static bool
81 spdk_nvmf_valid_nqn(const char *nqn)
82 {
83 	size_t len;
84 	struct spdk_uuid uuid_value;
85 	uint32_t i;
86 	int bytes_consumed;
87 	uint32_t domain_label_length;
88 	char *reverse_domain_end;
89 	uint32_t reverse_domain_end_index;
90 	enum spdk_nvmf_nqn_domain_states domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LETTER;
91 
92 	/* Check for length requirements */
93 	len = strlen(nqn);
94 	if (len > SPDK_NVMF_NQN_MAX_LEN) {
95 		SPDK_ERRLOG("Invalid NQN \"%s\": length %zu > max %d\n", nqn, len, SPDK_NVMF_NQN_MAX_LEN);
96 		return false;
97 	}
98 
99 	/* The nqn must be at least as long as SPDK_NVMF_NQN_MIN_LEN to contain the necessary prefix. */
100 	if (len < SPDK_NVMF_NQN_MIN_LEN) {
101 		SPDK_ERRLOG("Invalid NQN \"%s\": length %zu < min %d\n", nqn, len, SPDK_NVMF_NQN_MIN_LEN);
102 		return false;
103 	}
104 
105 	/* Check for discovery controller nqn */
106 	if (!strcmp(nqn, SPDK_NVMF_DISCOVERY_NQN)) {
107 		return true;
108 	}
109 
110 	/* Check for equality with the generic nqn structure of the form "nqn.2014-08.org.nvmexpress:uuid:11111111-2222-3333-4444-555555555555" */
111 	if (!strncmp(nqn, SPDK_NVMF_NQN_UUID_PRE, SPDK_NVMF_NQN_UUID_PRE_LEN)) {
112 		if (len != SPDK_NVMF_NQN_UUID_PRE_LEN + SPDK_NVMF_UUID_STRING_LEN) {
113 			SPDK_ERRLOG("Invalid NQN \"%s\": uuid is not the correct length\n", nqn);
114 			return false;
115 		}
116 
117 		if (spdk_uuid_parse(&uuid_value, &nqn[SPDK_NVMF_NQN_UUID_PRE_LEN])) {
118 			SPDK_ERRLOG("Invalid NQN \"%s\": uuid is not formatted correctly\n", nqn);
119 			return false;
120 		}
121 		return true;
122 	}
123 
124 	/* If the nqn does not match the uuid structure, the next several checks validate the form "nqn.yyyy-mm.reverse.domain:user-string" */
125 
126 	if (strncmp(nqn, "nqn.", 4) != 0) {
127 		SPDK_ERRLOG("Invalid NQN \"%s\": NQN must begin with \"nqn.\".\n", nqn);
128 		return false;
129 	}
130 
131 	/* Check for yyyy-mm. */
132 	if (!(isdigit(nqn[4]) && isdigit(nqn[5]) && isdigit(nqn[6]) && isdigit(nqn[7]) &&
133 	      nqn[8] == '-' && isdigit(nqn[9]) && isdigit(nqn[10]) && nqn[11] == '.')) {
134 		SPDK_ERRLOG("Invalid date code in NQN \"%s\"\n", nqn);
135 		return false;
136 	}
137 
138 	reverse_domain_end = strchr(nqn, ':');
139 	if (reverse_domain_end != NULL && (reverse_domain_end_index = reverse_domain_end - nqn) < len - 1) {
140 	} else {
141 		SPDK_ERRLOG("Invalid NQN \"%s\". NQN must contain user specified name with a ':' as a prefix.\n",
142 			    nqn);
143 		return false;
144 	}
145 
146 	/* Check for valid reverse domain */
147 	domain_label_length = 0;
148 	for (i = 12; i < reverse_domain_end_index; i++) {
149 		if (domain_label_length > SPDK_DOMAIN_LABEL_MAX_LEN) {
150 			SPDK_ERRLOG("Invalid domain name in NQN \"%s\". At least one Label is too long.\n", nqn);
151 			return false;
152 		}
153 
154 		switch (domain_state) {
155 
156 		case SPDK_NVMF_DOMAIN_ACCEPT_LETTER: {
157 			if (isalpha(nqn[i])) {
158 				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_ANY;
159 				domain_label_length++;
160 				break;
161 			} else {
162 				SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must start with a letter.\n", nqn);
163 				return false;
164 			}
165 		}
166 
167 		case SPDK_NVMF_DOMAIN_ACCEPT_LDH: {
168 			if (isalpha(nqn[i]) || isdigit(nqn[i])) {
169 				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_ANY;
170 				domain_label_length++;
171 				break;
172 			} else if (nqn[i] == '-') {
173 				if (i == reverse_domain_end_index - 1) {
174 					SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must end with an alphanumeric symbol.\n",
175 						    nqn);
176 					return false;
177 				}
178 				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LDH;
179 				domain_label_length++;
180 				break;
181 			} else if (nqn[i] == '.') {
182 				SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must end with an alphanumeric symbol.\n",
183 					    nqn);
184 				return false;
185 			} else {
186 				SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must contain only [a-z,A-Z,0-9,'-','.'].\n",
187 					    nqn);
188 				return false;
189 			}
190 		}
191 
192 		case SPDK_NVMF_DOMAIN_ACCEPT_ANY: {
193 			if (isalpha(nqn[i]) || isdigit(nqn[i])) {
194 				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_ANY;
195 				domain_label_length++;
196 				break;
197 			} else if (nqn[i] == '-') {
198 				if (i == reverse_domain_end_index - 1) {
199 					SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must end with an alphanumeric symbol.\n",
200 						    nqn);
201 					return false;
202 				}
203 				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LDH;
204 				domain_label_length++;
205 				break;
206 			} else if (nqn[i] == '.') {
207 				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LETTER;
208 				domain_label_length = 0;
209 				break;
210 			} else {
211 				SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must contain only [a-z,A-Z,0-9,'-','.'].\n",
212 					    nqn);
213 				return false;
214 			}
215 		}
216 		}
217 	}
218 
219 	i = reverse_domain_end_index + 1;
220 	while (i < len) {
221 		bytes_consumed = utf8_valid(&nqn[i], &nqn[len]);
222 		if (bytes_consumed <= 0) {
223 			SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must contain only valid utf-8.\n", nqn);
224 			return false;
225 		}
226 
227 		i += bytes_consumed;
228 	}
229 	return true;
230 }
231 
232 struct spdk_nvmf_subsystem *
233 spdk_nvmf_subsystem_create(struct spdk_nvmf_tgt *tgt,
234 			   const char *nqn,
235 			   enum spdk_nvmf_subtype type,
236 			   uint32_t num_ns)
237 {
238 	struct spdk_nvmf_subsystem	*subsystem;
239 	uint32_t			sid;
240 
241 	if (spdk_nvmf_tgt_find_subsystem(tgt, nqn)) {
242 		SPDK_ERRLOG("Subsystem NQN '%s' already exists\n", nqn);
243 		return NULL;
244 	}
245 
246 	if (!spdk_nvmf_valid_nqn(nqn)) {
247 		return NULL;
248 	}
249 
250 	if (type == SPDK_NVMF_SUBTYPE_DISCOVERY && num_ns != 0) {
251 		SPDK_ERRLOG("Discovery subsystem cannot have namespaces.\n");
252 		return NULL;
253 	}
254 
255 	/* Find a free subsystem id (sid) */
256 	for (sid = 0; sid < tgt->max_subsystems; sid++) {
257 		if (tgt->subsystems[sid] == NULL) {
258 			break;
259 		}
260 	}
261 	if (sid >= tgt->max_subsystems) {
262 		return NULL;
263 	}
264 
265 	subsystem = calloc(1, sizeof(struct spdk_nvmf_subsystem));
266 	if (subsystem == NULL) {
267 		return NULL;
268 	}
269 
270 	subsystem->thread = spdk_get_thread();
271 	subsystem->state = SPDK_NVMF_SUBSYSTEM_INACTIVE;
272 	subsystem->tgt = tgt;
273 	subsystem->id = sid;
274 	subsystem->subtype = type;
275 	subsystem->max_nsid = num_ns;
276 	subsystem->max_allowed_nsid = num_ns;
277 	subsystem->next_cntlid = 0;
278 	snprintf(subsystem->subnqn, sizeof(subsystem->subnqn), "%s", nqn);
279 	TAILQ_INIT(&subsystem->listeners);
280 	TAILQ_INIT(&subsystem->hosts);
281 	TAILQ_INIT(&subsystem->ctrlrs);
282 
283 	if (num_ns != 0) {
284 		subsystem->ns = calloc(num_ns, sizeof(struct spdk_nvmf_ns *));
285 		if (subsystem->ns == NULL) {
286 			SPDK_ERRLOG("Namespace memory allocation failed\n");
287 			free(subsystem);
288 			return NULL;
289 		}
290 	}
291 
292 	memset(subsystem->sn, '0', sizeof(subsystem->sn) - 1);
293 	subsystem->sn[sizeof(subsystem->sn) - 1] = '\n';
294 
295 	tgt->subsystems[sid] = subsystem;
296 	tgt->discovery_genctr++;
297 
298 	return subsystem;
299 }
300 
301 static void
302 _spdk_nvmf_subsystem_remove_host(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_host *host)
303 {
304 	TAILQ_REMOVE(&subsystem->hosts, host, link);
305 	free(host->nqn);
306 	free(host);
307 }
308 
309 static int _spdk_nvmf_subsystem_remove_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid);
310 
311 void
312 spdk_nvmf_subsystem_destroy(struct spdk_nvmf_subsystem *subsystem)
313 {
314 	struct spdk_nvmf_listener	*listener, *listener_tmp;
315 	struct spdk_nvmf_host		*host, *host_tmp;
316 	struct spdk_nvmf_ctrlr		*ctrlr, *ctrlr_tmp;
317 	struct spdk_nvmf_ns		*ns;
318 
319 	if (!subsystem) {
320 		return;
321 	}
322 
323 	assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE);
324 
325 	SPDK_DEBUGLOG(SPDK_LOG_NVMF, "subsystem is %p\n", subsystem);
326 
327 	TAILQ_FOREACH_SAFE(listener, &subsystem->listeners, link, listener_tmp) {
328 		TAILQ_REMOVE(&subsystem->listeners, listener, link);
329 		free(listener);
330 	}
331 
332 	TAILQ_FOREACH_SAFE(host, &subsystem->hosts, link, host_tmp) {
333 		_spdk_nvmf_subsystem_remove_host(subsystem, host);
334 	}
335 
336 	TAILQ_FOREACH_SAFE(ctrlr, &subsystem->ctrlrs, link, ctrlr_tmp) {
337 		spdk_nvmf_ctrlr_destruct(ctrlr);
338 	}
339 
340 	ns = spdk_nvmf_subsystem_get_first_ns(subsystem);
341 	while (ns != NULL) {
342 		struct spdk_nvmf_ns *next_ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns);
343 
344 		_spdk_nvmf_subsystem_remove_ns(subsystem, ns->opts.nsid);
345 		ns = next_ns;
346 	}
347 
348 	free(subsystem->ns);
349 
350 	subsystem->tgt->subsystems[subsystem->id] = NULL;
351 	subsystem->tgt->discovery_genctr++;
352 
353 	free(subsystem);
354 }
355 
356 static int
357 spdk_nvmf_subsystem_set_state(struct spdk_nvmf_subsystem *subsystem,
358 			      enum spdk_nvmf_subsystem_state state)
359 {
360 	enum spdk_nvmf_subsystem_state actual_old_state, expected_old_state;
361 
362 	switch (state) {
363 	case SPDK_NVMF_SUBSYSTEM_INACTIVE:
364 		expected_old_state = SPDK_NVMF_SUBSYSTEM_DEACTIVATING;
365 		break;
366 	case SPDK_NVMF_SUBSYSTEM_ACTIVATING:
367 		expected_old_state = SPDK_NVMF_SUBSYSTEM_INACTIVE;
368 		break;
369 	case SPDK_NVMF_SUBSYSTEM_ACTIVE:
370 		expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING;
371 		break;
372 	case SPDK_NVMF_SUBSYSTEM_PAUSING:
373 		expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
374 		break;
375 	case SPDK_NVMF_SUBSYSTEM_PAUSED:
376 		expected_old_state = SPDK_NVMF_SUBSYSTEM_PAUSING;
377 		break;
378 	case SPDK_NVMF_SUBSYSTEM_RESUMING:
379 		expected_old_state = SPDK_NVMF_SUBSYSTEM_PAUSED;
380 		break;
381 	case SPDK_NVMF_SUBSYSTEM_DEACTIVATING:
382 		expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
383 		break;
384 	default:
385 		assert(false);
386 		return -1;
387 	}
388 
389 	actual_old_state = __sync_val_compare_and_swap(&subsystem->state, expected_old_state, state);
390 	if (actual_old_state != expected_old_state) {
391 		if (actual_old_state == SPDK_NVMF_SUBSYSTEM_RESUMING &&
392 		    state == SPDK_NVMF_SUBSYSTEM_ACTIVE) {
393 			expected_old_state = SPDK_NVMF_SUBSYSTEM_RESUMING;
394 		}
395 		/* This is for the case when activating the subsystem fails. */
396 		if (actual_old_state == SPDK_NVMF_SUBSYSTEM_ACTIVATING &&
397 		    state == SPDK_NVMF_SUBSYSTEM_DEACTIVATING) {
398 			expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING;
399 		}
400 		actual_old_state = __sync_val_compare_and_swap(&subsystem->state, expected_old_state, state);
401 	}
402 	assert(actual_old_state == expected_old_state);
403 	return actual_old_state - expected_old_state;
404 }
405 
406 struct subsystem_state_change_ctx {
407 	struct spdk_nvmf_subsystem *subsystem;
408 
409 	enum spdk_nvmf_subsystem_state requested_state;
410 
411 	spdk_nvmf_subsystem_state_change_done cb_fn;
412 	void *cb_arg;
413 };
414 
415 static void
416 subsystem_state_change_done(struct spdk_io_channel_iter *i, int status)
417 {
418 	struct subsystem_state_change_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
419 
420 	if (status == 0) {
421 		status = spdk_nvmf_subsystem_set_state(ctx->subsystem, ctx->requested_state);
422 		if (status) {
423 			status = -1;
424 		}
425 	}
426 
427 	if (ctx->cb_fn) {
428 		ctx->cb_fn(ctx->subsystem, ctx->cb_arg, status);
429 	}
430 	free(ctx);
431 }
432 
433 static void
434 subsystem_state_change_continue(void *ctx, int status)
435 {
436 	struct spdk_io_channel_iter *i = ctx;
437 	spdk_for_each_channel_continue(i, status);
438 }
439 
440 static void
441 subsystem_state_change_on_pg(struct spdk_io_channel_iter *i)
442 {
443 	struct subsystem_state_change_ctx *ctx;
444 	struct spdk_io_channel *ch;
445 	struct spdk_nvmf_poll_group *group;
446 
447 	ctx = spdk_io_channel_iter_get_ctx(i);
448 	ch = spdk_io_channel_iter_get_channel(i);
449 	group = spdk_io_channel_get_ctx(ch);
450 
451 	switch (ctx->requested_state) {
452 	case SPDK_NVMF_SUBSYSTEM_INACTIVE:
453 		spdk_nvmf_poll_group_remove_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i);
454 		break;
455 	case SPDK_NVMF_SUBSYSTEM_ACTIVE:
456 		if (ctx->subsystem->state == SPDK_NVMF_SUBSYSTEM_ACTIVATING) {
457 			spdk_nvmf_poll_group_add_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i);
458 		} else if (ctx->subsystem->state == SPDK_NVMF_SUBSYSTEM_RESUMING) {
459 			spdk_nvmf_poll_group_resume_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i);
460 		}
461 		break;
462 	case SPDK_NVMF_SUBSYSTEM_PAUSED:
463 		spdk_nvmf_poll_group_pause_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i);
464 		break;
465 	default:
466 		assert(false);
467 		break;
468 	}
469 }
470 
471 static int
472 spdk_nvmf_subsystem_state_change(struct spdk_nvmf_subsystem *subsystem,
473 				 enum spdk_nvmf_subsystem_state requested_state,
474 				 spdk_nvmf_subsystem_state_change_done cb_fn,
475 				 void *cb_arg)
476 {
477 	struct subsystem_state_change_ctx *ctx;
478 	enum spdk_nvmf_subsystem_state intermediate_state;
479 	int rc;
480 
481 	switch (requested_state) {
482 	case SPDK_NVMF_SUBSYSTEM_INACTIVE:
483 		intermediate_state = SPDK_NVMF_SUBSYSTEM_DEACTIVATING;
484 		break;
485 	case SPDK_NVMF_SUBSYSTEM_ACTIVE:
486 		if (subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED) {
487 			intermediate_state = SPDK_NVMF_SUBSYSTEM_RESUMING;
488 		} else {
489 			intermediate_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING;
490 		}
491 		break;
492 	case SPDK_NVMF_SUBSYSTEM_PAUSED:
493 		intermediate_state = SPDK_NVMF_SUBSYSTEM_PAUSING;
494 		break;
495 	default:
496 		assert(false);
497 		return -EINVAL;
498 	}
499 
500 	ctx = calloc(1, sizeof(*ctx));
501 	if (!ctx) {
502 		return -ENOMEM;
503 	}
504 
505 	rc = spdk_nvmf_subsystem_set_state(subsystem, intermediate_state);
506 	if (rc) {
507 		free(ctx);
508 		return rc;
509 	}
510 
511 	ctx->subsystem = subsystem;
512 	ctx->requested_state = requested_state;
513 	ctx->cb_fn = cb_fn;
514 	ctx->cb_arg = cb_arg;
515 
516 	spdk_for_each_channel(subsystem->tgt,
517 			      subsystem_state_change_on_pg,
518 			      ctx,
519 			      subsystem_state_change_done);
520 
521 	return 0;
522 }
523 
524 int
525 spdk_nvmf_subsystem_start(struct spdk_nvmf_subsystem *subsystem,
526 			  spdk_nvmf_subsystem_state_change_done cb_fn,
527 			  void *cb_arg)
528 {
529 	return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_ACTIVE, cb_fn, cb_arg);
530 }
531 
532 int
533 spdk_nvmf_subsystem_stop(struct spdk_nvmf_subsystem *subsystem,
534 			 spdk_nvmf_subsystem_state_change_done cb_fn,
535 			 void *cb_arg)
536 {
537 	return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_INACTIVE, cb_fn, cb_arg);
538 }
539 
540 int
541 spdk_nvmf_subsystem_pause(struct spdk_nvmf_subsystem *subsystem,
542 			  spdk_nvmf_subsystem_state_change_done cb_fn,
543 			  void *cb_arg)
544 {
545 	return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_PAUSED, cb_fn, cb_arg);
546 }
547 
548 int
549 spdk_nvmf_subsystem_resume(struct spdk_nvmf_subsystem *subsystem,
550 			   spdk_nvmf_subsystem_state_change_done cb_fn,
551 			   void *cb_arg)
552 {
553 	return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_ACTIVE, cb_fn, cb_arg);
554 }
555 
556 struct spdk_nvmf_subsystem *
557 spdk_nvmf_subsystem_get_first(struct spdk_nvmf_tgt *tgt)
558 {
559 	struct spdk_nvmf_subsystem	*subsystem;
560 	uint32_t sid;
561 
562 	for (sid = 0; sid < tgt->max_subsystems; sid++) {
563 		subsystem = tgt->subsystems[sid];
564 		if (subsystem) {
565 			return subsystem;
566 		}
567 	}
568 
569 	return NULL;
570 }
571 
572 struct spdk_nvmf_subsystem *
573 spdk_nvmf_subsystem_get_next(struct spdk_nvmf_subsystem *subsystem)
574 {
575 	uint32_t sid;
576 	struct spdk_nvmf_tgt *tgt;
577 
578 	if (!subsystem) {
579 		return NULL;
580 	}
581 
582 	tgt = subsystem->tgt;
583 
584 	for (sid = subsystem->id + 1; sid < tgt->max_subsystems; sid++) {
585 		subsystem = tgt->subsystems[sid];
586 		if (subsystem) {
587 			return subsystem;
588 		}
589 	}
590 
591 	return NULL;
592 }
593 
594 static struct spdk_nvmf_host *
595 _spdk_nvmf_subsystem_find_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn)
596 {
597 	struct spdk_nvmf_host *host = NULL;
598 
599 	TAILQ_FOREACH(host, &subsystem->hosts, link) {
600 		if (strcmp(hostnqn, host->nqn) == 0) {
601 			return host;
602 		}
603 	}
604 
605 	return NULL;
606 }
607 
608 int
609 spdk_nvmf_subsystem_add_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn)
610 {
611 	struct spdk_nvmf_host *host;
612 
613 	if (!spdk_nvmf_valid_nqn(hostnqn)) {
614 		return -EINVAL;
615 	}
616 
617 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
618 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
619 		return -EAGAIN;
620 	}
621 
622 	if (_spdk_nvmf_subsystem_find_host(subsystem, hostnqn)) {
623 		/* This subsystem already allows the specified host. */
624 		return 0;
625 	}
626 
627 	host = calloc(1, sizeof(*host));
628 	if (!host) {
629 		return -ENOMEM;
630 	}
631 	host->nqn = strdup(hostnqn);
632 	if (!host->nqn) {
633 		free(host);
634 		return -ENOMEM;
635 	}
636 
637 	TAILQ_INSERT_HEAD(&subsystem->hosts, host, link);
638 	subsystem->tgt->discovery_genctr++;
639 
640 	return 0;
641 }
642 
643 int
644 spdk_nvmf_subsystem_remove_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn)
645 {
646 	struct spdk_nvmf_host *host;
647 
648 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
649 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
650 		return -EAGAIN;
651 	}
652 
653 	host = _spdk_nvmf_subsystem_find_host(subsystem, hostnqn);
654 	if (host == NULL) {
655 		return -ENOENT;
656 	}
657 
658 	_spdk_nvmf_subsystem_remove_host(subsystem, host);
659 	return 0;
660 }
661 
662 int
663 spdk_nvmf_subsystem_set_allow_any_host(struct spdk_nvmf_subsystem *subsystem, bool allow_any_host)
664 {
665 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
666 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
667 		return -EAGAIN;
668 	}
669 
670 	subsystem->allow_any_host = allow_any_host;
671 
672 	return 0;
673 }
674 
675 bool
676 spdk_nvmf_subsystem_get_allow_any_host(const struct spdk_nvmf_subsystem *subsystem)
677 {
678 	return subsystem->allow_any_host;
679 }
680 
681 bool
682 spdk_nvmf_subsystem_host_allowed(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn)
683 {
684 	if (!hostnqn) {
685 		return false;
686 	}
687 
688 	if (subsystem->allow_any_host) {
689 		return true;
690 	}
691 
692 	return _spdk_nvmf_subsystem_find_host(subsystem, hostnqn) != NULL;
693 }
694 
695 struct spdk_nvmf_host *
696 spdk_nvmf_subsystem_get_first_host(struct spdk_nvmf_subsystem *subsystem)
697 {
698 	return TAILQ_FIRST(&subsystem->hosts);
699 }
700 
701 
702 struct spdk_nvmf_host *
703 spdk_nvmf_subsystem_get_next_host(struct spdk_nvmf_subsystem *subsystem,
704 				  struct spdk_nvmf_host *prev_host)
705 {
706 	return TAILQ_NEXT(prev_host, link);
707 }
708 
709 const char *
710 spdk_nvmf_host_get_nqn(struct spdk_nvmf_host *host)
711 {
712 	return host->nqn;
713 }
714 
715 static struct spdk_nvmf_listener *
716 _spdk_nvmf_subsystem_find_listener(struct spdk_nvmf_subsystem *subsystem,
717 				   const struct spdk_nvme_transport_id *trid)
718 {
719 	struct spdk_nvmf_listener *listener;
720 
721 	TAILQ_FOREACH(listener, &subsystem->listeners, link) {
722 		if (spdk_nvme_transport_id_compare(&listener->trid, trid) == 0) {
723 			return listener;
724 		}
725 	}
726 
727 	return NULL;
728 }
729 
730 int
731 spdk_nvmf_subsystem_add_listener(struct spdk_nvmf_subsystem *subsystem,
732 				 struct spdk_nvme_transport_id *trid)
733 {
734 	struct spdk_nvmf_transport *transport;
735 	struct spdk_nvmf_listener *listener;
736 
737 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
738 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
739 		return -EAGAIN;
740 	}
741 
742 	if (_spdk_nvmf_subsystem_find_listener(subsystem, trid)) {
743 		/* Listener already exists in this subsystem */
744 		return 0;
745 	}
746 
747 	transport = spdk_nvmf_tgt_get_transport(subsystem->tgt, trid->trtype);
748 	if (transport == NULL) {
749 		SPDK_ERRLOG("Unknown transport type %d\n", trid->trtype);
750 		return -EINVAL;
751 	}
752 
753 	listener = calloc(1, sizeof(*listener));
754 	if (!listener) {
755 		return -ENOMEM;
756 	}
757 
758 	listener->trid = *trid;
759 	listener->transport = transport;
760 
761 	TAILQ_INSERT_HEAD(&subsystem->listeners, listener, link);
762 
763 	return 0;
764 }
765 
766 int
767 spdk_nvmf_subsystem_remove_listener(struct spdk_nvmf_subsystem *subsystem,
768 				    const struct spdk_nvme_transport_id *trid)
769 {
770 	struct spdk_nvmf_listener *listener;
771 
772 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
773 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
774 		return -EAGAIN;
775 	}
776 
777 	listener = _spdk_nvmf_subsystem_find_listener(subsystem, trid);
778 	if (listener == NULL) {
779 		return -ENOENT;
780 	}
781 
782 	TAILQ_REMOVE(&subsystem->listeners, listener, link);
783 	free(listener);
784 
785 	return 0;
786 }
787 
788 bool
789 spdk_nvmf_subsystem_listener_allowed(struct spdk_nvmf_subsystem *subsystem,
790 				     struct spdk_nvme_transport_id *trid)
791 {
792 	struct spdk_nvmf_listener *listener;
793 
794 	if (!strcmp(subsystem->subnqn, SPDK_NVMF_DISCOVERY_NQN)) {
795 		return true;
796 	}
797 
798 	TAILQ_FOREACH(listener, &subsystem->listeners, link) {
799 		if (spdk_nvme_transport_id_compare(&listener->trid, trid) == 0) {
800 			return true;
801 		}
802 	}
803 
804 	return false;
805 }
806 
807 struct spdk_nvmf_listener *
808 spdk_nvmf_subsystem_get_first_listener(struct spdk_nvmf_subsystem *subsystem)
809 {
810 	return TAILQ_FIRST(&subsystem->listeners);
811 }
812 
813 struct spdk_nvmf_listener *
814 spdk_nvmf_subsystem_get_next_listener(struct spdk_nvmf_subsystem *subsystem,
815 				      struct spdk_nvmf_listener *prev_listener)
816 {
817 	return TAILQ_NEXT(prev_listener, link);
818 }
819 
820 const struct spdk_nvme_transport_id *
821 spdk_nvmf_listener_get_trid(struct spdk_nvmf_listener *listener)
822 {
823 	return &listener->trid;
824 }
825 
826 struct subsystem_update_ns_ctx {
827 	struct spdk_nvmf_subsystem *subsystem;
828 
829 	spdk_nvmf_subsystem_state_change_done cb_fn;
830 	void *cb_arg;
831 };
832 
833 static void
834 subsystem_update_ns_done(struct spdk_io_channel_iter *i, int status)
835 {
836 	struct subsystem_update_ns_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
837 
838 	if (ctx->cb_fn) {
839 		ctx->cb_fn(ctx->subsystem, ctx->cb_arg, status);
840 	}
841 	free(ctx);
842 }
843 
844 static void
845 subsystem_update_ns_on_pg(struct spdk_io_channel_iter *i)
846 {
847 	int rc;
848 	struct subsystem_update_ns_ctx *ctx;
849 	struct spdk_nvmf_poll_group *group;
850 	struct spdk_nvmf_subsystem *subsystem;
851 
852 	ctx = spdk_io_channel_iter_get_ctx(i);
853 	group = spdk_io_channel_get_ctx(spdk_io_channel_iter_get_channel(i));
854 	subsystem = ctx->subsystem;
855 
856 	rc = spdk_nvmf_poll_group_update_subsystem(group, subsystem);
857 	spdk_for_each_channel_continue(i, rc);
858 }
859 
860 static int
861 spdk_nvmf_subsystem_update_ns(struct spdk_nvmf_subsystem *subsystem, spdk_channel_for_each_cpl cpl,
862 			      void *ctx)
863 {
864 	spdk_for_each_channel(subsystem->tgt,
865 			      subsystem_update_ns_on_pg,
866 			      ctx,
867 			      cpl);
868 
869 	return 0;
870 }
871 
872 static void
873 spdk_nvmf_subsystem_ns_changed(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid)
874 {
875 	struct spdk_nvmf_ctrlr *ctrlr;
876 
877 	TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) {
878 		spdk_nvmf_ctrlr_ns_changed(ctrlr, nsid);
879 	}
880 }
881 
882 static int
883 _spdk_nvmf_subsystem_remove_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid)
884 {
885 	struct spdk_nvmf_ns *ns;
886 	struct spdk_nvmf_registrant *reg, *reg_tmp;
887 
888 	assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED ||
889 	       subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE);
890 
891 	if (nsid == 0 || nsid > subsystem->max_nsid) {
892 		return -1;
893 	}
894 
895 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
896 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
897 		return -1;
898 	}
899 
900 	ns = subsystem->ns[nsid - 1];
901 	if (!ns) {
902 		return -1;
903 	}
904 
905 	subsystem->ns[nsid - 1] = NULL;
906 
907 	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, reg_tmp) {
908 		TAILQ_REMOVE(&ns->registrants, reg, link);
909 		free(reg);
910 	}
911 	spdk_bdev_module_release_bdev(ns->bdev);
912 	spdk_bdev_close(ns->desc);
913 	free(ns);
914 
915 	spdk_nvmf_subsystem_ns_changed(subsystem, nsid);
916 
917 	return 0;
918 }
919 
920 int
921 spdk_nvmf_subsystem_remove_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid,
922 			      spdk_nvmf_subsystem_state_change_done cb_fn, void *cb_arg)
923 {
924 	int rc;
925 	struct subsystem_update_ns_ctx *ctx;
926 
927 	rc = _spdk_nvmf_subsystem_remove_ns(subsystem, nsid);
928 	if (rc < 0) {
929 		return rc;
930 	}
931 
932 	ctx = calloc(1, sizeof(*ctx));
933 
934 	if (ctx == NULL) {
935 		return -ENOMEM;
936 	}
937 
938 	ctx->subsystem = subsystem;
939 	ctx->cb_fn = cb_fn;
940 	ctx->cb_arg = cb_arg;
941 
942 	spdk_nvmf_subsystem_update_ns(subsystem, subsystem_update_ns_done, ctx);
943 
944 	return 0;
945 }
946 
947 static void
948 _spdk_nvmf_ns_hot_remove_done(struct spdk_nvmf_subsystem *subsystem, void *cb_arg, int status)
949 {
950 	if (status != 0) {
951 		SPDK_ERRLOG("Failed to make changes to NVMe-oF subsystem with id %u\n", subsystem->id);
952 	}
953 	spdk_nvmf_subsystem_resume(subsystem, NULL, NULL);
954 }
955 
956 static void
957 _spdk_nvmf_ns_hot_remove(struct spdk_nvmf_subsystem *subsystem,
958 			 void *cb_arg, int status)
959 {
960 	struct spdk_nvmf_ns *ns = cb_arg;
961 
962 	spdk_nvmf_subsystem_remove_ns(subsystem, ns->opts.nsid, _spdk_nvmf_ns_hot_remove_done,
963 				      subsystem);
964 }
965 
966 static void
967 spdk_nvmf_ns_hot_remove(void *remove_ctx)
968 {
969 	struct spdk_nvmf_ns *ns = remove_ctx;
970 	int rc;
971 
972 	rc = spdk_nvmf_subsystem_pause(ns->subsystem, _spdk_nvmf_ns_hot_remove, ns);
973 	if (rc) {
974 		SPDK_ERRLOG("Unable to pause subsystem to process namespace removal!\n");
975 	}
976 }
977 
978 void
979 spdk_nvmf_ns_opts_get_defaults(struct spdk_nvmf_ns_opts *opts, size_t opts_size)
980 {
981 	/* All current fields are set to 0 by default. */
982 	memset(opts, 0, opts_size);
983 }
984 
985 /* Dummy bdev module used to to claim bdevs. */
986 static struct spdk_bdev_module ns_bdev_module = {
987 	.name	= "NVMe-oF Target",
988 };
989 
990 uint32_t
991 spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bdev *bdev,
992 			   const struct spdk_nvmf_ns_opts *user_opts, size_t opts_size)
993 {
994 	struct spdk_nvmf_ns_opts opts;
995 	struct spdk_nvmf_ns *ns;
996 	int rc;
997 
998 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
999 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
1000 		return 0;
1001 	}
1002 
1003 	spdk_nvmf_ns_opts_get_defaults(&opts, sizeof(opts));
1004 	if (user_opts) {
1005 		memcpy(&opts, user_opts, spdk_min(sizeof(opts), opts_size));
1006 	}
1007 
1008 	if (spdk_mem_all_zero(&opts.uuid, sizeof(opts.uuid))) {
1009 		opts.uuid = *spdk_bdev_get_uuid(bdev);
1010 	}
1011 
1012 	if (opts.nsid == SPDK_NVME_GLOBAL_NS_TAG) {
1013 		SPDK_ERRLOG("Invalid NSID %" PRIu32 "\n", opts.nsid);
1014 		return 0;
1015 	}
1016 
1017 	if (opts.nsid == 0) {
1018 		/*
1019 		 * NSID not specified - find a free index.
1020 		 *
1021 		 * If no free slots are found, opts.nsid will be subsystem->max_nsid + 1, which will
1022 		 * expand max_nsid if possible.
1023 		 */
1024 		for (opts.nsid = 1; opts.nsid <= subsystem->max_nsid; opts.nsid++) {
1025 			if (_spdk_nvmf_subsystem_get_ns(subsystem, opts.nsid) == NULL) {
1026 				break;
1027 			}
1028 		}
1029 	}
1030 
1031 	if (_spdk_nvmf_subsystem_get_ns(subsystem, opts.nsid)) {
1032 		SPDK_ERRLOG("Requested NSID %" PRIu32 " already in use\n", opts.nsid);
1033 		return 0;
1034 	}
1035 
1036 	if (opts.nsid > subsystem->max_nsid) {
1037 		struct spdk_nvmf_ns **new_ns_array;
1038 
1039 		/* If MaxNamespaces was specified, we can't extend max_nsid beyond it. */
1040 		if (subsystem->max_allowed_nsid > 0 && opts.nsid > subsystem->max_allowed_nsid) {
1041 			SPDK_ERRLOG("Can't extend NSID range above MaxNamespaces\n");
1042 			return 0;
1043 		}
1044 
1045 		/* If a controller is connected, we can't change NN. */
1046 		if (!TAILQ_EMPTY(&subsystem->ctrlrs)) {
1047 			SPDK_ERRLOG("Can't extend NSID range while controllers are connected\n");
1048 			return 0;
1049 		}
1050 
1051 		new_ns_array = realloc(subsystem->ns, sizeof(struct spdk_nvmf_ns *) * opts.nsid);
1052 		if (new_ns_array == NULL) {
1053 			SPDK_ERRLOG("Memory allocation error while resizing namespace array.\n");
1054 			return 0;
1055 		}
1056 
1057 		memset(new_ns_array + subsystem->max_nsid, 0,
1058 		       sizeof(struct spdk_nvmf_ns *) * (opts.nsid - subsystem->max_nsid));
1059 		subsystem->ns = new_ns_array;
1060 		subsystem->max_nsid = opts.nsid;
1061 	}
1062 
1063 	ns = calloc(1, sizeof(*ns));
1064 	if (ns == NULL) {
1065 		SPDK_ERRLOG("Namespace allocation failed\n");
1066 		return 0;
1067 	}
1068 
1069 	ns->bdev = bdev;
1070 	ns->opts = opts;
1071 	ns->subsystem = subsystem;
1072 	rc = spdk_bdev_open(bdev, true, spdk_nvmf_ns_hot_remove, ns, &ns->desc);
1073 	if (rc != 0) {
1074 		SPDK_ERRLOG("Subsystem %s: bdev %s cannot be opened, error=%d\n",
1075 			    subsystem->subnqn, spdk_bdev_get_name(bdev), rc);
1076 		free(ns);
1077 		return 0;
1078 	}
1079 	rc = spdk_bdev_module_claim_bdev(bdev, ns->desc, &ns_bdev_module);
1080 	if (rc != 0) {
1081 		spdk_bdev_close(ns->desc);
1082 		free(ns);
1083 		return 0;
1084 	}
1085 	subsystem->ns[opts.nsid - 1] = ns;
1086 	ns->nsid = opts.nsid;
1087 	TAILQ_INIT(&ns->registrants);
1088 
1089 	SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Subsystem %s: bdev %s assigned nsid %" PRIu32 "\n",
1090 		      spdk_nvmf_subsystem_get_nqn(subsystem),
1091 		      spdk_bdev_get_name(bdev),
1092 		      opts.nsid);
1093 
1094 	spdk_nvmf_subsystem_ns_changed(subsystem, opts.nsid);
1095 
1096 	return opts.nsid;
1097 }
1098 
1099 static uint32_t
1100 spdk_nvmf_subsystem_get_next_allocated_nsid(struct spdk_nvmf_subsystem *subsystem,
1101 		uint32_t prev_nsid)
1102 {
1103 	uint32_t nsid;
1104 
1105 	if (prev_nsid >= subsystem->max_nsid) {
1106 		return 0;
1107 	}
1108 
1109 	for (nsid = prev_nsid + 1; nsid <= subsystem->max_nsid; nsid++) {
1110 		if (subsystem->ns[nsid - 1]) {
1111 			return nsid;
1112 		}
1113 	}
1114 
1115 	return 0;
1116 }
1117 
1118 struct spdk_nvmf_ns *
1119 spdk_nvmf_subsystem_get_first_ns(struct spdk_nvmf_subsystem *subsystem)
1120 {
1121 	uint32_t first_nsid;
1122 
1123 	first_nsid = spdk_nvmf_subsystem_get_next_allocated_nsid(subsystem, 0);
1124 	return _spdk_nvmf_subsystem_get_ns(subsystem, first_nsid);
1125 }
1126 
1127 struct spdk_nvmf_ns *
1128 spdk_nvmf_subsystem_get_next_ns(struct spdk_nvmf_subsystem *subsystem,
1129 				struct spdk_nvmf_ns *prev_ns)
1130 {
1131 	uint32_t next_nsid;
1132 
1133 	next_nsid = spdk_nvmf_subsystem_get_next_allocated_nsid(subsystem, prev_ns->opts.nsid);
1134 	return _spdk_nvmf_subsystem_get_ns(subsystem, next_nsid);
1135 }
1136 
1137 struct spdk_nvmf_ns *
1138 spdk_nvmf_subsystem_get_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid)
1139 {
1140 	return _spdk_nvmf_subsystem_get_ns(subsystem, nsid);
1141 }
1142 
1143 uint32_t
1144 spdk_nvmf_ns_get_id(const struct spdk_nvmf_ns *ns)
1145 {
1146 	return ns->opts.nsid;
1147 }
1148 
1149 struct spdk_bdev *
1150 spdk_nvmf_ns_get_bdev(struct spdk_nvmf_ns *ns)
1151 {
1152 	return ns->bdev;
1153 }
1154 
1155 void
1156 spdk_nvmf_ns_get_opts(const struct spdk_nvmf_ns *ns, struct spdk_nvmf_ns_opts *opts,
1157 		      size_t opts_size)
1158 {
1159 	memset(opts, 0, opts_size);
1160 	memcpy(opts, &ns->opts, spdk_min(sizeof(ns->opts), opts_size));
1161 }
1162 
1163 const char *
1164 spdk_nvmf_subsystem_get_sn(const struct spdk_nvmf_subsystem *subsystem)
1165 {
1166 	return subsystem->sn;
1167 }
1168 
1169 int
1170 spdk_nvmf_subsystem_set_sn(struct spdk_nvmf_subsystem *subsystem, const char *sn)
1171 {
1172 	size_t len, max_len;
1173 
1174 	max_len = sizeof(subsystem->sn) - 1;
1175 	len = strlen(sn);
1176 	if (len > max_len) {
1177 		SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Invalid sn \"%s\": length %zu > max %zu\n",
1178 			      sn, len, max_len);
1179 		return -1;
1180 	}
1181 
1182 	if (!spdk_nvmf_valid_ascii_string(sn, len)) {
1183 		SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Non-ASCII sn\n");
1184 		SPDK_LOGDUMP(SPDK_LOG_NVMF, "sn", sn, len);
1185 		return -1;
1186 	}
1187 
1188 	snprintf(subsystem->sn, sizeof(subsystem->sn), "%s", sn);
1189 
1190 	return 0;
1191 }
1192 
1193 const char *
1194 spdk_nvmf_subsystem_get_nqn(struct spdk_nvmf_subsystem *subsystem)
1195 {
1196 	return subsystem->subnqn;
1197 }
1198 
1199 /* Workaround for astyle formatting bug */
1200 typedef enum spdk_nvmf_subtype nvmf_subtype_t;
1201 
1202 nvmf_subtype_t
1203 spdk_nvmf_subsystem_get_type(struct spdk_nvmf_subsystem *subsystem)
1204 {
1205 	return subsystem->subtype;
1206 }
1207 
1208 static uint16_t
1209 spdk_nvmf_subsystem_gen_cntlid(struct spdk_nvmf_subsystem *subsystem)
1210 {
1211 	int count;
1212 
1213 	/*
1214 	 * In the worst case, we might have to try all CNTLID values between 1 and 0xFFF0 - 1
1215 	 * before we find one that is unused (or find that all values are in use).
1216 	 */
1217 	for (count = 0; count < 0xFFF0 - 1; count++) {
1218 		subsystem->next_cntlid++;
1219 		if (subsystem->next_cntlid >= 0xFFF0) {
1220 			/* The spec reserves cntlid values in the range FFF0h to FFFFh. */
1221 			subsystem->next_cntlid = 1;
1222 		}
1223 
1224 		/* Check if a controller with this cntlid currently exists. */
1225 		if (spdk_nvmf_subsystem_get_ctrlr(subsystem, subsystem->next_cntlid) == NULL) {
1226 			/* Found unused cntlid */
1227 			return subsystem->next_cntlid;
1228 		}
1229 	}
1230 
1231 	/* All valid cntlid values are in use. */
1232 	return 0xFFFF;
1233 }
1234 
1235 int
1236 spdk_nvmf_subsystem_add_ctrlr(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *ctrlr)
1237 {
1238 	ctrlr->cntlid = spdk_nvmf_subsystem_gen_cntlid(subsystem);
1239 	if (ctrlr->cntlid == 0xFFFF) {
1240 		/* Unable to get a cntlid */
1241 		SPDK_ERRLOG("Reached max simultaneous ctrlrs\n");
1242 		return -EBUSY;
1243 	}
1244 
1245 	TAILQ_INSERT_TAIL(&subsystem->ctrlrs, ctrlr, link);
1246 
1247 	return 0;
1248 }
1249 
1250 void
1251 spdk_nvmf_subsystem_remove_ctrlr(struct spdk_nvmf_subsystem *subsystem,
1252 				 struct spdk_nvmf_ctrlr *ctrlr)
1253 {
1254 	assert(subsystem == ctrlr->subsys);
1255 	TAILQ_REMOVE(&subsystem->ctrlrs, ctrlr, link);
1256 }
1257 
1258 struct spdk_nvmf_ctrlr *
1259 spdk_nvmf_subsystem_get_ctrlr(struct spdk_nvmf_subsystem *subsystem, uint16_t cntlid)
1260 {
1261 	struct spdk_nvmf_ctrlr *ctrlr;
1262 
1263 	TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) {
1264 		if (ctrlr->cntlid == cntlid) {
1265 			return ctrlr;
1266 		}
1267 	}
1268 
1269 	return NULL;
1270 }
1271 
1272 uint32_t
1273 spdk_nvmf_subsystem_get_max_namespaces(const struct spdk_nvmf_subsystem *subsystem)
1274 {
1275 	return subsystem->max_allowed_nsid;
1276 }
1277 
1278 static struct spdk_nvmf_registrant *
1279 nvmf_ns_reservation_get_registrant(struct spdk_nvmf_ns *ns,
1280 				   struct spdk_uuid *uuid)
1281 {
1282 	struct spdk_nvmf_registrant *reg, *tmp;
1283 
1284 	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) {
1285 		if (spdk_uuid_compare(&reg->hostid, uuid) == 0) {
1286 			return reg;
1287 		}
1288 	}
1289 
1290 	return NULL;
1291 }
1292 
1293 /* current reservation type is all registrants or not */
1294 static bool
1295 nvmf_ns_reservation_all_registrants_type(struct spdk_nvmf_ns *ns)
1296 {
1297 	return (ns->rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS ||
1298 		ns->rtype == SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_ALL_REGS);
1299 }
1300 
1301 /* current registrant is reservation holder or not */
1302 static bool
1303 nvmf_ns_reservation_registrant_is_holder(struct spdk_nvmf_ns *ns,
1304 		struct spdk_nvmf_registrant *reg)
1305 {
1306 	if (!reg) {
1307 		return false;
1308 	}
1309 
1310 	if (nvmf_ns_reservation_all_registrants_type(ns)) {
1311 		return true;
1312 	}
1313 
1314 	return (ns->holder == reg);
1315 }
1316 
1317 static int
1318 nvmf_ns_reservation_add_registrant(struct spdk_nvmf_ns *ns,
1319 				   struct spdk_nvmf_ctrlr *ctrlr,
1320 				   uint64_t nrkey)
1321 {
1322 	struct spdk_nvmf_registrant *reg;
1323 
1324 	reg = calloc(1, sizeof(*reg));
1325 	if (!reg) {
1326 		return -ENOMEM;
1327 	}
1328 
1329 	reg->rkey = nrkey;
1330 	/* set hostid for the registrant */
1331 	spdk_uuid_copy(&reg->hostid, &ctrlr->hostid);
1332 	TAILQ_INSERT_TAIL(&ns->registrants, reg, link);
1333 	ns->gen++;
1334 
1335 	return 0;
1336 }
1337 
1338 static void
1339 nvmf_ns_reservation_release_reservation(struct spdk_nvmf_ns *ns)
1340 {
1341 	ns->rtype = 0;
1342 	ns->crkey = 0;
1343 	ns->holder = NULL;
1344 }
1345 
1346 /* release the reservation if the last registrant was removed */
1347 static void
1348 nvmf_ns_reservation_check_release_on_remove_registrant(struct spdk_nvmf_ns *ns,
1349 		struct spdk_nvmf_registrant *reg)
1350 {
1351 	struct spdk_nvmf_registrant *next_reg;
1352 
1353 	/* no reservation holder */
1354 	if (!ns->holder) {
1355 		assert(ns->rtype == 0);
1356 		return;
1357 	}
1358 
1359 	next_reg = TAILQ_FIRST(&ns->registrants);
1360 	if (next_reg && nvmf_ns_reservation_all_registrants_type(ns)) {
1361 		/* the next valid registrant is the new holder now */
1362 		ns->holder = next_reg;
1363 	} else if (nvmf_ns_reservation_registrant_is_holder(ns, reg)) {
1364 		/* release the reservation */
1365 		nvmf_ns_reservation_release_reservation(ns);
1366 	}
1367 }
1368 
1369 static void
1370 nvmf_ns_reservation_remove_registrant(struct spdk_nvmf_ns *ns,
1371 				      struct spdk_nvmf_registrant *reg)
1372 {
1373 	TAILQ_REMOVE(&ns->registrants, reg, link);
1374 	nvmf_ns_reservation_check_release_on_remove_registrant(ns, reg);
1375 	free(reg);
1376 	ns->gen++;
1377 	return;
1378 }
1379 
1380 static uint32_t
1381 nvmf_ns_reservation_remove_registrants_by_key(struct spdk_nvmf_ns *ns,
1382 		uint64_t rkey)
1383 {
1384 	struct spdk_nvmf_registrant *reg, *tmp;
1385 	uint32_t count = 0;
1386 
1387 	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) {
1388 		if (reg->rkey == rkey) {
1389 			nvmf_ns_reservation_remove_registrant(ns, reg);
1390 			count++;
1391 		}
1392 	}
1393 	return count;
1394 }
1395 
1396 static uint32_t
1397 nvmf_ns_reservation_remove_all_other_registrants(struct spdk_nvmf_ns *ns,
1398 		struct spdk_nvmf_registrant *reg)
1399 {
1400 	struct spdk_nvmf_registrant *reg_tmp, *reg_tmp2;
1401 	uint32_t count = 0;
1402 
1403 	TAILQ_FOREACH_SAFE(reg_tmp, &ns->registrants, link, reg_tmp2) {
1404 		if (reg_tmp != reg) {
1405 			nvmf_ns_reservation_remove_registrant(ns, reg_tmp);
1406 			count++;
1407 		}
1408 	}
1409 	return count;
1410 }
1411 
1412 static uint32_t
1413 nvmf_ns_reservation_clear_all_registrants(struct spdk_nvmf_ns *ns)
1414 {
1415 	struct spdk_nvmf_registrant *reg, *reg_tmp;
1416 	uint32_t count = 0;
1417 
1418 	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, reg_tmp) {
1419 		nvmf_ns_reservation_remove_registrant(ns, reg);
1420 		count++;
1421 	}
1422 	return count;
1423 }
1424 
1425 static void
1426 nvmf_ns_reservation_acquire_reservation(struct spdk_nvmf_ns *ns, uint64_t rkey,
1427 					enum spdk_nvme_reservation_type rtype,
1428 					struct spdk_nvmf_registrant *holder)
1429 {
1430 	ns->rtype = rtype;
1431 	ns->crkey = rkey;
1432 	assert(ns->holder == NULL);
1433 	ns->holder = holder;
1434 }
1435 
1436 static void
1437 nvmf_ns_reservation_register(struct spdk_nvmf_ns *ns,
1438 			     struct spdk_nvmf_ctrlr *ctrlr,
1439 			     struct spdk_nvmf_request *req)
1440 {
1441 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
1442 	uint8_t rrega, iekey, cptpl;
1443 	struct spdk_nvme_reservation_register_data key;
1444 	struct spdk_nvmf_registrant *reg;
1445 	uint8_t status = SPDK_NVME_SC_SUCCESS;
1446 	int rc;
1447 
1448 	rrega = cmd->cdw10 & 0x7u;
1449 	iekey = (cmd->cdw10 >> 3) & 0x1u;
1450 	cptpl = (cmd->cdw10 >> 30) & 0x3u;
1451 	memcpy(&key, req->data, sizeof(key));
1452 
1453 	SPDK_DEBUGLOG(SPDK_LOG_NVMF, "REGISTER: RREGA %u, IEKEY %u, CPTPL %u, "
1454 		      "NRKEY 0x%"PRIx64", NRKEY 0x%"PRIx64"\n",
1455 		      rrega, iekey, cptpl, key.crkey, key.nrkey);
1456 
1457 	/* TODO: doesn't support for now */
1458 	if (cptpl == SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS) {
1459 		SPDK_ERRLOG("Can't change persist through power loss for now\n");
1460 		status = SPDK_NVME_SC_INVALID_FIELD;
1461 		goto exit;
1462 	}
1463 
1464 	/* current Host Identifier has registrant or not */
1465 	reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid);
1466 
1467 	switch (rrega) {
1468 	case SPDK_NVME_RESERVE_REGISTER_KEY:
1469 		if (!reg) {
1470 			/* register new controller */
1471 			if (key.nrkey == 0) {
1472 				SPDK_ERRLOG("Can't register zeroed new key\n");
1473 				status = SPDK_NVME_SC_INVALID_FIELD;
1474 				goto exit;
1475 			}
1476 			rc = nvmf_ns_reservation_add_registrant(ns, ctrlr, key.nrkey);
1477 			if (rc < 0) {
1478 				status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
1479 				goto exit;
1480 			}
1481 		} else {
1482 			/* register with same key is not an error */
1483 			if (reg->rkey != key.nrkey) {
1484 				SPDK_ERRLOG("The same host already register a "
1485 					    "key with 0x%"PRIx64"\n",
1486 					    reg->rkey);
1487 				status = SPDK_NVME_SC_RESERVATION_CONFLICT;
1488 				goto exit;
1489 			}
1490 		}
1491 		break;
1492 	case SPDK_NVME_RESERVE_UNREGISTER_KEY:
1493 		if (!reg || (!iekey && reg->rkey != key.crkey)) {
1494 			SPDK_ERRLOG("No registrant or current key doesn't match "
1495 				    "with existing registrant key\n");
1496 			status = SPDK_NVME_SC_RESERVATION_CONFLICT;
1497 			goto exit;
1498 		}
1499 		nvmf_ns_reservation_remove_registrant(ns, reg);
1500 		break;
1501 	case SPDK_NVME_RESERVE_REPLACE_KEY:
1502 		if (!reg || (!iekey && reg->rkey != key.crkey)) {
1503 			SPDK_ERRLOG("No registrant or current key doesn't match "
1504 				    "with existing registrant key\n");
1505 			status = SPDK_NVME_SC_RESERVATION_CONFLICT;
1506 			goto exit;
1507 		}
1508 		if (key.nrkey == 0) {
1509 			SPDK_ERRLOG("Can't register zeroed new key\n");
1510 			status = SPDK_NVME_SC_INVALID_FIELD;
1511 			goto exit;
1512 		}
1513 		reg->rkey = key.nrkey;
1514 		break;
1515 	default:
1516 		status = SPDK_NVME_SC_INVALID_FIELD;
1517 		goto exit;
1518 	}
1519 
1520 exit:
1521 	req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC;
1522 	req->rsp->nvme_cpl.status.sc = status;
1523 	return;
1524 }
1525 
1526 static void
1527 nvmf_ns_reservation_acquire(struct spdk_nvmf_ns *ns,
1528 			    struct spdk_nvmf_ctrlr *ctrlr,
1529 			    struct spdk_nvmf_request *req)
1530 {
1531 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
1532 	uint8_t racqa, iekey, rtype;
1533 	struct spdk_nvme_reservation_acquire_data key;
1534 	struct spdk_nvmf_registrant *reg;
1535 	bool all_regs = false;
1536 	uint32_t count = 0;
1537 	uint8_t status = SPDK_NVME_SC_SUCCESS;
1538 
1539 	racqa = cmd->cdw10 & 0x7u;
1540 	iekey = (cmd->cdw10 >> 3) & 0x1u;
1541 	rtype = (cmd->cdw10 >> 8) & 0xffu;
1542 	memcpy(&key, req->data, sizeof(key));
1543 
1544 	SPDK_DEBUGLOG(SPDK_LOG_NVMF, "ACQUIIRE: RACQA %u, IEKEY %u, RTYPE %u, "
1545 		      "NRKEY 0x%"PRIx64", PRKEY 0x%"PRIx64"\n",
1546 		      racqa, iekey, rtype, key.crkey, key.prkey);
1547 
1548 	if (iekey) {
1549 		SPDK_ERRLOG("Ignore existing key field set to 1\n");
1550 		status = SPDK_NVME_SC_INVALID_FIELD;
1551 		goto exit;
1552 	}
1553 
1554 	reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid);
1555 	/* must be registrant and CRKEY must match */
1556 	if (!reg || reg->rkey != key.crkey) {
1557 		SPDK_ERRLOG("No registrant or current key doesn't match "
1558 			    "with existing registrant key\n");
1559 		status = SPDK_NVME_SC_RESERVATION_CONFLICT;
1560 		goto exit;
1561 	}
1562 
1563 	all_regs = nvmf_ns_reservation_all_registrants_type(ns);
1564 
1565 	switch (racqa) {
1566 	case SPDK_NVME_RESERVE_ACQUIRE:
1567 		/* it's not an error for the holder to acquire same reservation type again */
1568 		if (nvmf_ns_reservation_registrant_is_holder(ns, reg) && ns->rtype == rtype) {
1569 			/* do nothing */
1570 		} else if (ns->holder == NULL) {
1571 			/* fisrt time to acquire the reservation */
1572 			nvmf_ns_reservation_acquire_reservation(ns, key.crkey, rtype, reg);
1573 		} else {
1574 			SPDK_ERRLOG("Invalid rtype or current registrant is not holder\n");
1575 			status = SPDK_NVME_SC_RESERVATION_CONFLICT;
1576 			goto exit;
1577 		}
1578 		break;
1579 	case SPDK_NVME_RESERVE_PREEMPT:
1580 		/* no reservation holder */
1581 		if (!ns->holder) {
1582 			/* unregister with PRKEY */
1583 			nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey);
1584 			break;
1585 		}
1586 		/* only 1 reservation holder and reservation key is valid */
1587 		if (!all_regs) {
1588 			/* preempt itself */
1589 			if (nvmf_ns_reservation_registrant_is_holder(ns, reg) &&
1590 			    ns->crkey == key.prkey) {
1591 				ns->rtype = rtype;
1592 				break;
1593 			}
1594 
1595 			if (ns->crkey == key.prkey) {
1596 				nvmf_ns_reservation_remove_registrant(ns, ns->holder);
1597 				nvmf_ns_reservation_acquire_reservation(ns, key.crkey, rtype, reg);
1598 			} else if (key.prkey != 0) {
1599 				nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey);
1600 			} else {
1601 				/* PRKEY is zero */
1602 				SPDK_ERRLOG("Current PRKEY is zero\n");
1603 				status = SPDK_NVME_SC_RESERVATION_CONFLICT;
1604 				goto exit;
1605 			}
1606 		} else {
1607 			/* release all other registrants except for the current one */
1608 			if (key.prkey == 0) {
1609 				nvmf_ns_reservation_remove_all_other_registrants(ns, reg);
1610 				assert(ns->holder == reg);
1611 			} else {
1612 				count = nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey);
1613 				if (count == 0) {
1614 					SPDK_ERRLOG("PRKEY doesn't match any registrant\n");
1615 					status = SPDK_NVME_SC_RESERVATION_CONFLICT;
1616 					goto exit;
1617 				}
1618 			}
1619 		}
1620 		break;
1621 	default:
1622 		break;
1623 	}
1624 
1625 exit:
1626 	req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC;
1627 	req->rsp->nvme_cpl.status.sc = status;
1628 	return;
1629 }
1630 
1631 static void
1632 nvmf_ns_reservation_release(struct spdk_nvmf_ns *ns,
1633 			    struct spdk_nvmf_ctrlr *ctrlr,
1634 			    struct spdk_nvmf_request *req)
1635 {
1636 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
1637 	uint8_t rrela, iekey, rtype;
1638 	struct spdk_nvmf_registrant *reg;
1639 	uint64_t crkey;
1640 	uint8_t status = SPDK_NVME_SC_SUCCESS;
1641 
1642 	rrela = cmd->cdw10 & 0x7u;
1643 	iekey = (cmd->cdw10 >> 3) & 0x1u;
1644 	rtype = (cmd->cdw10 >> 8) & 0xffu;
1645 	memcpy(&crkey, req->data, sizeof(crkey));
1646 
1647 	SPDK_DEBUGLOG(SPDK_LOG_NVMF, "RELEASE: RRELA %u, IEKEY %u, RTYPE %u, "
1648 		      "CRKEY 0x%"PRIx64"\n",  rrela, iekey, rtype, crkey);
1649 
1650 	if (iekey) {
1651 		SPDK_ERRLOG("Ignore existing key field set to 1\n");
1652 		status = SPDK_NVME_SC_INVALID_FIELD;
1653 		goto exit;
1654 	}
1655 
1656 	reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid);
1657 	if (!reg || reg->rkey != crkey) {
1658 		SPDK_ERRLOG("No registrant or current key doesn't match "
1659 			    "with existing registrant key\n");
1660 		status = SPDK_NVME_SC_RESERVATION_CONFLICT;
1661 		goto exit;
1662 	}
1663 
1664 	switch (rrela) {
1665 	case SPDK_NVME_RESERVE_RELEASE:
1666 		if (!ns->holder) {
1667 			SPDK_DEBUGLOG(SPDK_LOG_NVMF, "RELEASE: no holder\n");
1668 			goto exit;
1669 		}
1670 		if (ns->rtype != rtype) {
1671 			SPDK_ERRLOG("Type doesn't match\n");
1672 			status = SPDK_NVME_SC_INVALID_FIELD;
1673 			goto exit;
1674 		}
1675 		if (!nvmf_ns_reservation_registrant_is_holder(ns, reg)) {
1676 			/* not the reservation holder, this isn't an error */
1677 			goto exit;
1678 		}
1679 		nvmf_ns_reservation_release_reservation(ns);
1680 		break;
1681 	case SPDK_NVME_RESERVE_CLEAR:
1682 		nvmf_ns_reservation_clear_all_registrants(ns);
1683 		break;
1684 	default:
1685 		status = SPDK_NVME_SC_INVALID_FIELD;
1686 		goto exit;
1687 	}
1688 
1689 exit:
1690 	req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC;
1691 	req->rsp->nvme_cpl.status.sc = status;
1692 	return;
1693 }
1694 
1695 static void
1696 spdk_nvmf_ns_reservation_complete(void *ctx)
1697 {
1698 	struct spdk_nvmf_request *req = ctx;
1699 
1700 	spdk_nvmf_request_complete(req);
1701 }
1702 
1703 void
1704 spdk_nvmf_ns_reservation_request(void *ctx)
1705 {
1706 	struct spdk_nvmf_request *req = (struct spdk_nvmf_request *)ctx;
1707 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
1708 	struct spdk_nvmf_poll_group *group = req->qpair->group;
1709 	struct spdk_nvmf_ctrlr *ctrlr = req->qpair->ctrlr;
1710 	uint32_t nsid;
1711 	struct spdk_nvmf_ns *ns;
1712 
1713 	nsid = cmd->nsid;
1714 	ns = _spdk_nvmf_subsystem_get_ns(ctrlr->subsys, nsid);
1715 	assert(ns != NULL);
1716 
1717 	switch (cmd->opc) {
1718 	case SPDK_NVME_OPC_RESERVATION_REGISTER:
1719 		nvmf_ns_reservation_register(ns, ctrlr, req);
1720 		break;
1721 	case SPDK_NVME_OPC_RESERVATION_ACQUIRE:
1722 		nvmf_ns_reservation_acquire(ns, ctrlr, req);
1723 		break;
1724 	case SPDK_NVME_OPC_RESERVATION_RELEASE:
1725 		nvmf_ns_reservation_release(ns, ctrlr, req);
1726 		break;
1727 	default:
1728 		break;
1729 	}
1730 	spdk_thread_send_msg(group->thread, spdk_nvmf_ns_reservation_complete, req);
1731 }
1732