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