xref: /spdk/lib/nvmf/subsystem.c (revision b066126b0b9afdcae328cbb989244620398cc64d)
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_internal/bdev.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_sid; sid++) {
257 		if (tgt->subsystems[sid] == NULL) {
258 			break;
259 		}
260 	}
261 	if (sid == tgt->max_sid) {
262 		struct spdk_nvmf_subsystem **subsys_array;
263 		/* No free slots. Add more. */
264 		tgt->max_sid++;
265 		subsys_array = realloc(tgt->subsystems, tgt->max_sid * sizeof(struct spdk_nvmf_subsystem *));
266 		if (!subsys_array) {
267 			tgt->max_sid--;
268 			return NULL;
269 		}
270 		tgt->subsystems = subsys_array;
271 	}
272 
273 	subsystem = calloc(1, sizeof(struct spdk_nvmf_subsystem));
274 	if (subsystem == NULL) {
275 		return NULL;
276 	}
277 
278 	subsystem->thread = spdk_get_thread();
279 	subsystem->state = SPDK_NVMF_SUBSYSTEM_INACTIVE;
280 	subsystem->tgt = tgt;
281 	subsystem->id = sid;
282 	subsystem->subtype = type;
283 	subsystem->max_nsid = num_ns;
284 	/*
285 	 *  Initially max_nsid and max_allowed_nsid will be same. If max_allowed_nsid is zero nsid range can grow dynamically
286 	 *  but if it is more than 1 nsid range cannot be extended beyond max_allowed_nsid
287 	 */
288 	subsystem->max_allowed_nsid = num_ns;
289 	subsystem->num_allocated_nsid = 0;
290 	subsystem->next_cntlid = 0;
291 	snprintf(subsystem->subnqn, sizeof(subsystem->subnqn), "%s", nqn);
292 	TAILQ_INIT(&subsystem->listeners);
293 	TAILQ_INIT(&subsystem->hosts);
294 	TAILQ_INIT(&subsystem->ctrlrs);
295 
296 	if (num_ns != 0) {
297 		subsystem->ns = calloc(num_ns, sizeof(struct spdk_nvmf_ns *));
298 		if (subsystem->ns == NULL) {
299 			SPDK_ERRLOG("Namespace memory allocation failed\n");
300 			free(subsystem);
301 			return NULL;
302 		}
303 	}
304 
305 	tgt->subsystems[sid] = subsystem;
306 	tgt->discovery_genctr++;
307 
308 	return subsystem;
309 }
310 
311 static void
312 _spdk_nvmf_subsystem_remove_host(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_host *host)
313 {
314 	TAILQ_REMOVE(&subsystem->hosts, host, link);
315 	free(host->nqn);
316 	free(host);
317 }
318 
319 void
320 spdk_nvmf_subsystem_destroy(struct spdk_nvmf_subsystem *subsystem)
321 {
322 	struct spdk_nvmf_listener	*listener, *listener_tmp;
323 	struct spdk_nvmf_host		*host, *host_tmp;
324 	struct spdk_nvmf_ctrlr		*ctrlr, *ctrlr_tmp;
325 	struct spdk_nvmf_ns		*ns;
326 
327 	if (!subsystem) {
328 		return;
329 	}
330 
331 	assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE);
332 
333 	SPDK_DEBUGLOG(SPDK_LOG_NVMF, "subsystem is %p\n", subsystem);
334 
335 	TAILQ_FOREACH_SAFE(listener, &subsystem->listeners, link, listener_tmp) {
336 		TAILQ_REMOVE(&subsystem->listeners, listener, link);
337 		free(listener);
338 	}
339 
340 	TAILQ_FOREACH_SAFE(host, &subsystem->hosts, link, host_tmp) {
341 		_spdk_nvmf_subsystem_remove_host(subsystem, host);
342 	}
343 
344 	TAILQ_FOREACH_SAFE(ctrlr, &subsystem->ctrlrs, link, ctrlr_tmp) {
345 		spdk_nvmf_ctrlr_destruct(ctrlr);
346 	}
347 
348 	ns = spdk_nvmf_subsystem_get_first_ns(subsystem);
349 	while (ns != NULL) {
350 		struct spdk_nvmf_ns *next_ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns);
351 
352 		spdk_nvmf_subsystem_remove_ns(subsystem, ns->opts.nsid);
353 		ns = next_ns;
354 	}
355 
356 	free(subsystem->ns);
357 
358 	subsystem->tgt->subsystems[subsystem->id] = NULL;
359 	subsystem->tgt->discovery_genctr++;
360 
361 	free(subsystem);
362 }
363 
364 static int
365 spdk_nvmf_subsystem_set_state(struct spdk_nvmf_subsystem *subsystem,
366 			      enum spdk_nvmf_subsystem_state state)
367 {
368 	enum spdk_nvmf_subsystem_state actual_old_state, expected_old_state;
369 
370 	switch (state) {
371 	case SPDK_NVMF_SUBSYSTEM_INACTIVE:
372 		expected_old_state = SPDK_NVMF_SUBSYSTEM_DEACTIVATING;
373 		break;
374 	case SPDK_NVMF_SUBSYSTEM_ACTIVATING:
375 		expected_old_state = SPDK_NVMF_SUBSYSTEM_INACTIVE;
376 		break;
377 	case SPDK_NVMF_SUBSYSTEM_ACTIVE:
378 		expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING;
379 		break;
380 	case SPDK_NVMF_SUBSYSTEM_PAUSING:
381 		expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
382 		break;
383 	case SPDK_NVMF_SUBSYSTEM_PAUSED:
384 		expected_old_state = SPDK_NVMF_SUBSYSTEM_PAUSING;
385 		break;
386 	case SPDK_NVMF_SUBSYSTEM_RESUMING:
387 		expected_old_state = SPDK_NVMF_SUBSYSTEM_PAUSED;
388 		break;
389 	case SPDK_NVMF_SUBSYSTEM_DEACTIVATING:
390 		expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
391 		break;
392 	default:
393 		assert(false);
394 		return -1;
395 	}
396 
397 	actual_old_state = __sync_val_compare_and_swap(&subsystem->state, expected_old_state, state);
398 	if (actual_old_state != expected_old_state) {
399 		if (actual_old_state == SPDK_NVMF_SUBSYSTEM_RESUMING &&
400 		    state == SPDK_NVMF_SUBSYSTEM_ACTIVE) {
401 			expected_old_state = SPDK_NVMF_SUBSYSTEM_RESUMING;
402 		}
403 		actual_old_state = __sync_val_compare_and_swap(&subsystem->state, expected_old_state, state);
404 	}
405 	assert(actual_old_state == expected_old_state);
406 	return actual_old_state - expected_old_state;
407 }
408 
409 struct subsystem_state_change_ctx {
410 	struct spdk_nvmf_subsystem *subsystem;
411 
412 	enum spdk_nvmf_subsystem_state requested_state;
413 
414 	spdk_nvmf_subsystem_state_change_done cb_fn;
415 	void *cb_arg;
416 };
417 
418 static void
419 subsystem_state_change_done(struct spdk_io_channel_iter *i, int status)
420 {
421 	struct subsystem_state_change_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
422 
423 	if (status == 0) {
424 		status = spdk_nvmf_subsystem_set_state(ctx->subsystem, ctx->requested_state);
425 		if (status) {
426 			status = -1;
427 		}
428 	}
429 
430 	if (ctx->cb_fn) {
431 		ctx->cb_fn(ctx->subsystem, ctx->cb_arg, status);
432 	}
433 	free(ctx);
434 }
435 
436 static void
437 subsystem_state_change_on_pg(struct spdk_io_channel_iter *i)
438 {
439 	struct subsystem_state_change_ctx *ctx;
440 	struct spdk_io_channel *ch;
441 	struct spdk_nvmf_poll_group *group;
442 	int rc = -1;
443 
444 	ctx = spdk_io_channel_iter_get_ctx(i);
445 	ch = spdk_io_channel_iter_get_channel(i);
446 	group = spdk_io_channel_get_ctx(ch);
447 
448 	switch (ctx->requested_state) {
449 	case SPDK_NVMF_SUBSYSTEM_INACTIVE:
450 		rc = spdk_nvmf_poll_group_remove_subsystem(group, ctx->subsystem);
451 		break;
452 	case SPDK_NVMF_SUBSYSTEM_ACTIVE:
453 		if (ctx->subsystem->state == SPDK_NVMF_SUBSYSTEM_ACTIVATING) {
454 			rc = spdk_nvmf_poll_group_add_subsystem(group, ctx->subsystem);
455 		} else if (ctx->subsystem->state == SPDK_NVMF_SUBSYSTEM_RESUMING) {
456 			rc = spdk_nvmf_poll_group_resume_subsystem(group, ctx->subsystem);
457 		}
458 		break;
459 	case SPDK_NVMF_SUBSYSTEM_PAUSED:
460 		rc = spdk_nvmf_poll_group_pause_subsystem(group, ctx->subsystem);
461 		break;
462 	default:
463 		assert(false);
464 		break;
465 	}
466 
467 	spdk_for_each_channel_continue(i, rc);
468 }
469 
470 static int
471 spdk_nvmf_subsystem_state_change(struct spdk_nvmf_subsystem *subsystem,
472 				 enum spdk_nvmf_subsystem_state requested_state,
473 				 spdk_nvmf_subsystem_state_change_done cb_fn,
474 				 void *cb_arg)
475 {
476 	struct subsystem_state_change_ctx *ctx;
477 	enum spdk_nvmf_subsystem_state intermediate_state;
478 	int rc;
479 
480 	switch (requested_state) {
481 	case SPDK_NVMF_SUBSYSTEM_INACTIVE:
482 		intermediate_state = SPDK_NVMF_SUBSYSTEM_DEACTIVATING;
483 		break;
484 	case SPDK_NVMF_SUBSYSTEM_ACTIVE:
485 		if (subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED) {
486 			intermediate_state = SPDK_NVMF_SUBSYSTEM_RESUMING;
487 		} else {
488 			intermediate_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING;
489 		}
490 		break;
491 	case SPDK_NVMF_SUBSYSTEM_PAUSED:
492 		intermediate_state = SPDK_NVMF_SUBSYSTEM_PAUSING;
493 		break;
494 	default:
495 		assert(false);
496 		return -EINVAL;
497 	}
498 
499 	ctx = calloc(1, sizeof(*ctx));
500 	if (!ctx) {
501 		return -ENOMEM;
502 	}
503 
504 	rc = spdk_nvmf_subsystem_set_state(subsystem, intermediate_state);
505 	if (rc) {
506 		free(ctx);
507 		return rc;
508 	}
509 
510 	ctx->subsystem = subsystem;
511 	ctx->requested_state = requested_state;
512 	ctx->cb_fn = cb_fn;
513 	ctx->cb_arg = cb_arg;
514 
515 	spdk_for_each_channel(subsystem->tgt,
516 			      subsystem_state_change_on_pg,
517 			      ctx,
518 			      subsystem_state_change_done);
519 
520 	return 0;
521 }
522 
523 int
524 spdk_nvmf_subsystem_start(struct spdk_nvmf_subsystem *subsystem,
525 			  spdk_nvmf_subsystem_state_change_done cb_fn,
526 			  void *cb_arg)
527 {
528 	return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_ACTIVE, cb_fn, cb_arg);
529 }
530 
531 int
532 spdk_nvmf_subsystem_stop(struct spdk_nvmf_subsystem *subsystem,
533 			 spdk_nvmf_subsystem_state_change_done cb_fn,
534 			 void *cb_arg)
535 {
536 	return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_INACTIVE, cb_fn, cb_arg);
537 }
538 
539 int
540 spdk_nvmf_subsystem_pause(struct spdk_nvmf_subsystem *subsystem,
541 			  spdk_nvmf_subsystem_state_change_done cb_fn,
542 			  void *cb_arg)
543 {
544 	return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_PAUSED, cb_fn, cb_arg);
545 }
546 
547 int
548 spdk_nvmf_subsystem_resume(struct spdk_nvmf_subsystem *subsystem,
549 			   spdk_nvmf_subsystem_state_change_done cb_fn,
550 			   void *cb_arg)
551 {
552 	return spdk_nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_ACTIVE, cb_fn, cb_arg);
553 }
554 
555 struct spdk_nvmf_subsystem *
556 spdk_nvmf_subsystem_get_first(struct spdk_nvmf_tgt *tgt)
557 {
558 	struct spdk_nvmf_subsystem	*subsystem;
559 	uint32_t sid;
560 
561 	for (sid = 0; sid < tgt->max_sid; sid++) {
562 		subsystem = tgt->subsystems[sid];
563 		if (subsystem) {
564 			return subsystem;
565 		}
566 	}
567 
568 	return NULL;
569 }
570 
571 struct spdk_nvmf_subsystem *
572 spdk_nvmf_subsystem_get_next(struct spdk_nvmf_subsystem *subsystem)
573 {
574 	uint32_t sid;
575 	struct spdk_nvmf_tgt *tgt;
576 
577 	if (!subsystem) {
578 		return NULL;
579 	}
580 
581 	tgt = subsystem->tgt;
582 
583 	for (sid = subsystem->id + 1; sid < tgt->max_sid; sid++) {
584 		subsystem = tgt->subsystems[sid];
585 		if (subsystem) {
586 			return subsystem;
587 		}
588 	}
589 
590 	return NULL;
591 }
592 
593 static struct spdk_nvmf_host *
594 _spdk_nvmf_subsystem_find_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn)
595 {
596 	struct spdk_nvmf_host *host = NULL;
597 
598 	TAILQ_FOREACH(host, &subsystem->hosts, link) {
599 		if (strcmp(hostnqn, host->nqn) == 0) {
600 			return host;
601 		}
602 	}
603 
604 	return NULL;
605 }
606 
607 int
608 spdk_nvmf_subsystem_add_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn)
609 {
610 	struct spdk_nvmf_host *host;
611 
612 	if (!spdk_nvmf_valid_nqn(hostnqn)) {
613 		return -EINVAL;
614 	}
615 
616 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
617 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
618 		return -EAGAIN;
619 	}
620 
621 	if (_spdk_nvmf_subsystem_find_host(subsystem, hostnqn)) {
622 		/* This subsystem already allows the specified host. */
623 		return 0;
624 	}
625 
626 	host = calloc(1, sizeof(*host));
627 	if (!host) {
628 		return -ENOMEM;
629 	}
630 	host->nqn = strdup(hostnqn);
631 	if (!host->nqn) {
632 		free(host);
633 		return -ENOMEM;
634 	}
635 
636 	TAILQ_INSERT_HEAD(&subsystem->hosts, host, link);
637 	subsystem->tgt->discovery_genctr++;
638 
639 	return 0;
640 }
641 
642 int
643 spdk_nvmf_subsystem_remove_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn)
644 {
645 	struct spdk_nvmf_host *host;
646 
647 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
648 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
649 		return -EAGAIN;
650 	}
651 
652 	host = _spdk_nvmf_subsystem_find_host(subsystem, hostnqn);
653 	if (host == NULL) {
654 		return -ENOENT;
655 	}
656 
657 	_spdk_nvmf_subsystem_remove_host(subsystem, host);
658 	return 0;
659 }
660 
661 int
662 spdk_nvmf_subsystem_set_allow_any_host(struct spdk_nvmf_subsystem *subsystem, bool allow_any_host)
663 {
664 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
665 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
666 		return -EAGAIN;
667 	}
668 
669 	subsystem->allow_any_host = allow_any_host;
670 
671 	return 0;
672 }
673 
674 bool
675 spdk_nvmf_subsystem_get_allow_any_host(const struct spdk_nvmf_subsystem *subsystem)
676 {
677 	return subsystem->allow_any_host;
678 }
679 
680 bool
681 spdk_nvmf_subsystem_host_allowed(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn)
682 {
683 	if (!hostnqn) {
684 		return false;
685 	}
686 
687 	if (subsystem->allow_any_host) {
688 		return true;
689 	}
690 
691 	return _spdk_nvmf_subsystem_find_host(subsystem, hostnqn) != NULL;
692 }
693 
694 struct spdk_nvmf_host *
695 spdk_nvmf_subsystem_get_first_host(struct spdk_nvmf_subsystem *subsystem)
696 {
697 	return TAILQ_FIRST(&subsystem->hosts);
698 }
699 
700 
701 struct spdk_nvmf_host *
702 spdk_nvmf_subsystem_get_next_host(struct spdk_nvmf_subsystem *subsystem,
703 				  struct spdk_nvmf_host *prev_host)
704 {
705 	return TAILQ_NEXT(prev_host, link);
706 }
707 
708 const char *
709 spdk_nvmf_host_get_nqn(struct spdk_nvmf_host *host)
710 {
711 	return host->nqn;
712 }
713 
714 static struct spdk_nvmf_listener *
715 _spdk_nvmf_subsystem_find_listener(struct spdk_nvmf_subsystem *subsystem,
716 				   const struct spdk_nvme_transport_id *trid)
717 {
718 	struct spdk_nvmf_listener *listener;
719 
720 	TAILQ_FOREACH(listener, &subsystem->listeners, link) {
721 		if (spdk_nvme_transport_id_compare(&listener->trid, trid) == 0) {
722 			return listener;
723 		}
724 	}
725 
726 	return NULL;
727 }
728 
729 int
730 spdk_nvmf_subsystem_add_listener(struct spdk_nvmf_subsystem *subsystem,
731 				 struct spdk_nvme_transport_id *trid)
732 {
733 	struct spdk_nvmf_transport *transport;
734 	struct spdk_nvmf_listener *listener;
735 
736 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
737 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
738 		return -EAGAIN;
739 	}
740 
741 	if (_spdk_nvmf_subsystem_find_listener(subsystem, trid)) {
742 		/* Listener already exists in this subsystem */
743 		return 0;
744 	}
745 
746 	transport = spdk_nvmf_tgt_get_transport(subsystem->tgt, trid->trtype);
747 	if (transport == NULL) {
748 		SPDK_ERRLOG("Unknown transport type %d\n", trid->trtype);
749 		return -EINVAL;
750 	}
751 
752 	listener = calloc(1, sizeof(*listener));
753 	if (!listener) {
754 		return -ENOMEM;
755 	}
756 
757 	listener->trid = *trid;
758 	listener->transport = transport;
759 
760 	TAILQ_INSERT_HEAD(&subsystem->listeners, listener, link);
761 
762 	return 0;
763 }
764 
765 int
766 spdk_nvmf_subsystem_remove_listener(struct spdk_nvmf_subsystem *subsystem,
767 				    const struct spdk_nvme_transport_id *trid)
768 {
769 	struct spdk_nvmf_listener *listener;
770 
771 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
772 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
773 		return -EAGAIN;
774 	}
775 
776 	listener = _spdk_nvmf_subsystem_find_listener(subsystem, trid);
777 	if (listener == NULL) {
778 		return -ENOENT;
779 	}
780 
781 	TAILQ_REMOVE(&subsystem->listeners, listener, link);
782 	free(listener);
783 
784 	return 0;
785 }
786 
787 /*
788  * TODO: this is the whitelist and will be called during connection setup
789  */
790 bool
791 spdk_nvmf_subsystem_listener_allowed(struct spdk_nvmf_subsystem *subsystem,
792 				     struct spdk_nvme_transport_id *trid)
793 {
794 	struct spdk_nvmf_listener *listener;
795 
796 	if (TAILQ_EMPTY(&subsystem->listeners)) {
797 		return true;
798 	}
799 
800 	TAILQ_FOREACH(listener, &subsystem->listeners, link) {
801 		if (spdk_nvme_transport_id_compare(&listener->trid, trid) == 0) {
802 			return true;
803 		}
804 	}
805 
806 	return false;
807 }
808 
809 struct spdk_nvmf_listener *
810 spdk_nvmf_subsystem_get_first_listener(struct spdk_nvmf_subsystem *subsystem)
811 {
812 	return TAILQ_FIRST(&subsystem->listeners);
813 }
814 
815 struct spdk_nvmf_listener *
816 spdk_nvmf_subsystem_get_next_listener(struct spdk_nvmf_subsystem *subsystem,
817 				      struct spdk_nvmf_listener *prev_listener)
818 {
819 	return TAILQ_NEXT(prev_listener, link);
820 }
821 
822 
823 const struct spdk_nvme_transport_id *
824 spdk_nvmf_listener_get_trid(struct spdk_nvmf_listener *listener)
825 {
826 	return &listener->trid;
827 }
828 
829 static void
830 spdk_nvmf_subsystem_ns_changed(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid)
831 {
832 	struct spdk_nvmf_ctrlr *ctrlr;
833 
834 	TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) {
835 		spdk_nvmf_ctrlr_ns_changed(ctrlr, nsid);
836 	}
837 }
838 
839 int
840 spdk_nvmf_subsystem_remove_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid)
841 {
842 	struct spdk_nvmf_ns *ns;
843 
844 	assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED ||
845 	       subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE);
846 
847 	if (nsid == 0 || nsid > subsystem->max_nsid) {
848 		return -1;
849 	}
850 
851 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
852 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
853 		return -1;
854 	}
855 
856 	ns = subsystem->ns[nsid - 1];
857 	if (!ns) {
858 		return -1;
859 	}
860 
861 	subsystem->ns[nsid - 1] = NULL;
862 
863 	spdk_bdev_close(ns->desc);
864 	free(ns);
865 	subsystem->num_allocated_nsid--;
866 
867 	spdk_nvmf_subsystem_ns_changed(subsystem, nsid);
868 
869 	return 0;
870 }
871 
872 static void
873 _spdk_nvmf_ns_hot_remove(struct spdk_nvmf_subsystem *subsystem,
874 			 void *cb_arg, int status)
875 {
876 	struct spdk_nvmf_ns *ns = cb_arg;
877 
878 	spdk_nvmf_subsystem_remove_ns(subsystem, ns->opts.nsid);
879 
880 	spdk_nvmf_subsystem_resume(subsystem, NULL, NULL);
881 }
882 
883 static void
884 spdk_nvmf_ns_hot_remove(void *remove_ctx)
885 {
886 	struct spdk_nvmf_ns *ns = remove_ctx;
887 	int rc;
888 
889 	rc = spdk_nvmf_subsystem_pause(ns->subsystem, _spdk_nvmf_ns_hot_remove, ns);
890 	if (rc) {
891 		SPDK_ERRLOG("Unable to pause subsystem to process namespace removal!\n");
892 	}
893 }
894 
895 void
896 spdk_nvmf_ns_opts_get_defaults(struct spdk_nvmf_ns_opts *opts, size_t opts_size)
897 {
898 	/* All current fields are set to 0 by default. */
899 	memset(opts, 0, opts_size);
900 }
901 
902 uint32_t
903 spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bdev *bdev,
904 			   const struct spdk_nvmf_ns_opts *user_opts, size_t opts_size)
905 {
906 	struct spdk_nvmf_ns_opts opts;
907 	struct spdk_nvmf_ns *ns;
908 	uint32_t i;
909 	int rc;
910 
911 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
912 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
913 		return 0;
914 	}
915 
916 	spdk_nvmf_ns_opts_get_defaults(&opts, sizeof(opts));
917 	if (user_opts) {
918 		memcpy(&opts, user_opts, spdk_min(sizeof(opts), opts_size));
919 	}
920 
921 	if (spdk_mem_all_zero(&opts.uuid, sizeof(opts.uuid))) {
922 		opts.uuid = *spdk_bdev_get_uuid(bdev);
923 	}
924 
925 	if (opts.nsid == SPDK_NVME_GLOBAL_NS_TAG) {
926 		SPDK_ERRLOG("Invalid NSID %" PRIu32 "\n", opts.nsid);
927 		return 0;
928 	}
929 
930 	if ((subsystem->max_allowed_nsid > 0) && (opts.nsid > subsystem->max_allowed_nsid)) {
931 		SPDK_ERRLOG("Can't extend NSID range above MaxNamespaces\n");
932 		return 0;
933 	}
934 
935 	if (opts.nsid > subsystem->max_nsid ||
936 	    (opts.nsid == 0 && subsystem->num_allocated_nsid == subsystem->max_nsid)) {
937 		struct spdk_nvmf_ns **new_ns_array;
938 		uint32_t new_max_nsid;
939 
940 		if (opts.nsid > subsystem->max_nsid) {
941 			new_max_nsid = opts.nsid;
942 		} else {
943 			new_max_nsid = subsystem->max_nsid + 1;
944 		}
945 
946 		new_ns_array = realloc(subsystem->ns, sizeof(struct spdk_nvmf_ns *) * new_max_nsid);
947 		if (new_ns_array == NULL) {
948 			SPDK_ERRLOG("Memory allocation error while resizing namespace array.\n");
949 			return 0;
950 		}
951 
952 		memset(new_ns_array + subsystem->max_nsid, 0,
953 		       sizeof(struct spdk_nvmf_ns *) * (new_max_nsid - subsystem->max_nsid));
954 		subsystem->ns = new_ns_array;
955 		subsystem->max_nsid = new_max_nsid;
956 	}
957 
958 	if (opts.nsid == 0) {
959 		/* NSID not specified - find a free index */
960 		for (i = 0; i < subsystem->max_nsid; i++) {
961 			if (_spdk_nvmf_subsystem_get_ns(subsystem, i + 1) == NULL) {
962 				opts.nsid = i + 1;
963 				break;
964 			}
965 		}
966 		if (opts.nsid == 0) {
967 			SPDK_ERRLOG("All available NSIDs in use\n");
968 			return 0;
969 		}
970 	} else {
971 		/* Specific NSID requested */
972 		if (_spdk_nvmf_subsystem_get_ns(subsystem, opts.nsid)) {
973 			SPDK_ERRLOG("Requested NSID %" PRIu32 " already in use\n", opts.nsid);
974 			return 0;
975 		}
976 	}
977 
978 	ns = calloc(1, sizeof(*ns));
979 	if (ns == NULL) {
980 		SPDK_ERRLOG("Namespace allocation failed\n");
981 		return 0;
982 	}
983 
984 	ns->bdev = bdev;
985 	ns->opts = opts;
986 	ns->subsystem = subsystem;
987 	rc = spdk_bdev_open(bdev, true, spdk_nvmf_ns_hot_remove, ns, &ns->desc);
988 	if (rc != 0) {
989 		SPDK_ERRLOG("Subsystem %s: bdev %s cannot be opened, error=%d\n",
990 			    subsystem->subnqn, spdk_bdev_get_name(bdev), rc);
991 		free(ns);
992 		return 0;
993 	}
994 	subsystem->ns[opts.nsid - 1] = ns;
995 
996 	SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Subsystem %s: bdev %s assigned nsid %" PRIu32 "\n",
997 		      spdk_nvmf_subsystem_get_nqn(subsystem),
998 		      spdk_bdev_get_name(bdev),
999 		      opts.nsid);
1000 
1001 	subsystem->max_nsid = spdk_max(subsystem->max_nsid, opts.nsid);
1002 	subsystem->num_allocated_nsid++;
1003 
1004 	spdk_nvmf_subsystem_ns_changed(subsystem, opts.nsid);
1005 
1006 	return opts.nsid;
1007 }
1008 
1009 static uint32_t
1010 spdk_nvmf_subsystem_get_next_allocated_nsid(struct spdk_nvmf_subsystem *subsystem,
1011 		uint32_t prev_nsid)
1012 {
1013 	uint32_t nsid;
1014 
1015 	if (prev_nsid >= subsystem->max_nsid) {
1016 		return 0;
1017 	}
1018 
1019 	for (nsid = prev_nsid + 1; nsid <= subsystem->max_nsid; nsid++) {
1020 		if (subsystem->ns[nsid - 1]) {
1021 			return nsid;
1022 		}
1023 	}
1024 
1025 	return 0;
1026 }
1027 
1028 struct spdk_nvmf_ns *
1029 spdk_nvmf_subsystem_get_first_ns(struct spdk_nvmf_subsystem *subsystem)
1030 {
1031 	uint32_t first_nsid;
1032 
1033 	first_nsid = spdk_nvmf_subsystem_get_next_allocated_nsid(subsystem, 0);
1034 	return _spdk_nvmf_subsystem_get_ns(subsystem, first_nsid);
1035 }
1036 
1037 struct spdk_nvmf_ns *
1038 spdk_nvmf_subsystem_get_next_ns(struct spdk_nvmf_subsystem *subsystem,
1039 				struct spdk_nvmf_ns *prev_ns)
1040 {
1041 	uint32_t next_nsid;
1042 
1043 	next_nsid = spdk_nvmf_subsystem_get_next_allocated_nsid(subsystem, prev_ns->opts.nsid);
1044 	return _spdk_nvmf_subsystem_get_ns(subsystem, next_nsid);
1045 }
1046 
1047 struct spdk_nvmf_ns *
1048 spdk_nvmf_subsystem_get_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid)
1049 {
1050 	return _spdk_nvmf_subsystem_get_ns(subsystem, nsid);
1051 }
1052 
1053 uint32_t
1054 spdk_nvmf_ns_get_id(const struct spdk_nvmf_ns *ns)
1055 {
1056 	return ns->opts.nsid;
1057 }
1058 
1059 struct spdk_bdev *
1060 spdk_nvmf_ns_get_bdev(struct spdk_nvmf_ns *ns)
1061 {
1062 	return ns->bdev;
1063 }
1064 
1065 void
1066 spdk_nvmf_ns_get_opts(const struct spdk_nvmf_ns *ns, struct spdk_nvmf_ns_opts *opts,
1067 		      size_t opts_size)
1068 {
1069 	memset(opts, 0, opts_size);
1070 	memcpy(opts, &ns->opts, spdk_min(sizeof(ns->opts), opts_size));
1071 }
1072 
1073 const char *
1074 spdk_nvmf_subsystem_get_sn(const struct spdk_nvmf_subsystem *subsystem)
1075 {
1076 	return subsystem->sn;
1077 }
1078 
1079 int
1080 spdk_nvmf_subsystem_set_sn(struct spdk_nvmf_subsystem *subsystem, const char *sn)
1081 {
1082 	size_t len, max_len;
1083 
1084 	max_len = sizeof(subsystem->sn) - 1;
1085 	len = strlen(sn);
1086 	if (len > max_len) {
1087 		SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Invalid sn \"%s\": length %zu > max %zu\n",
1088 			      sn, len, max_len);
1089 		return -1;
1090 	}
1091 
1092 	if (!spdk_nvmf_valid_ascii_string(sn, len)) {
1093 		SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Non-ASCII sn\n");
1094 		SPDK_TRACEDUMP(SPDK_LOG_NVMF, "sn", sn, len);
1095 		return -1;
1096 	}
1097 
1098 	snprintf(subsystem->sn, sizeof(subsystem->sn), "%s", sn);
1099 
1100 	return 0;
1101 }
1102 
1103 const char *
1104 spdk_nvmf_subsystem_get_nqn(struct spdk_nvmf_subsystem *subsystem)
1105 {
1106 	return subsystem->subnqn;
1107 }
1108 
1109 /* Workaround for astyle formatting bug */
1110 typedef enum spdk_nvmf_subtype nvmf_subtype_t;
1111 
1112 nvmf_subtype_t
1113 spdk_nvmf_subsystem_get_type(struct spdk_nvmf_subsystem *subsystem)
1114 {
1115 	return subsystem->subtype;
1116 }
1117 
1118 static uint16_t
1119 spdk_nvmf_subsystem_gen_cntlid(struct spdk_nvmf_subsystem *subsystem)
1120 {
1121 	int count;
1122 
1123 	/*
1124 	 * In the worst case, we might have to try all CNTLID values between 1 and 0xFFF0 - 1
1125 	 * before we find one that is unused (or find that all values are in use).
1126 	 */
1127 	for (count = 0; count < 0xFFF0 - 1; count++) {
1128 		subsystem->next_cntlid++;
1129 		if (subsystem->next_cntlid >= 0xFFF0) {
1130 			/* The spec reserves cntlid values in the range FFF0h to FFFFh. */
1131 			subsystem->next_cntlid = 1;
1132 		}
1133 
1134 		/* Check if a controller with this cntlid currently exists. */
1135 		if (spdk_nvmf_subsystem_get_ctrlr(subsystem, subsystem->next_cntlid) == NULL) {
1136 			/* Found unused cntlid */
1137 			return subsystem->next_cntlid;
1138 		}
1139 	}
1140 
1141 	/* All valid cntlid values are in use. */
1142 	return 0xFFFF;
1143 }
1144 
1145 int
1146 spdk_nvmf_subsystem_add_ctrlr(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *ctrlr)
1147 {
1148 	ctrlr->cntlid = spdk_nvmf_subsystem_gen_cntlid(subsystem);
1149 	if (ctrlr->cntlid == 0xFFFF) {
1150 		/* Unable to get a cntlid */
1151 		SPDK_ERRLOG("Reached max simultaneous ctrlrs\n");
1152 		return -EBUSY;
1153 	}
1154 
1155 	TAILQ_INSERT_TAIL(&subsystem->ctrlrs, ctrlr, link);
1156 
1157 	return 0;
1158 }
1159 
1160 void
1161 spdk_nvmf_subsystem_remove_ctrlr(struct spdk_nvmf_subsystem *subsystem,
1162 				 struct spdk_nvmf_ctrlr *ctrlr)
1163 {
1164 	assert(subsystem == ctrlr->subsys);
1165 	TAILQ_REMOVE(&subsystem->ctrlrs, ctrlr, link);
1166 }
1167 
1168 struct spdk_nvmf_ctrlr *
1169 spdk_nvmf_subsystem_get_ctrlr(struct spdk_nvmf_subsystem *subsystem, uint16_t cntlid)
1170 {
1171 	struct spdk_nvmf_ctrlr *ctrlr;
1172 
1173 	TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) {
1174 		if (ctrlr->cntlid == cntlid) {
1175 			return ctrlr;
1176 		}
1177 	}
1178 
1179 	return NULL;
1180 }
1181