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