xref: /spdk/lib/nvmf/subsystem.c (revision 9aed854be08215eb96edeff897e8a25a2858dc78)
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 
45 #include "spdk_internal/bdev.h"
46 #include "spdk_internal/log.h"
47 #include "spdk_internal/utf.h"
48 
49 #include <uuid/uuid.h>
50 
51 /*
52  * States for parsing valid domains in NQNs according to RFC 1034
53  */
54 enum spdk_nvmf_nqn_domain_states {
55 	/* First character of a domain must be a letter */
56 	SPDK_NVMF_DOMAIN_ACCEPT_LETTER = 0,
57 
58 	/* Subsequent characters can be any of letter, digit, or hyphen */
59 	SPDK_NVMF_DOMAIN_ACCEPT_LDH = 1,
60 
61 	/* A domain label must end with either a letter or digit */
62 	SPDK_NVMF_DOMAIN_ACCEPT_ANY = 2
63 };
64 
65 static bool
66 spdk_nvmf_valid_nqn(const char *nqn)
67 {
68 	size_t len;
69 	uuid_t uuid_value;
70 	uint i;
71 	int bytes_consumed;
72 	uint domain_label_length;
73 	char *reverse_domain_end;
74 	uint reverse_domain_end_index;
75 	enum spdk_nvmf_nqn_domain_states domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LETTER;
76 
77 	/* Check for length requirements */
78 	len = strlen(nqn);
79 	if (len > SPDK_NVMF_NQN_MAX_LEN) {
80 		SPDK_ERRLOG("Invalid NQN \"%s\": length %zu > max %d\n", nqn, len, SPDK_NVMF_NQN_MAX_LEN);
81 		return false;
82 	}
83 
84 	/* The nqn must be at least as long as SPDK_NVMF_NQN_MIN_LEN to contain the necessary prefix. */
85 	if (len < SPDK_NVMF_NQN_MIN_LEN) {
86 		SPDK_ERRLOG("Invalid NQN \"%s\": length %zu < min %d\n", nqn, len, SPDK_NVMF_NQN_MIN_LEN);
87 		return false;
88 	}
89 
90 	/* Check for discovery controller nqn */
91 	if (!strcmp(nqn, SPDK_NVMF_DISCOVERY_NQN)) {
92 		return true;
93 	}
94 
95 	/* Check for equality with the generic nqn structure of the form "nqn.2014-08.org.nvmexpress:uuid:11111111-2222-3333-4444-555555555555" */
96 	if (!strncmp(nqn, SPDK_NVMF_NQN_UUID_PRE, SPDK_NVMF_NQN_UUID_PRE_LEN)) {
97 		if (len != SPDK_NVMF_NQN_UUID_PRE_LEN + SPDK_NVMF_UUID_STRING_LEN) {
98 			SPDK_ERRLOG("Invalid NQN \"%s\": uuid is not the correct length\n", nqn);
99 			return false;
100 		}
101 
102 		if (uuid_parse(&nqn[SPDK_NVMF_NQN_UUID_PRE_LEN], uuid_value) == -1) {
103 			SPDK_ERRLOG("Invalid NQN \"%s\": uuid is not formatted correctly\n", nqn);
104 			return false;
105 		}
106 		return true;
107 	}
108 
109 	/* If the nqn does not match the uuid structure, the next several checks validate the form "nqn.yyyy-mm.reverse.domain:user-string" */
110 
111 	if (strncmp(nqn, "nqn.", 4) != 0) {
112 		SPDK_ERRLOG("Invalid NQN \"%s\": NQN must begin with \"nqn.\".\n", nqn);
113 		return false;
114 	}
115 
116 	/* Check for yyyy-mm. */
117 	if (!(isdigit(nqn[4]) && isdigit(nqn[5]) && isdigit(nqn[6]) && isdigit(nqn[7]) &&
118 	      nqn[8] == '-' && isdigit(nqn[9]) && isdigit(nqn[10]) && nqn[11] == '.')) {
119 		SPDK_ERRLOG("Invalid date code in NQN \"%s\"\n", nqn);
120 		return false;
121 	}
122 
123 	reverse_domain_end = strchr(nqn, ':');
124 	if (reverse_domain_end != NULL && (reverse_domain_end_index = reverse_domain_end - nqn) < len - 1) {
125 	} else {
126 		SPDK_ERRLOG("Invalid NQN \"%s\". NQN must contain user specified name with a ':' as a prefix.\n",
127 			    nqn);
128 		return false;
129 	}
130 
131 	/* Check for valid reverse domain */
132 	domain_label_length = 0;
133 	for (i = 12; i < reverse_domain_end_index; i++) {
134 		if (domain_label_length > SPDK_DOMAIN_LABEL_MAX_LEN) {
135 			SPDK_ERRLOG("Invalid domain name in NQN \"%s\". At least one Label is too long.\n", nqn);
136 			return false;
137 		}
138 
139 		switch (domain_state) {
140 
141 		case SPDK_NVMF_DOMAIN_ACCEPT_LETTER: {
142 			if (isalpha(nqn[i])) {
143 				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_ANY;
144 				domain_label_length++;
145 				break;
146 			} else {
147 				SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must start with a letter.\n", nqn);
148 				return false;
149 			}
150 		}
151 
152 		case SPDK_NVMF_DOMAIN_ACCEPT_LDH: {
153 			if (isalpha(nqn[i]) || isdigit(nqn[i])) {
154 				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_ANY;
155 				domain_label_length++;
156 				break;
157 			} else if (nqn[i] == '-') {
158 				if (i == reverse_domain_end_index - 1) {
159 					SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must end with an alphanumeric symbol.\n",
160 						    nqn);
161 					return false;
162 				}
163 				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LDH;
164 				domain_label_length++;
165 				break;
166 			} else if (nqn[i] == '.') {
167 				SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must end with an alphanumeric symbol.\n",
168 					    nqn);
169 				return false;
170 			} else {
171 				SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must contain only [a-z,A-Z,0-9,'-','.'].\n",
172 					    nqn);
173 				return false;
174 			}
175 		}
176 
177 		case SPDK_NVMF_DOMAIN_ACCEPT_ANY: {
178 			if (isalpha(nqn[i]) || isdigit(nqn[i])) {
179 				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_ANY;
180 				domain_label_length++;
181 				break;
182 			} else if (nqn[i] == '-') {
183 				if (i == reverse_domain_end_index - 1) {
184 					SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must end with an alphanumeric symbol.\n",
185 						    nqn);
186 					return false;
187 				}
188 				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LDH;
189 				domain_label_length++;
190 				break;
191 			} else if (nqn[i] == '.') {
192 				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LETTER;
193 				domain_label_length = 0;
194 				break;
195 			} else {
196 				SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must contain only [a-z,A-Z,0-9,'-','.'].\n",
197 					    nqn);
198 				return false;
199 			}
200 		}
201 		}
202 	}
203 
204 	i = reverse_domain_end_index + 1;
205 	while (i < len) {
206 		bytes_consumed = utf8_valid(&nqn[i], &nqn[len]);
207 		if (bytes_consumed <= 0) {
208 			SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must contain only valid utf-8.\n", nqn);
209 			return false;
210 		}
211 
212 		i += bytes_consumed;
213 	}
214 	return true;
215 }
216 
217 struct spdk_nvmf_subsystem *
218 spdk_nvmf_subsystem_create(struct spdk_nvmf_tgt *tgt,
219 			   const char *nqn,
220 			   enum spdk_nvmf_subtype type,
221 			   uint32_t num_ns)
222 {
223 	struct spdk_nvmf_subsystem	*subsystem;
224 	uint32_t			sid;
225 
226 	if (!spdk_nvmf_valid_nqn(nqn)) {
227 		return NULL;
228 	}
229 
230 	if (type == SPDK_NVMF_SUBTYPE_DISCOVERY && num_ns != 0) {
231 		SPDK_ERRLOG("Discovery subsystem cannot have namespaces.\n");
232 		return NULL;
233 	}
234 
235 	/* Find a free subsystem id (sid) */
236 	for (sid = 0; sid < tgt->max_sid; sid++) {
237 		if (tgt->subsystems[sid] == NULL) {
238 			break;
239 		}
240 	}
241 	if (sid == tgt->max_sid) {
242 		struct spdk_nvmf_subsystem **subsys_array;
243 		/* No free slots. Add more. */
244 		tgt->max_sid++;
245 		subsys_array = realloc(tgt->subsystems, tgt->max_sid * sizeof(struct spdk_nvmf_subsystem *));
246 		if (!subsys_array) {
247 			tgt->max_sid--;
248 			return NULL;
249 		}
250 		tgt->subsystems = subsys_array;
251 	}
252 
253 	subsystem = calloc(1, sizeof(struct spdk_nvmf_subsystem));
254 	if (subsystem == NULL) {
255 		return NULL;
256 	}
257 
258 	subsystem->state = SPDK_NVMF_SUBSYSTEM_INACTIVE;
259 	subsystem->tgt = tgt;
260 	subsystem->id = sid;
261 	subsystem->subtype = type;
262 	subsystem->max_nsid = num_ns;
263 	subsystem->num_allocated_nsid = 0;
264 	subsystem->next_cntlid = 0;
265 	snprintf(subsystem->subnqn, sizeof(subsystem->subnqn), "%s", nqn);
266 	TAILQ_INIT(&subsystem->listeners);
267 	TAILQ_INIT(&subsystem->hosts);
268 	TAILQ_INIT(&subsystem->ctrlrs);
269 
270 	if (num_ns != 0) {
271 		subsystem->ns = calloc(num_ns, sizeof(struct spdk_nvmf_ns));
272 		if (subsystem->ns == NULL) {
273 			SPDK_ERRLOG("Namespace memory allocation failed\n");
274 			free(subsystem);
275 			return NULL;
276 		}
277 	}
278 
279 	tgt->subsystems[sid] = subsystem;
280 	tgt->discovery_genctr++;
281 
282 	return subsystem;
283 }
284 
285 void
286 spdk_nvmf_subsystem_destroy(struct spdk_nvmf_subsystem *subsystem)
287 {
288 	struct spdk_nvmf_listener	*listener, *listener_tmp;
289 	struct spdk_nvmf_host		*host, *host_tmp;
290 	struct spdk_nvmf_ctrlr		*ctrlr, *ctrlr_tmp;
291 	struct spdk_nvmf_ns		*ns;
292 
293 	if (!subsystem) {
294 		return;
295 	}
296 
297 	assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE);
298 
299 	SPDK_DEBUGLOG(SPDK_LOG_NVMF, "subsystem is %p\n", subsystem);
300 
301 	TAILQ_FOREACH_SAFE(listener, &subsystem->listeners, link, listener_tmp) {
302 		TAILQ_REMOVE(&subsystem->listeners, listener, link);
303 		free(listener);
304 	}
305 
306 	TAILQ_FOREACH_SAFE(host, &subsystem->hosts, link, host_tmp) {
307 		TAILQ_REMOVE(&subsystem->hosts, host, link);
308 		free(host->nqn);
309 		free(host);
310 	}
311 
312 	TAILQ_FOREACH_SAFE(ctrlr, &subsystem->ctrlrs, link, ctrlr_tmp) {
313 		spdk_nvmf_ctrlr_destruct(ctrlr);
314 	}
315 
316 	for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL;
317 	     ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns)) {
318 		if (ns->bdev == NULL) {
319 			continue;
320 		}
321 		spdk_bdev_close(ns->desc);
322 	}
323 
324 	free(subsystem->ns);
325 
326 	subsystem->tgt->subsystems[subsystem->id] = NULL;
327 	subsystem->tgt->discovery_genctr++;
328 
329 	free(subsystem);
330 }
331 
332 static int
333 spdk_nvmf_subsystem_set_state(struct spdk_nvmf_subsystem *subsystem,
334 			      enum spdk_nvmf_subsystem_state state)
335 {
336 	enum spdk_nvmf_subsystem_state actual_old_state, expected_old_state;
337 
338 	switch (state) {
339 	case SPDK_NVMF_SUBSYSTEM_INACTIVE:
340 		expected_old_state = SPDK_NVMF_SUBSYSTEM_DEACTIVATING;
341 		break;
342 	case SPDK_NVMF_SUBSYSTEM_ACTIVATING:
343 		expected_old_state = SPDK_NVMF_SUBSYSTEM_INACTIVE;
344 		break;
345 	case SPDK_NVMF_SUBSYSTEM_ACTIVE:
346 		expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING;
347 		break;
348 	case SPDK_NVMF_SUBSYSTEM_PAUSING:
349 		expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
350 		break;
351 	case SPDK_NVMF_SUBSYSTEM_PAUSED:
352 		expected_old_state = SPDK_NVMF_SUBSYSTEM_PAUSING;
353 		break;
354 	case SPDK_NVMF_SUBSYSTEM_RESUMING:
355 		expected_old_state = SPDK_NVMF_SUBSYSTEM_PAUSED;
356 		break;
357 	case SPDK_NVMF_SUBSYSTEM_DEACTIVATING:
358 		expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
359 		break;
360 	default:
361 		assert(false);
362 		return -1;
363 	}
364 
365 	actual_old_state = __sync_val_compare_and_swap(&subsystem->state, expected_old_state, state);
366 	if (actual_old_state != expected_old_state) {
367 		if (actual_old_state == SPDK_NVMF_SUBSYSTEM_RESUMING &&
368 		    state == SPDK_NVMF_SUBSYSTEM_ACTIVE) {
369 			expected_old_state = SPDK_NVMF_SUBSYSTEM_RESUMING;
370 		}
371 		actual_old_state = __sync_val_compare_and_swap(&subsystem->state, expected_old_state, state);
372 	}
373 	assert(actual_old_state == expected_old_state);
374 	return actual_old_state - expected_old_state;
375 }
376 
377 struct subsystem_state_change_ctx {
378 	struct spdk_nvmf_subsystem *subsystem;
379 
380 	enum spdk_nvmf_subsystem_state requested_state;
381 
382 	spdk_nvmf_subsystem_state_change_done cb_fn;
383 	void *cb_arg;
384 };
385 
386 static void
387 subsystem_state_change_done(struct spdk_io_channel_iter *i, int status)
388 {
389 	struct subsystem_state_change_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
390 
391 	if (status == 0) {
392 		status = spdk_nvmf_subsystem_set_state(ctx->subsystem, ctx->requested_state);
393 		if (status) {
394 			status = -1;
395 		}
396 	}
397 
398 	if (ctx->cb_fn) {
399 		ctx->cb_fn(ctx->subsystem, ctx->cb_arg, status);
400 	}
401 	free(ctx);
402 }
403 
404 static void
405 subsystem_state_change_on_pg(struct spdk_io_channel_iter *i)
406 {
407 	struct subsystem_state_change_ctx *ctx;
408 	struct spdk_io_channel *ch;
409 	struct spdk_nvmf_poll_group *group;
410 	int rc = -1;
411 
412 	ctx = spdk_io_channel_iter_get_ctx(i);
413 	ch = spdk_io_channel_iter_get_channel(i);
414 	group = spdk_io_channel_get_ctx(ch);
415 
416 	switch (ctx->requested_state) {
417 	case SPDK_NVMF_SUBSYSTEM_INACTIVE:
418 		rc = spdk_nvmf_poll_group_remove_subsystem(group, ctx->subsystem);
419 		break;
420 	case SPDK_NVMF_SUBSYSTEM_ACTIVE:
421 		if (ctx->subsystem->state == SPDK_NVMF_SUBSYSTEM_ACTIVATING) {
422 			rc = spdk_nvmf_poll_group_add_subsystem(group, ctx->subsystem);
423 		} else if (ctx->subsystem->state == SPDK_NVMF_SUBSYSTEM_RESUMING) {
424 			rc = spdk_nvmf_poll_group_resume_subsystem(group, ctx->subsystem);
425 		}
426 		break;
427 	case SPDK_NVMF_SUBSYSTEM_PAUSED:
428 		rc = spdk_nvmf_poll_group_pause_subsystem(group, ctx->subsystem);
429 		break;
430 	default:
431 		assert(false);
432 		break;
433 	}
434 
435 	spdk_for_each_channel_continue(i, rc);
436 }
437 
438 static int
439 spdk_nvmf_subsystem_state_change(struct spdk_nvmf_subsystem *subsystem,
440 				 enum spdk_nvmf_subsystem_state requested_state,
441 				 spdk_nvmf_subsystem_state_change_done cb_fn,
442 				 void *cb_arg)
443 {
444 	struct subsystem_state_change_ctx *ctx;
445 	enum spdk_nvmf_subsystem_state intermediate_state;
446 	int rc;
447 
448 	switch (requested_state) {
449 	case SPDK_NVMF_SUBSYSTEM_INACTIVE:
450 		intermediate_state = SPDK_NVMF_SUBSYSTEM_DEACTIVATING;
451 		break;
452 	case SPDK_NVMF_SUBSYSTEM_ACTIVE:
453 		if (subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED) {
454 			intermediate_state = SPDK_NVMF_SUBSYSTEM_RESUMING;
455 		} else {
456 			intermediate_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING;
457 		}
458 		break;
459 	case SPDK_NVMF_SUBSYSTEM_PAUSED:
460 		intermediate_state = SPDK_NVMF_SUBSYSTEM_PAUSING;
461 		break;
462 	default:
463 		assert(false);
464 		return -EINVAL;
465 	}
466 
467 	ctx = calloc(1, sizeof(*ctx));
468 	if (!ctx) {
469 		return -ENOMEM;
470 	}
471 
472 	rc = spdk_nvmf_subsystem_set_state(subsystem, intermediate_state);
473 	if (rc) {
474 		free(ctx);
475 		return rc;
476 	}
477 
478 	ctx->subsystem = subsystem;
479 	ctx->requested_state = requested_state;
480 	ctx->cb_fn = cb_fn;
481 	ctx->cb_arg = cb_arg;
482 
483 	spdk_for_each_channel(subsystem->tgt,
484 			      subsystem_state_change_on_pg,
485 			      ctx,
486 			      subsystem_state_change_done);
487 
488 	return 0;
489 }
490 
491 int
492 spdk_nvmf_subsystem_start(struct spdk_nvmf_subsystem *subsystem,
493 			  spdk_nvmf_subsystem_state_change_done cb_fn,
494 			  void *cb_arg)
495 {
496 	return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_ACTIVE, cb_fn, cb_arg);
497 }
498 
499 int
500 spdk_nvmf_subsystem_stop(struct spdk_nvmf_subsystem *subsystem,
501 			 spdk_nvmf_subsystem_state_change_done cb_fn,
502 			 void *cb_arg)
503 {
504 	return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_INACTIVE, cb_fn, cb_arg);
505 }
506 
507 int
508 spdk_nvmf_subsystem_pause(struct spdk_nvmf_subsystem *subsystem,
509 			  spdk_nvmf_subsystem_state_change_done cb_fn,
510 			  void *cb_arg)
511 {
512 	return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_PAUSED, cb_fn, cb_arg);
513 }
514 
515 int
516 spdk_nvmf_subsystem_resume(struct spdk_nvmf_subsystem *subsystem,
517 			   spdk_nvmf_subsystem_state_change_done cb_fn,
518 			   void *cb_arg)
519 {
520 	return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_ACTIVE, cb_fn, cb_arg);
521 }
522 
523 struct spdk_nvmf_subsystem *
524 spdk_nvmf_subsystem_get_first(struct spdk_nvmf_tgt *tgt)
525 {
526 	struct spdk_nvmf_subsystem	*subsystem;
527 	uint32_t sid;
528 
529 	for (sid = 0; sid < tgt->max_sid; sid++) {
530 		subsystem = tgt->subsystems[sid];
531 		if (subsystem) {
532 			return subsystem;
533 		}
534 	}
535 
536 	return NULL;
537 }
538 
539 struct spdk_nvmf_subsystem *
540 spdk_nvmf_subsystem_get_next(struct spdk_nvmf_subsystem *subsystem)
541 {
542 	uint32_t sid;
543 	struct spdk_nvmf_tgt *tgt;
544 
545 	if (!subsystem) {
546 		return NULL;
547 	}
548 
549 	tgt = subsystem->tgt;
550 
551 	for (sid = subsystem->id + 1; sid < tgt->max_sid; sid++) {
552 		subsystem = tgt->subsystems[sid];
553 		if (subsystem) {
554 			return subsystem;
555 		}
556 	}
557 
558 	return NULL;
559 }
560 
561 int
562 spdk_nvmf_subsystem_add_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn)
563 {
564 	struct spdk_nvmf_host *host;
565 
566 	if (!spdk_nvmf_valid_nqn(hostnqn)) {
567 		return -EINVAL;
568 	}
569 
570 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
571 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
572 		return -EAGAIN;
573 	}
574 
575 	host = calloc(1, sizeof(*host));
576 	if (!host) {
577 		return -ENOMEM;
578 	}
579 	host->nqn = strdup(hostnqn);
580 	if (!host->nqn) {
581 		free(host);
582 		return -ENOMEM;
583 	}
584 
585 	TAILQ_INSERT_HEAD(&subsystem->hosts, host, link);
586 	subsystem->tgt->discovery_genctr++;
587 
588 	return 0;
589 }
590 
591 int
592 spdk_nvmf_subsystem_set_allow_any_host(struct spdk_nvmf_subsystem *subsystem, bool allow_any_host)
593 {
594 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
595 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
596 		return -EAGAIN;
597 	}
598 
599 	subsystem->allow_any_host = allow_any_host;
600 
601 	return 0;
602 }
603 
604 bool
605 spdk_nvmf_subsystem_get_allow_any_host(const struct spdk_nvmf_subsystem *subsystem)
606 {
607 	return subsystem->allow_any_host;
608 }
609 
610 bool
611 spdk_nvmf_subsystem_host_allowed(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn)
612 {
613 	struct spdk_nvmf_host *host;
614 
615 	if (!hostnqn) {
616 		return false;
617 	}
618 
619 	if (subsystem->allow_any_host) {
620 		return true;
621 	}
622 
623 	TAILQ_FOREACH(host, &subsystem->hosts, link) {
624 		if (strcmp(hostnqn, host->nqn) == 0) {
625 			return true;
626 		}
627 	}
628 
629 	return false;
630 }
631 
632 struct spdk_nvmf_host *
633 spdk_nvmf_subsystem_get_first_host(struct spdk_nvmf_subsystem *subsystem)
634 {
635 	return TAILQ_FIRST(&subsystem->hosts);
636 }
637 
638 
639 struct spdk_nvmf_host *
640 spdk_nvmf_subsystem_get_next_host(struct spdk_nvmf_subsystem *subsystem,
641 				  struct spdk_nvmf_host *prev_host)
642 {
643 	return TAILQ_NEXT(prev_host, link);
644 }
645 
646 const char *
647 spdk_nvmf_host_get_nqn(struct spdk_nvmf_host *host)
648 {
649 	return host->nqn;
650 }
651 
652 int
653 spdk_nvmf_subsystem_add_listener(struct spdk_nvmf_subsystem *subsystem,
654 				 struct spdk_nvme_transport_id *trid)
655 {
656 	struct spdk_nvmf_transport *transport;
657 	struct spdk_nvmf_listener *listener;
658 
659 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
660 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
661 		return -EAGAIN;
662 	}
663 
664 	transport = spdk_nvmf_tgt_get_transport(subsystem->tgt, trid->trtype);
665 	if (transport == NULL) {
666 		SPDK_ERRLOG("Unknown transport type %d\n", trid->trtype);
667 		return -EINVAL;
668 	}
669 
670 	listener = calloc(1, sizeof(*listener));
671 	if (!listener) {
672 		return -ENOMEM;
673 	}
674 
675 	listener->trid = *trid;
676 	listener->transport = transport;
677 
678 	TAILQ_INSERT_HEAD(&subsystem->listeners, listener, link);
679 
680 	return 0;
681 }
682 
683 /*
684  * TODO: this is the whitelist and will be called during connection setup
685  */
686 bool
687 spdk_nvmf_subsystem_listener_allowed(struct spdk_nvmf_subsystem *subsystem,
688 				     struct spdk_nvme_transport_id *trid)
689 {
690 	struct spdk_nvmf_listener *listener;
691 
692 	if (TAILQ_EMPTY(&subsystem->listeners)) {
693 		return true;
694 	}
695 
696 	TAILQ_FOREACH(listener, &subsystem->listeners, link) {
697 		if (spdk_nvme_transport_id_compare(&listener->trid, trid) == 0) {
698 			return true;
699 		}
700 	}
701 
702 	return false;
703 }
704 
705 struct spdk_nvmf_listener *
706 spdk_nvmf_subsystem_get_first_listener(struct spdk_nvmf_subsystem *subsystem)
707 {
708 	return TAILQ_FIRST(&subsystem->listeners);
709 }
710 
711 struct spdk_nvmf_listener *
712 spdk_nvmf_subsystem_get_next_listener(struct spdk_nvmf_subsystem *subsystem,
713 				      struct spdk_nvmf_listener *prev_listener)
714 {
715 	return TAILQ_NEXT(prev_listener, link);
716 }
717 
718 
719 const struct spdk_nvme_transport_id *
720 spdk_nvmf_listener_get_trid(struct spdk_nvmf_listener *listener)
721 {
722 	return &listener->trid;
723 }
724 
725 int
726 spdk_nvmf_subsystem_remove_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid)
727 {
728 	struct spdk_nvmf_ns *ns;
729 
730 	assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED ||
731 	       subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE);
732 
733 	if (nsid == 0 || nsid > subsystem->max_nsid) {
734 		return -1;
735 	}
736 
737 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
738 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
739 		return -1;
740 	}
741 
742 	ns = &subsystem->ns[nsid - 1];
743 	if (ns->allocated == false) {
744 		return -1;
745 	}
746 
747 	spdk_bdev_close(ns->desc);
748 	ns->allocated = false;
749 	subsystem->num_allocated_nsid--;
750 
751 	return 0;
752 }
753 
754 static void
755 _spdk_nvmf_ns_hot_remove(struct spdk_nvmf_subsystem *subsystem,
756 			 void *cb_arg, int status)
757 {
758 	struct spdk_nvmf_ns *ns = cb_arg;
759 
760 	spdk_nvmf_subsystem_remove_ns(ns->subsystem, ns->id);
761 
762 	spdk_nvmf_subsystem_resume(subsystem, NULL, NULL);
763 }
764 
765 static void
766 spdk_nvmf_ns_hot_remove(void *remove_ctx)
767 {
768 	struct spdk_nvmf_ns *ns = remove_ctx;
769 	int rc;
770 
771 	rc = spdk_nvmf_subsystem_pause(ns->subsystem, _spdk_nvmf_ns_hot_remove, ns);
772 	if (rc) {
773 		SPDK_ERRLOG("Unable to pause subsystem to process namespace removal!\n");
774 	}
775 }
776 
777 uint32_t
778 spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bdev *bdev,
779 			   uint32_t nsid)
780 {
781 	struct spdk_nvmf_ns *ns;
782 	uint32_t i;
783 	int rc;
784 
785 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
786 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
787 		return 0;
788 	}
789 
790 	if (nsid == SPDK_NVME_GLOBAL_NS_TAG) {
791 		SPDK_ERRLOG("Invalid NSID %" PRIu32 "\n", nsid);
792 		return 0;
793 	}
794 
795 	if (nsid > subsystem->max_nsid ||
796 	    (nsid == 0 && subsystem->num_allocated_nsid == subsystem->max_nsid)) {
797 		struct spdk_nvmf_ns *new_ns_array;
798 		uint32_t new_max_nsid;
799 
800 		if (nsid > subsystem->max_nsid) {
801 			new_max_nsid = nsid;
802 		} else {
803 			new_max_nsid = subsystem->max_nsid + 1;
804 		}
805 
806 		if (!TAILQ_EMPTY(&subsystem->ctrlrs)) {
807 			SPDK_ERRLOG("Can't extend NSID range with active connections\n");
808 			return 0;
809 		}
810 
811 		new_ns_array = realloc(subsystem->ns, sizeof(struct spdk_nvmf_ns) * new_max_nsid);
812 		if (new_ns_array == NULL) {
813 			SPDK_ERRLOG("Memory allocation error while resizing namespace array.\n");
814 			return 0;
815 		}
816 
817 		memset(new_ns_array + subsystem->max_nsid, 0,
818 		       sizeof(struct spdk_nvmf_ns) * (new_max_nsid - subsystem->max_nsid));
819 		subsystem->ns = new_ns_array;
820 		subsystem->max_nsid = new_max_nsid;
821 	}
822 
823 	if (nsid == 0) {
824 		/* NSID not specified - find a free index */
825 		for (i = 0; i < subsystem->max_nsid; i++) {
826 			if (_spdk_nvmf_subsystem_get_ns(subsystem, i + 1) == NULL) {
827 				nsid = i + 1;
828 				break;
829 			}
830 		}
831 		if (nsid == 0) {
832 			SPDK_ERRLOG("All available NSIDs in use\n");
833 			return 0;
834 		}
835 	} else {
836 		/* Specific NSID requested */
837 		if (_spdk_nvmf_subsystem_get_ns(subsystem, nsid)) {
838 			SPDK_ERRLOG("Requested NSID %" PRIu32 " already in use\n", nsid);
839 			return 0;
840 		}
841 	}
842 
843 	ns = &subsystem->ns[nsid - 1];
844 	memset(ns, 0, sizeof(*ns));
845 	ns->bdev = bdev;
846 	ns->id = nsid;
847 	ns->subsystem = subsystem;
848 	rc = spdk_bdev_open(bdev, true, spdk_nvmf_ns_hot_remove, ns, &ns->desc);
849 	if (rc != 0) {
850 		SPDK_ERRLOG("Subsystem %s: bdev %s cannot be opened, error=%d\n",
851 			    subsystem->subnqn, spdk_bdev_get_name(bdev), rc);
852 		return 0;
853 	}
854 	ns->allocated = true;
855 
856 	SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Subsystem %s: bdev %s assigned nsid %" PRIu32 "\n",
857 		      spdk_nvmf_subsystem_get_nqn(subsystem),
858 		      spdk_bdev_get_name(bdev),
859 		      nsid);
860 
861 	subsystem->max_nsid = spdk_max(subsystem->max_nsid, nsid);
862 	subsystem->num_allocated_nsid++;
863 
864 	return nsid;
865 }
866 
867 static uint32_t
868 spdk_nvmf_subsystem_get_next_allocated_nsid(struct spdk_nvmf_subsystem *subsystem,
869 		uint32_t prev_nsid)
870 {
871 	uint32_t nsid;
872 
873 	if (prev_nsid >= subsystem->max_nsid) {
874 		return 0;
875 	}
876 
877 	for (nsid = prev_nsid + 1; nsid <= subsystem->max_nsid; nsid++) {
878 		if (subsystem->ns[nsid - 1].allocated) {
879 			return nsid;
880 		}
881 	}
882 
883 	return 0;
884 }
885 
886 struct spdk_nvmf_ns *
887 spdk_nvmf_subsystem_get_first_ns(struct spdk_nvmf_subsystem *subsystem)
888 {
889 	uint32_t first_nsid;
890 
891 	first_nsid = spdk_nvmf_subsystem_get_next_allocated_nsid(subsystem, 0);
892 	return _spdk_nvmf_subsystem_get_ns(subsystem, first_nsid);
893 }
894 
895 struct spdk_nvmf_ns *
896 spdk_nvmf_subsystem_get_next_ns(struct spdk_nvmf_subsystem *subsystem,
897 				struct spdk_nvmf_ns *prev_ns)
898 {
899 	uint32_t next_nsid;
900 
901 	next_nsid = spdk_nvmf_subsystem_get_next_allocated_nsid(subsystem, prev_ns->id);
902 	return _spdk_nvmf_subsystem_get_ns(subsystem, next_nsid);
903 }
904 
905 struct spdk_nvmf_ns *
906 spdk_nvmf_subsystem_get_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid)
907 {
908 	return _spdk_nvmf_subsystem_get_ns(subsystem, nsid);
909 }
910 
911 uint32_t
912 spdk_nvmf_ns_get_id(const struct spdk_nvmf_ns *ns)
913 {
914 	return ns->id;
915 }
916 
917 struct spdk_bdev *
918 spdk_nvmf_ns_get_bdev(struct spdk_nvmf_ns *ns)
919 {
920 	return ns->bdev;
921 }
922 
923 const char *
924 spdk_nvmf_subsystem_get_sn(const struct spdk_nvmf_subsystem *subsystem)
925 {
926 	return subsystem->sn;
927 }
928 
929 int
930 spdk_nvmf_subsystem_set_sn(struct spdk_nvmf_subsystem *subsystem, const char *sn)
931 {
932 	size_t len, max_len;
933 
934 	max_len = sizeof(subsystem->sn) - 1;
935 	len = strlen(sn);
936 	if (len > max_len) {
937 		SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Invalid sn \"%s\": length %zu > max %zu\n",
938 			      sn, len, max_len);
939 		return -1;
940 	}
941 
942 	snprintf(subsystem->sn, sizeof(subsystem->sn), "%s", sn);
943 
944 	return 0;
945 }
946 
947 const char *
948 spdk_nvmf_subsystem_get_nqn(struct spdk_nvmf_subsystem *subsystem)
949 {
950 	return subsystem->subnqn;
951 }
952 
953 /* Workaround for astyle formatting bug */
954 typedef enum spdk_nvmf_subtype nvmf_subtype_t;
955 
956 nvmf_subtype_t
957 spdk_nvmf_subsystem_get_type(struct spdk_nvmf_subsystem *subsystem)
958 {
959 	return subsystem->subtype;
960 }
961 
962 static uint16_t
963 spdk_nvmf_subsystem_gen_cntlid(struct spdk_nvmf_subsystem *subsystem)
964 {
965 	int count;
966 
967 	/*
968 	 * In the worst case, we might have to try all CNTLID values between 1 and 0xFFF0 - 1
969 	 * before we find one that is unused (or find that all values are in use).
970 	 */
971 	for (count = 0; count < 0xFFF0 - 1; count++) {
972 		subsystem->next_cntlid++;
973 		if (subsystem->next_cntlid >= 0xFFF0) {
974 			/* The spec reserves cntlid values in the range FFF0h to FFFFh. */
975 			subsystem->next_cntlid = 1;
976 		}
977 
978 		/* Check if a controller with this cntlid currently exists. */
979 		if (spdk_nvmf_subsystem_get_ctrlr(subsystem, subsystem->next_cntlid) == NULL) {
980 			/* Found unused cntlid */
981 			return subsystem->next_cntlid;
982 		}
983 	}
984 
985 	/* All valid cntlid values are in use. */
986 	return 0xFFFF;
987 }
988 
989 int
990 spdk_nvmf_subsystem_add_ctrlr(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *ctrlr)
991 {
992 	ctrlr->cntlid = spdk_nvmf_subsystem_gen_cntlid(subsystem);
993 	if (ctrlr->cntlid == 0xFFFF) {
994 		/* Unable to get a cntlid */
995 		SPDK_ERRLOG("Reached max simultaneous ctrlrs\n");
996 		return -EBUSY;
997 	}
998 
999 	TAILQ_INSERT_TAIL(&subsystem->ctrlrs, ctrlr, link);
1000 
1001 	return 0;
1002 }
1003 
1004 void
1005 spdk_nvmf_subsystem_remove_ctrlr(struct spdk_nvmf_subsystem *subsystem,
1006 				 struct spdk_nvmf_ctrlr *ctrlr)
1007 {
1008 	assert(subsystem == ctrlr->subsys);
1009 	TAILQ_REMOVE(&subsystem->ctrlrs, ctrlr, link);
1010 }
1011 
1012 struct spdk_nvmf_ctrlr *
1013 spdk_nvmf_subsystem_get_ctrlr(struct spdk_nvmf_subsystem *subsystem, uint16_t cntlid)
1014 {
1015 	struct spdk_nvmf_ctrlr *ctrlr;
1016 
1017 	TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) {
1018 		if (ctrlr->cntlid == cntlid) {
1019 			return ctrlr;
1020 		}
1021 	}
1022 
1023 	return NULL;
1024 }
1025