xref: /spdk/lib/nvmf/subsystem.c (revision 310fc0b5d56fa43b80af869270fcf2758df9c92d)
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 	if (ns->ptpl_file) {
932 		free(ns->ptpl_file);
933 	}
934 	free(ns);
935 
936 	spdk_nvmf_subsystem_ns_changed(subsystem, nsid);
937 
938 	return 0;
939 }
940 
941 int
942 spdk_nvmf_subsystem_remove_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid,
943 			      spdk_nvmf_subsystem_state_change_done cb_fn, void *cb_arg)
944 {
945 	int rc;
946 	struct subsystem_update_ns_ctx *ctx;
947 
948 	rc = _spdk_nvmf_subsystem_remove_ns(subsystem, nsid);
949 	if (rc < 0) {
950 		return rc;
951 	}
952 
953 	ctx = calloc(1, sizeof(*ctx));
954 
955 	if (ctx == NULL) {
956 		return -ENOMEM;
957 	}
958 
959 	ctx->subsystem = subsystem;
960 	ctx->cb_fn = cb_fn;
961 	ctx->cb_arg = cb_arg;
962 
963 	spdk_nvmf_subsystem_update_ns(subsystem, subsystem_update_ns_done, ctx);
964 
965 	return 0;
966 }
967 
968 static void
969 _spdk_nvmf_ns_hot_remove_done(struct spdk_nvmf_subsystem *subsystem, void *cb_arg, int status)
970 {
971 	if (status != 0) {
972 		SPDK_ERRLOG("Failed to make changes to NVMe-oF subsystem with id %u\n", subsystem->id);
973 	}
974 	spdk_nvmf_subsystem_resume(subsystem, NULL, NULL);
975 }
976 
977 static void
978 _spdk_nvmf_ns_hot_remove(struct spdk_nvmf_subsystem *subsystem,
979 			 void *cb_arg, int status)
980 {
981 	struct spdk_nvmf_ns *ns = cb_arg;
982 
983 	spdk_nvmf_subsystem_remove_ns(subsystem, ns->opts.nsid, _spdk_nvmf_ns_hot_remove_done,
984 				      subsystem);
985 }
986 
987 static void
988 spdk_nvmf_ns_hot_remove(void *remove_ctx)
989 {
990 	struct spdk_nvmf_ns *ns = remove_ctx;
991 	int rc;
992 
993 	rc = spdk_nvmf_subsystem_pause(ns->subsystem, _spdk_nvmf_ns_hot_remove, ns);
994 	if (rc) {
995 		SPDK_ERRLOG("Unable to pause subsystem to process namespace removal!\n");
996 	}
997 }
998 
999 void
1000 spdk_nvmf_ns_opts_get_defaults(struct spdk_nvmf_ns_opts *opts, size_t opts_size)
1001 {
1002 	/* All current fields are set to 0 by default. */
1003 	memset(opts, 0, opts_size);
1004 }
1005 
1006 /* Dummy bdev module used to to claim bdevs. */
1007 static struct spdk_bdev_module ns_bdev_module = {
1008 	.name	= "NVMe-oF Target",
1009 };
1010 
1011 uint32_t
1012 spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bdev *bdev,
1013 			   const struct spdk_nvmf_ns_opts *user_opts, size_t opts_size,
1014 			   const char *ptpl_file)
1015 {
1016 	struct spdk_nvmf_ns_opts opts;
1017 	struct spdk_nvmf_ns *ns;
1018 	int rc;
1019 
1020 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
1021 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
1022 		return 0;
1023 	}
1024 
1025 	if (spdk_bdev_get_md_size(bdev) != 0 && !spdk_bdev_is_md_interleaved(bdev)) {
1026 		SPDK_ERRLOG("Can't attach bdev with separate metadata.\n");
1027 		return 0;
1028 	}
1029 
1030 	spdk_nvmf_ns_opts_get_defaults(&opts, sizeof(opts));
1031 	if (user_opts) {
1032 		memcpy(&opts, user_opts, spdk_min(sizeof(opts), opts_size));
1033 	}
1034 
1035 	if (spdk_mem_all_zero(&opts.uuid, sizeof(opts.uuid))) {
1036 		opts.uuid = *spdk_bdev_get_uuid(bdev);
1037 	}
1038 
1039 	if (opts.nsid == SPDK_NVME_GLOBAL_NS_TAG) {
1040 		SPDK_ERRLOG("Invalid NSID %" PRIu32 "\n", opts.nsid);
1041 		return 0;
1042 	}
1043 
1044 	if (opts.nsid == 0) {
1045 		/*
1046 		 * NSID not specified - find a free index.
1047 		 *
1048 		 * If no free slots are found, opts.nsid will be subsystem->max_nsid + 1, which will
1049 		 * expand max_nsid if possible.
1050 		 */
1051 		for (opts.nsid = 1; opts.nsid <= subsystem->max_nsid; opts.nsid++) {
1052 			if (_spdk_nvmf_subsystem_get_ns(subsystem, opts.nsid) == NULL) {
1053 				break;
1054 			}
1055 		}
1056 	}
1057 
1058 	if (_spdk_nvmf_subsystem_get_ns(subsystem, opts.nsid)) {
1059 		SPDK_ERRLOG("Requested NSID %" PRIu32 " already in use\n", opts.nsid);
1060 		return 0;
1061 	}
1062 
1063 	if (opts.nsid > subsystem->max_nsid) {
1064 		struct spdk_nvmf_ns **new_ns_array;
1065 
1066 		/* If MaxNamespaces was specified, we can't extend max_nsid beyond it. */
1067 		if (subsystem->max_allowed_nsid > 0 && opts.nsid > subsystem->max_allowed_nsid) {
1068 			SPDK_ERRLOG("Can't extend NSID range above MaxNamespaces\n");
1069 			return 0;
1070 		}
1071 
1072 		/* If a controller is connected, we can't change NN. */
1073 		if (!TAILQ_EMPTY(&subsystem->ctrlrs)) {
1074 			SPDK_ERRLOG("Can't extend NSID range while controllers are connected\n");
1075 			return 0;
1076 		}
1077 
1078 		new_ns_array = realloc(subsystem->ns, sizeof(struct spdk_nvmf_ns *) * opts.nsid);
1079 		if (new_ns_array == NULL) {
1080 			SPDK_ERRLOG("Memory allocation error while resizing namespace array.\n");
1081 			return 0;
1082 		}
1083 
1084 		memset(new_ns_array + subsystem->max_nsid, 0,
1085 		       sizeof(struct spdk_nvmf_ns *) * (opts.nsid - subsystem->max_nsid));
1086 		subsystem->ns = new_ns_array;
1087 		subsystem->max_nsid = opts.nsid;
1088 	}
1089 
1090 	ns = calloc(1, sizeof(*ns));
1091 	if (ns == NULL) {
1092 		SPDK_ERRLOG("Namespace allocation failed\n");
1093 		return 0;
1094 	}
1095 
1096 	ns->bdev = bdev;
1097 	ns->opts = opts;
1098 	ns->subsystem = subsystem;
1099 	rc = spdk_bdev_open(bdev, true, spdk_nvmf_ns_hot_remove, ns, &ns->desc);
1100 	if (rc != 0) {
1101 		SPDK_ERRLOG("Subsystem %s: bdev %s cannot be opened, error=%d\n",
1102 			    subsystem->subnqn, spdk_bdev_get_name(bdev), rc);
1103 		free(ns);
1104 		return 0;
1105 	}
1106 	rc = spdk_bdev_module_claim_bdev(bdev, ns->desc, &ns_bdev_module);
1107 	if (rc != 0) {
1108 		spdk_bdev_close(ns->desc);
1109 		free(ns);
1110 		return 0;
1111 	}
1112 	subsystem->ns[opts.nsid - 1] = ns;
1113 	ns->nsid = opts.nsid;
1114 	TAILQ_INIT(&ns->registrants);
1115 
1116 	if (ptpl_file) {
1117 		ns->ptpl_file = strdup(ptpl_file);
1118 	}
1119 
1120 	SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Subsystem %s: bdev %s assigned nsid %" PRIu32 "\n",
1121 		      spdk_nvmf_subsystem_get_nqn(subsystem),
1122 		      spdk_bdev_get_name(bdev),
1123 		      opts.nsid);
1124 
1125 	spdk_nvmf_subsystem_ns_changed(subsystem, opts.nsid);
1126 
1127 	return opts.nsid;
1128 }
1129 
1130 static uint32_t
1131 spdk_nvmf_subsystem_get_next_allocated_nsid(struct spdk_nvmf_subsystem *subsystem,
1132 		uint32_t prev_nsid)
1133 {
1134 	uint32_t nsid;
1135 
1136 	if (prev_nsid >= subsystem->max_nsid) {
1137 		return 0;
1138 	}
1139 
1140 	for (nsid = prev_nsid + 1; nsid <= subsystem->max_nsid; nsid++) {
1141 		if (subsystem->ns[nsid - 1]) {
1142 			return nsid;
1143 		}
1144 	}
1145 
1146 	return 0;
1147 }
1148 
1149 struct spdk_nvmf_ns *
1150 spdk_nvmf_subsystem_get_first_ns(struct spdk_nvmf_subsystem *subsystem)
1151 {
1152 	uint32_t first_nsid;
1153 
1154 	first_nsid = spdk_nvmf_subsystem_get_next_allocated_nsid(subsystem, 0);
1155 	return _spdk_nvmf_subsystem_get_ns(subsystem, first_nsid);
1156 }
1157 
1158 struct spdk_nvmf_ns *
1159 spdk_nvmf_subsystem_get_next_ns(struct spdk_nvmf_subsystem *subsystem,
1160 				struct spdk_nvmf_ns *prev_ns)
1161 {
1162 	uint32_t next_nsid;
1163 
1164 	next_nsid = spdk_nvmf_subsystem_get_next_allocated_nsid(subsystem, prev_ns->opts.nsid);
1165 	return _spdk_nvmf_subsystem_get_ns(subsystem, next_nsid);
1166 }
1167 
1168 struct spdk_nvmf_ns *
1169 spdk_nvmf_subsystem_get_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid)
1170 {
1171 	return _spdk_nvmf_subsystem_get_ns(subsystem, nsid);
1172 }
1173 
1174 uint32_t
1175 spdk_nvmf_ns_get_id(const struct spdk_nvmf_ns *ns)
1176 {
1177 	return ns->opts.nsid;
1178 }
1179 
1180 struct spdk_bdev *
1181 spdk_nvmf_ns_get_bdev(struct spdk_nvmf_ns *ns)
1182 {
1183 	return ns->bdev;
1184 }
1185 
1186 void
1187 spdk_nvmf_ns_get_opts(const struct spdk_nvmf_ns *ns, struct spdk_nvmf_ns_opts *opts,
1188 		      size_t opts_size)
1189 {
1190 	memset(opts, 0, opts_size);
1191 	memcpy(opts, &ns->opts, spdk_min(sizeof(ns->opts), opts_size));
1192 }
1193 
1194 const char *
1195 spdk_nvmf_subsystem_get_sn(const struct spdk_nvmf_subsystem *subsystem)
1196 {
1197 	return subsystem->sn;
1198 }
1199 
1200 int
1201 spdk_nvmf_subsystem_set_sn(struct spdk_nvmf_subsystem *subsystem, const char *sn)
1202 {
1203 	size_t len, max_len;
1204 
1205 	max_len = sizeof(subsystem->sn) - 1;
1206 	len = strlen(sn);
1207 	if (len > max_len) {
1208 		SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Invalid sn \"%s\": length %zu > max %zu\n",
1209 			      sn, len, max_len);
1210 		return -1;
1211 	}
1212 
1213 	if (!spdk_nvmf_valid_ascii_string(sn, len)) {
1214 		SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Non-ASCII sn\n");
1215 		SPDK_LOGDUMP(SPDK_LOG_NVMF, "sn", sn, len);
1216 		return -1;
1217 	}
1218 
1219 	snprintf(subsystem->sn, sizeof(subsystem->sn), "%s", sn);
1220 
1221 	return 0;
1222 }
1223 
1224 const char *
1225 spdk_nvmf_subsystem_get_mn(const struct spdk_nvmf_subsystem *subsystem)
1226 {
1227 	return subsystem->mn;
1228 }
1229 
1230 int
1231 spdk_nvmf_subsystem_set_mn(struct spdk_nvmf_subsystem *subsystem, const char *mn)
1232 {
1233 	size_t len, max_len;
1234 
1235 	if (mn == NULL) {
1236 		mn = MODEL_NUMBER_DEFAULT;
1237 	}
1238 	max_len = sizeof(subsystem->mn) - 1;
1239 	len = strlen(mn);
1240 	if (len > max_len) {
1241 		SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Invalid mn \"%s\": length %zu > max %zu\n",
1242 			      mn, len, max_len);
1243 		return -1;
1244 	}
1245 
1246 	if (!spdk_nvmf_valid_ascii_string(mn, len)) {
1247 		SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Non-ASCII mn\n");
1248 		SPDK_LOGDUMP(SPDK_LOG_NVMF, "mn", mn, len);
1249 		return -1;
1250 	}
1251 
1252 	snprintf(subsystem->mn, sizeof(subsystem->mn), "%s", mn);
1253 
1254 	return 0;
1255 }
1256 
1257 const char *
1258 spdk_nvmf_subsystem_get_nqn(struct spdk_nvmf_subsystem *subsystem)
1259 {
1260 	return subsystem->subnqn;
1261 }
1262 
1263 /* Workaround for astyle formatting bug */
1264 typedef enum spdk_nvmf_subtype nvmf_subtype_t;
1265 
1266 nvmf_subtype_t
1267 spdk_nvmf_subsystem_get_type(struct spdk_nvmf_subsystem *subsystem)
1268 {
1269 	return subsystem->subtype;
1270 }
1271 
1272 static uint16_t
1273 spdk_nvmf_subsystem_gen_cntlid(struct spdk_nvmf_subsystem *subsystem)
1274 {
1275 	int count;
1276 
1277 	/*
1278 	 * In the worst case, we might have to try all CNTLID values between 1 and 0xFFF0 - 1
1279 	 * before we find one that is unused (or find that all values are in use).
1280 	 */
1281 	for (count = 0; count < 0xFFF0 - 1; count++) {
1282 		subsystem->next_cntlid++;
1283 		if (subsystem->next_cntlid >= 0xFFF0) {
1284 			/* The spec reserves cntlid values in the range FFF0h to FFFFh. */
1285 			subsystem->next_cntlid = 1;
1286 		}
1287 
1288 		/* Check if a controller with this cntlid currently exists. */
1289 		if (spdk_nvmf_subsystem_get_ctrlr(subsystem, subsystem->next_cntlid) == NULL) {
1290 			/* Found unused cntlid */
1291 			return subsystem->next_cntlid;
1292 		}
1293 	}
1294 
1295 	/* All valid cntlid values are in use. */
1296 	return 0xFFFF;
1297 }
1298 
1299 int
1300 spdk_nvmf_subsystem_add_ctrlr(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *ctrlr)
1301 {
1302 	ctrlr->cntlid = spdk_nvmf_subsystem_gen_cntlid(subsystem);
1303 	if (ctrlr->cntlid == 0xFFFF) {
1304 		/* Unable to get a cntlid */
1305 		SPDK_ERRLOG("Reached max simultaneous ctrlrs\n");
1306 		return -EBUSY;
1307 	}
1308 
1309 	TAILQ_INSERT_TAIL(&subsystem->ctrlrs, ctrlr, link);
1310 
1311 	return 0;
1312 }
1313 
1314 void
1315 spdk_nvmf_subsystem_remove_ctrlr(struct spdk_nvmf_subsystem *subsystem,
1316 				 struct spdk_nvmf_ctrlr *ctrlr)
1317 {
1318 	assert(subsystem == ctrlr->subsys);
1319 	TAILQ_REMOVE(&subsystem->ctrlrs, ctrlr, link);
1320 }
1321 
1322 struct spdk_nvmf_ctrlr *
1323 spdk_nvmf_subsystem_get_ctrlr(struct spdk_nvmf_subsystem *subsystem, uint16_t cntlid)
1324 {
1325 	struct spdk_nvmf_ctrlr *ctrlr;
1326 
1327 	TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) {
1328 		if (ctrlr->cntlid == cntlid) {
1329 			return ctrlr;
1330 		}
1331 	}
1332 
1333 	return NULL;
1334 }
1335 
1336 uint32_t
1337 spdk_nvmf_subsystem_get_max_namespaces(const struct spdk_nvmf_subsystem *subsystem)
1338 {
1339 	return subsystem->max_allowed_nsid;
1340 }
1341 
1342 static struct spdk_nvmf_registrant *
1343 nvmf_ns_reservation_get_registrant(struct spdk_nvmf_ns *ns,
1344 				   struct spdk_uuid *uuid)
1345 {
1346 	struct spdk_nvmf_registrant *reg, *tmp;
1347 
1348 	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) {
1349 		if (!spdk_uuid_compare(&reg->hostid, uuid)) {
1350 			return reg;
1351 		}
1352 	}
1353 
1354 	return NULL;
1355 }
1356 
1357 /* Generate reservation notice log to registered HostID controllers */
1358 static void
1359 nvmf_subsystem_gen_ctrlr_notification(struct spdk_nvmf_subsystem *subsystem,
1360 				      struct spdk_nvmf_ns *ns,
1361 				      struct spdk_uuid *hostid_list,
1362 				      uint32_t num_hostid,
1363 				      enum spdk_nvme_reservation_notification_log_page_type type)
1364 {
1365 	struct spdk_nvmf_ctrlr *ctrlr;
1366 	uint32_t i;
1367 
1368 	for (i = 0; i < num_hostid; i++) {
1369 		TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) {
1370 			if (!spdk_uuid_compare(&ctrlr->hostid, &hostid_list[i])) {
1371 				spdk_nvmf_ctrlr_reservation_notice_log(ctrlr, ns, type);
1372 			}
1373 		}
1374 	}
1375 }
1376 
1377 /* Get all registrants' hostid other than the controller who issued the command */
1378 static uint32_t
1379 nvmf_ns_reservation_get_all_other_hostid(struct spdk_nvmf_ns *ns,
1380 		struct spdk_uuid *hostid_list,
1381 		uint32_t max_num_hostid,
1382 		struct spdk_uuid *current_hostid)
1383 {
1384 	struct spdk_nvmf_registrant *reg, *tmp;
1385 	uint32_t num_hostid = 0;
1386 
1387 	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) {
1388 		if (spdk_uuid_compare(&reg->hostid, current_hostid)) {
1389 			if (num_hostid == max_num_hostid) {
1390 				assert(false);
1391 				return max_num_hostid;
1392 			}
1393 			hostid_list[num_hostid++] = reg->hostid;
1394 		}
1395 	}
1396 
1397 	return num_hostid;
1398 }
1399 
1400 /* Calculate the unregistered HostID list according to list
1401  * prior to execute preempt command and list after executing
1402  * preempt command.
1403  */
1404 static uint32_t
1405 nvmf_ns_reservation_get_unregistered_hostid(struct spdk_uuid *old_hostid_list,
1406 		uint32_t old_num_hostid,
1407 		struct spdk_uuid *remaining_hostid_list,
1408 		uint32_t remaining_num_hostid)
1409 {
1410 	struct spdk_uuid temp_hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS];
1411 	uint32_t i, j, num_hostid = 0;
1412 	bool found;
1413 
1414 	if (!remaining_num_hostid) {
1415 		return old_num_hostid;
1416 	}
1417 
1418 	for (i = 0; i < old_num_hostid; i++) {
1419 		found = false;
1420 		for (j = 0; j < remaining_num_hostid; j++) {
1421 			if (!spdk_uuid_compare(&old_hostid_list[i], &remaining_hostid_list[j])) {
1422 				found = true;
1423 				break;
1424 			}
1425 		}
1426 		if (!found) {
1427 			spdk_uuid_copy(&temp_hostid_list[num_hostid++], &old_hostid_list[i]);
1428 		}
1429 	}
1430 
1431 	if (num_hostid) {
1432 		memcpy(old_hostid_list, temp_hostid_list, sizeof(struct spdk_uuid) * num_hostid);
1433 	}
1434 
1435 	return num_hostid;
1436 }
1437 
1438 /* current reservation type is all registrants or not */
1439 static bool
1440 nvmf_ns_reservation_all_registrants_type(struct spdk_nvmf_ns *ns)
1441 {
1442 	return (ns->rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS ||
1443 		ns->rtype == SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_ALL_REGS);
1444 }
1445 
1446 /* current registrant is reservation holder or not */
1447 static bool
1448 nvmf_ns_reservation_registrant_is_holder(struct spdk_nvmf_ns *ns,
1449 		struct spdk_nvmf_registrant *reg)
1450 {
1451 	if (!reg) {
1452 		return false;
1453 	}
1454 
1455 	if (nvmf_ns_reservation_all_registrants_type(ns)) {
1456 		return true;
1457 	}
1458 
1459 	return (ns->holder == reg);
1460 }
1461 
1462 static int
1463 nvmf_ns_reservation_add_registrant(struct spdk_nvmf_ns *ns,
1464 				   struct spdk_nvmf_ctrlr *ctrlr,
1465 				   uint64_t nrkey)
1466 {
1467 	struct spdk_nvmf_registrant *reg;
1468 
1469 	reg = calloc(1, sizeof(*reg));
1470 	if (!reg) {
1471 		return -ENOMEM;
1472 	}
1473 
1474 	reg->rkey = nrkey;
1475 	/* set hostid for the registrant */
1476 	spdk_uuid_copy(&reg->hostid, &ctrlr->hostid);
1477 	TAILQ_INSERT_TAIL(&ns->registrants, reg, link);
1478 	ns->gen++;
1479 
1480 	return 0;
1481 }
1482 
1483 static void
1484 nvmf_ns_reservation_release_reservation(struct spdk_nvmf_ns *ns)
1485 {
1486 	ns->rtype = 0;
1487 	ns->crkey = 0;
1488 	ns->holder = NULL;
1489 }
1490 
1491 /* release the reservation if the last registrant was removed */
1492 static void
1493 nvmf_ns_reservation_check_release_on_remove_registrant(struct spdk_nvmf_ns *ns,
1494 		struct spdk_nvmf_registrant *reg)
1495 {
1496 	struct spdk_nvmf_registrant *next_reg;
1497 
1498 	/* no reservation holder */
1499 	if (!ns->holder) {
1500 		assert(ns->rtype == 0);
1501 		return;
1502 	}
1503 
1504 	next_reg = TAILQ_FIRST(&ns->registrants);
1505 	if (next_reg && nvmf_ns_reservation_all_registrants_type(ns)) {
1506 		/* the next valid registrant is the new holder now */
1507 		ns->holder = next_reg;
1508 	} else if (nvmf_ns_reservation_registrant_is_holder(ns, reg)) {
1509 		/* release the reservation */
1510 		nvmf_ns_reservation_release_reservation(ns);
1511 	}
1512 }
1513 
1514 static void
1515 nvmf_ns_reservation_remove_registrant(struct spdk_nvmf_ns *ns,
1516 				      struct spdk_nvmf_registrant *reg)
1517 {
1518 	TAILQ_REMOVE(&ns->registrants, reg, link);
1519 	nvmf_ns_reservation_check_release_on_remove_registrant(ns, reg);
1520 	free(reg);
1521 	ns->gen++;
1522 	return;
1523 }
1524 
1525 static uint32_t
1526 nvmf_ns_reservation_remove_registrants_by_key(struct spdk_nvmf_ns *ns,
1527 		uint64_t rkey)
1528 {
1529 	struct spdk_nvmf_registrant *reg, *tmp;
1530 	uint32_t count = 0;
1531 
1532 	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) {
1533 		if (reg->rkey == rkey) {
1534 			nvmf_ns_reservation_remove_registrant(ns, reg);
1535 			count++;
1536 		}
1537 	}
1538 	return count;
1539 }
1540 
1541 static uint32_t
1542 nvmf_ns_reservation_remove_all_other_registrants(struct spdk_nvmf_ns *ns,
1543 		struct spdk_nvmf_registrant *reg)
1544 {
1545 	struct spdk_nvmf_registrant *reg_tmp, *reg_tmp2;
1546 	uint32_t count = 0;
1547 
1548 	TAILQ_FOREACH_SAFE(reg_tmp, &ns->registrants, link, reg_tmp2) {
1549 		if (reg_tmp != reg) {
1550 			nvmf_ns_reservation_remove_registrant(ns, reg_tmp);
1551 			count++;
1552 		}
1553 	}
1554 	return count;
1555 }
1556 
1557 static uint32_t
1558 nvmf_ns_reservation_clear_all_registrants(struct spdk_nvmf_ns *ns)
1559 {
1560 	struct spdk_nvmf_registrant *reg, *reg_tmp;
1561 	uint32_t count = 0;
1562 
1563 	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, reg_tmp) {
1564 		nvmf_ns_reservation_remove_registrant(ns, reg);
1565 		count++;
1566 	}
1567 	return count;
1568 }
1569 
1570 static void
1571 nvmf_ns_reservation_acquire_reservation(struct spdk_nvmf_ns *ns, uint64_t rkey,
1572 					enum spdk_nvme_reservation_type rtype,
1573 					struct spdk_nvmf_registrant *holder)
1574 {
1575 	ns->rtype = rtype;
1576 	ns->crkey = rkey;
1577 	assert(ns->holder == NULL);
1578 	ns->holder = holder;
1579 }
1580 
1581 static bool
1582 nvmf_ns_reservation_register(struct spdk_nvmf_ns *ns,
1583 			     struct spdk_nvmf_ctrlr *ctrlr,
1584 			     struct spdk_nvmf_request *req)
1585 {
1586 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
1587 	uint8_t rrega, iekey, cptpl, rtype;
1588 	struct spdk_nvme_reservation_register_data key;
1589 	struct spdk_nvmf_registrant *reg;
1590 	uint8_t status = SPDK_NVME_SC_SUCCESS;
1591 	bool update_sgroup = false;
1592 	struct spdk_uuid hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS];
1593 	uint32_t num_hostid = 0;
1594 	int rc;
1595 
1596 	rrega = cmd->cdw10 & 0x7u;
1597 	iekey = (cmd->cdw10 >> 3) & 0x1u;
1598 	cptpl = (cmd->cdw10 >> 30) & 0x3u;
1599 
1600 	if (req->data && req->length >= sizeof(key)) {
1601 		memcpy(&key, req->data, sizeof(key));
1602 	} else {
1603 		SPDK_ERRLOG("No key provided. Failing request.\n");
1604 		status = SPDK_NVME_SC_INVALID_FIELD;
1605 		goto exit;
1606 	}
1607 
1608 	SPDK_DEBUGLOG(SPDK_LOG_NVMF, "REGISTER: RREGA %u, IEKEY %u, CPTPL %u, "
1609 		      "NRKEY 0x%"PRIx64", NRKEY 0x%"PRIx64"\n",
1610 		      rrega, iekey, cptpl, key.crkey, key.nrkey);
1611 
1612 	/* TODO: doesn't support for now */
1613 	if (cptpl == SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS) {
1614 		SPDK_ERRLOG("Can't change persist through power loss for now\n");
1615 		status = SPDK_NVME_SC_INVALID_FIELD;
1616 		goto exit;
1617 	}
1618 
1619 	/* current Host Identifier has registrant or not */
1620 	reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid);
1621 
1622 	switch (rrega) {
1623 	case SPDK_NVME_RESERVE_REGISTER_KEY:
1624 		if (!reg) {
1625 			/* register new controller */
1626 			if (key.nrkey == 0) {
1627 				SPDK_ERRLOG("Can't register zeroed new key\n");
1628 				status = SPDK_NVME_SC_INVALID_FIELD;
1629 				goto exit;
1630 			}
1631 			rc = nvmf_ns_reservation_add_registrant(ns, ctrlr, key.nrkey);
1632 			if (rc < 0) {
1633 				status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
1634 				goto exit;
1635 			}
1636 			update_sgroup = true;
1637 		} else {
1638 			/* register with same key is not an error */
1639 			if (reg->rkey != key.nrkey) {
1640 				SPDK_ERRLOG("The same host already register a "
1641 					    "key with 0x%"PRIx64"\n",
1642 					    reg->rkey);
1643 				status = SPDK_NVME_SC_RESERVATION_CONFLICT;
1644 				goto exit;
1645 			}
1646 		}
1647 		break;
1648 	case SPDK_NVME_RESERVE_UNREGISTER_KEY:
1649 		if (!reg || (!iekey && reg->rkey != key.crkey)) {
1650 			SPDK_ERRLOG("No registrant or current key doesn't match "
1651 				    "with existing registrant key\n");
1652 			status = SPDK_NVME_SC_RESERVATION_CONFLICT;
1653 			goto exit;
1654 		}
1655 
1656 		rtype = ns->rtype;
1657 		num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, hostid_list,
1658 				SPDK_NVMF_MAX_NUM_REGISTRANTS,
1659 				&ctrlr->hostid);
1660 
1661 		nvmf_ns_reservation_remove_registrant(ns, reg);
1662 
1663 		if (!ns->rtype && num_hostid && (rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY ||
1664 						 rtype == SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY)) {
1665 			nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns,
1666 							      hostid_list,
1667 							      num_hostid,
1668 							      SPDK_NVME_RESERVATION_RELEASED);
1669 		}
1670 		update_sgroup = true;
1671 		break;
1672 	case SPDK_NVME_RESERVE_REPLACE_KEY:
1673 		if (!reg || (!iekey && reg->rkey != key.crkey)) {
1674 			SPDK_ERRLOG("No registrant or current key doesn't match "
1675 				    "with existing registrant key\n");
1676 			status = SPDK_NVME_SC_RESERVATION_CONFLICT;
1677 			goto exit;
1678 		}
1679 		if (key.nrkey == 0) {
1680 			SPDK_ERRLOG("Can't register zeroed new key\n");
1681 			status = SPDK_NVME_SC_INVALID_FIELD;
1682 			goto exit;
1683 		}
1684 		reg->rkey = key.nrkey;
1685 		update_sgroup = true;
1686 		break;
1687 	default:
1688 		status = SPDK_NVME_SC_INVALID_FIELD;
1689 		goto exit;
1690 	}
1691 
1692 exit:
1693 	req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC;
1694 	req->rsp->nvme_cpl.status.sc = status;
1695 	return update_sgroup;
1696 }
1697 
1698 static bool
1699 nvmf_ns_reservation_acquire(struct spdk_nvmf_ns *ns,
1700 			    struct spdk_nvmf_ctrlr *ctrlr,
1701 			    struct spdk_nvmf_request *req)
1702 {
1703 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
1704 	uint8_t racqa, iekey, rtype;
1705 	struct spdk_nvme_reservation_acquire_data key;
1706 	struct spdk_nvmf_registrant *reg;
1707 	bool all_regs = false;
1708 	uint32_t count = 0;
1709 	bool update_sgroup = true;
1710 	struct spdk_uuid hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS];
1711 	uint32_t num_hostid = 0;
1712 	struct spdk_uuid new_hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS];
1713 	uint32_t new_num_hostid = 0;
1714 	bool reservation_released = false;
1715 	uint8_t status = SPDK_NVME_SC_SUCCESS;
1716 
1717 	racqa = cmd->cdw10 & 0x7u;
1718 	iekey = (cmd->cdw10 >> 3) & 0x1u;
1719 	rtype = (cmd->cdw10 >> 8) & 0xffu;
1720 
1721 	if (req->data && req->length >= sizeof(key)) {
1722 		memcpy(&key, req->data, sizeof(key));
1723 	} else {
1724 		SPDK_ERRLOG("No key provided. Failing request.\n");
1725 		status = SPDK_NVME_SC_INVALID_FIELD;
1726 		goto exit;
1727 	}
1728 
1729 	SPDK_DEBUGLOG(SPDK_LOG_NVMF, "ACQUIRE: RACQA %u, IEKEY %u, RTYPE %u, "
1730 		      "NRKEY 0x%"PRIx64", PRKEY 0x%"PRIx64"\n",
1731 		      racqa, iekey, rtype, key.crkey, key.prkey);
1732 
1733 	if (iekey || rtype > SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_ALL_REGS) {
1734 		SPDK_ERRLOG("Ignore existing key field set to 1\n");
1735 		status = SPDK_NVME_SC_INVALID_FIELD;
1736 		update_sgroup = false;
1737 		goto exit;
1738 	}
1739 
1740 	reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid);
1741 	/* must be registrant and CRKEY must match */
1742 	if (!reg || reg->rkey != key.crkey) {
1743 		SPDK_ERRLOG("No registrant or current key doesn't match "
1744 			    "with existing registrant key\n");
1745 		status = SPDK_NVME_SC_RESERVATION_CONFLICT;
1746 		update_sgroup = false;
1747 		goto exit;
1748 	}
1749 
1750 	all_regs = nvmf_ns_reservation_all_registrants_type(ns);
1751 
1752 	switch (racqa) {
1753 	case SPDK_NVME_RESERVE_ACQUIRE:
1754 		/* it's not an error for the holder to acquire same reservation type again */
1755 		if (nvmf_ns_reservation_registrant_is_holder(ns, reg) && ns->rtype == rtype) {
1756 			/* do nothing */
1757 			update_sgroup = false;
1758 		} else if (ns->holder == NULL) {
1759 			/* fisrt time to acquire the reservation */
1760 			nvmf_ns_reservation_acquire_reservation(ns, key.crkey, rtype, reg);
1761 		} else {
1762 			SPDK_ERRLOG("Invalid rtype or current registrant is not holder\n");
1763 			status = SPDK_NVME_SC_RESERVATION_CONFLICT;
1764 			update_sgroup = false;
1765 			goto exit;
1766 		}
1767 		break;
1768 	case SPDK_NVME_RESERVE_PREEMPT:
1769 		/* no reservation holder */
1770 		if (!ns->holder) {
1771 			/* unregister with PRKEY */
1772 			nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey);
1773 			break;
1774 		}
1775 		num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, hostid_list,
1776 				SPDK_NVMF_MAX_NUM_REGISTRANTS,
1777 				&ctrlr->hostid);
1778 
1779 		/* only 1 reservation holder and reservation key is valid */
1780 		if (!all_regs) {
1781 			/* preempt itself */
1782 			if (nvmf_ns_reservation_registrant_is_holder(ns, reg) &&
1783 			    ns->crkey == key.prkey) {
1784 				ns->rtype = rtype;
1785 				reservation_released = true;
1786 				break;
1787 			}
1788 
1789 			if (ns->crkey == key.prkey) {
1790 				nvmf_ns_reservation_remove_registrant(ns, ns->holder);
1791 				nvmf_ns_reservation_acquire_reservation(ns, key.crkey, rtype, reg);
1792 				reservation_released = true;
1793 			} else if (key.prkey != 0) {
1794 				nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey);
1795 			} else {
1796 				/* PRKEY is zero */
1797 				SPDK_ERRLOG("Current PRKEY is zero\n");
1798 				status = SPDK_NVME_SC_RESERVATION_CONFLICT;
1799 				update_sgroup = false;
1800 				goto exit;
1801 			}
1802 		} else {
1803 			/* release all other registrants except for the current one */
1804 			if (key.prkey == 0) {
1805 				nvmf_ns_reservation_remove_all_other_registrants(ns, reg);
1806 				assert(ns->holder == reg);
1807 			} else {
1808 				count = nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey);
1809 				if (count == 0) {
1810 					SPDK_ERRLOG("PRKEY doesn't match any registrant\n");
1811 					status = SPDK_NVME_SC_RESERVATION_CONFLICT;
1812 					update_sgroup = false;
1813 					goto exit;
1814 				}
1815 			}
1816 		}
1817 		break;
1818 	default:
1819 		status = SPDK_NVME_SC_INVALID_FIELD;
1820 		update_sgroup = false;
1821 		break;
1822 	}
1823 
1824 exit:
1825 	if (update_sgroup && racqa == SPDK_NVME_RESERVE_PREEMPT) {
1826 		new_num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, new_hostid_list,
1827 				 SPDK_NVMF_MAX_NUM_REGISTRANTS,
1828 				 &ctrlr->hostid);
1829 		/* Preempt notification occurs on the unregistered controllers
1830 		 * other than the controller who issued the command.
1831 		 */
1832 		num_hostid = nvmf_ns_reservation_get_unregistered_hostid(hostid_list,
1833 				num_hostid,
1834 				new_hostid_list,
1835 				new_num_hostid);
1836 		if (num_hostid) {
1837 			nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns,
1838 							      hostid_list,
1839 							      num_hostid,
1840 							      SPDK_NVME_REGISTRATION_PREEMPTED);
1841 
1842 		}
1843 		/* Reservation released notification occurs on the
1844 		 * controllers which are the remaining registrants other than
1845 		 * the controller who issued the command.
1846 		 */
1847 		if (reservation_released && new_num_hostid) {
1848 			nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns,
1849 							      new_hostid_list,
1850 							      new_num_hostid,
1851 							      SPDK_NVME_RESERVATION_RELEASED);
1852 
1853 		}
1854 	}
1855 	req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC;
1856 	req->rsp->nvme_cpl.status.sc = status;
1857 	return update_sgroup;
1858 }
1859 
1860 static bool
1861 nvmf_ns_reservation_release(struct spdk_nvmf_ns *ns,
1862 			    struct spdk_nvmf_ctrlr *ctrlr,
1863 			    struct spdk_nvmf_request *req)
1864 {
1865 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
1866 	uint8_t rrela, iekey, rtype;
1867 	struct spdk_nvmf_registrant *reg;
1868 	uint64_t crkey;
1869 	uint8_t status = SPDK_NVME_SC_SUCCESS;
1870 	bool update_sgroup = true;
1871 	struct spdk_uuid hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS];
1872 	uint32_t num_hostid = 0;
1873 
1874 	rrela = cmd->cdw10 & 0x7u;
1875 	iekey = (cmd->cdw10 >> 3) & 0x1u;
1876 	rtype = (cmd->cdw10 >> 8) & 0xffu;
1877 
1878 	if (req->data && req->length >= sizeof(crkey)) {
1879 		memcpy(&crkey, req->data, sizeof(crkey));
1880 	} else {
1881 		SPDK_ERRLOG("No key provided. Failing request.\n");
1882 		status = SPDK_NVME_SC_INVALID_FIELD;
1883 		goto exit;
1884 	}
1885 
1886 	SPDK_DEBUGLOG(SPDK_LOG_NVMF, "RELEASE: RRELA %u, IEKEY %u, RTYPE %u, "
1887 		      "CRKEY 0x%"PRIx64"\n",  rrela, iekey, rtype, crkey);
1888 
1889 	if (iekey) {
1890 		SPDK_ERRLOG("Ignore existing key field set to 1\n");
1891 		status = SPDK_NVME_SC_INVALID_FIELD;
1892 		update_sgroup = false;
1893 		goto exit;
1894 	}
1895 
1896 	reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid);
1897 	if (!reg || reg->rkey != crkey) {
1898 		SPDK_ERRLOG("No registrant or current key doesn't match "
1899 			    "with existing registrant key\n");
1900 		status = SPDK_NVME_SC_RESERVATION_CONFLICT;
1901 		update_sgroup = false;
1902 		goto exit;
1903 	}
1904 
1905 	num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, hostid_list,
1906 			SPDK_NVMF_MAX_NUM_REGISTRANTS,
1907 			&ctrlr->hostid);
1908 
1909 	switch (rrela) {
1910 	case SPDK_NVME_RESERVE_RELEASE:
1911 		if (!ns->holder) {
1912 			SPDK_DEBUGLOG(SPDK_LOG_NVMF, "RELEASE: no holder\n");
1913 			update_sgroup = false;
1914 			goto exit;
1915 		}
1916 		if (ns->rtype != rtype) {
1917 			SPDK_ERRLOG("Type doesn't match\n");
1918 			status = SPDK_NVME_SC_INVALID_FIELD;
1919 			update_sgroup = false;
1920 			goto exit;
1921 		}
1922 		if (!nvmf_ns_reservation_registrant_is_holder(ns, reg)) {
1923 			/* not the reservation holder, this isn't an error */
1924 			update_sgroup = false;
1925 			goto exit;
1926 		}
1927 
1928 		rtype = ns->rtype;
1929 		nvmf_ns_reservation_release_reservation(ns);
1930 
1931 		if (num_hostid && rtype != SPDK_NVME_RESERVE_WRITE_EXCLUSIVE &&
1932 		    rtype != SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS) {
1933 			nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns,
1934 							      hostid_list,
1935 							      num_hostid,
1936 							      SPDK_NVME_RESERVATION_RELEASED);
1937 		}
1938 		break;
1939 	case SPDK_NVME_RESERVE_CLEAR:
1940 		nvmf_ns_reservation_clear_all_registrants(ns);
1941 		if (num_hostid) {
1942 			nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns,
1943 							      hostid_list,
1944 							      num_hostid,
1945 							      SPDK_NVME_RESERVATION_PREEMPTED);
1946 		}
1947 		break;
1948 	default:
1949 		status = SPDK_NVME_SC_INVALID_FIELD;
1950 		update_sgroup = false;
1951 		goto exit;
1952 	}
1953 
1954 exit:
1955 	req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC;
1956 	req->rsp->nvme_cpl.status.sc = status;
1957 	return update_sgroup;
1958 }
1959 
1960 static void
1961 nvmf_ns_reservation_report(struct spdk_nvmf_ns *ns,
1962 			   struct spdk_nvmf_ctrlr *ctrlr,
1963 			   struct spdk_nvmf_request *req)
1964 {
1965 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
1966 	struct spdk_nvmf_subsystem *subsystem = ctrlr->subsys;
1967 	struct spdk_nvmf_ctrlr *ctrlr_tmp;
1968 	struct spdk_nvmf_registrant *reg, *tmp;
1969 	struct spdk_nvme_reservation_status_extended_data *status_data;
1970 	struct spdk_nvme_registered_ctrlr_extended_data *ctrlr_data;
1971 	uint8_t *payload;
1972 	uint32_t len, count = 0;
1973 	uint32_t regctl = 0;
1974 	uint8_t status = SPDK_NVME_SC_SUCCESS;
1975 
1976 	if (req->data == NULL) {
1977 		SPDK_ERRLOG("No data transfer specified for request. "
1978 			    " Unable to transfer back response.\n");
1979 		status = SPDK_NVME_SC_INVALID_FIELD;
1980 		goto exit;
1981 	}
1982 
1983 	/* NVMeoF uses Extended Data Structure */
1984 	if ((cmd->cdw11 & 0x00000001u) == 0) {
1985 		SPDK_ERRLOG("NVMeoF uses extended controller data structure, "
1986 			    "please set EDS bit in cdw11 and try again\n");
1987 		status = SPDK_NVME_SC_INVALID_FIELD;
1988 		goto exit;
1989 	}
1990 
1991 	/* Get number of registerd controllers, one Host may have more than
1992 	 * one controller based on different ports.
1993 	 */
1994 	TAILQ_FOREACH(ctrlr_tmp, &subsystem->ctrlrs, link) {
1995 		reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr_tmp->hostid);
1996 		if (reg) {
1997 			regctl++;
1998 		}
1999 	}
2000 
2001 	len = sizeof(*status_data) + sizeof(*ctrlr_data) * regctl;
2002 	payload = calloc(1, len);
2003 	if (!payload) {
2004 		status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
2005 		goto exit;
2006 	}
2007 
2008 	status_data = (struct spdk_nvme_reservation_status_extended_data *)payload;
2009 	status_data->data.gen = ns->gen;
2010 	status_data->data.rtype = ns->rtype;
2011 	status_data->data.regctl = regctl;
2012 	status_data->data.ptpls = ns->ptpl_activated;
2013 
2014 	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) {
2015 		assert(count <= regctl);
2016 		ctrlr_data = (struct spdk_nvme_registered_ctrlr_extended_data *)
2017 			     (payload + sizeof(*status_data) + sizeof(*ctrlr_data) * count);
2018 		/* Set to 0xffffh for dynamic controller */
2019 		ctrlr_data->cntlid = 0xffff;
2020 		ctrlr_data->rcsts.status = (ns->holder == reg) ? true : false;
2021 		ctrlr_data->rkey = reg->rkey;
2022 		spdk_uuid_copy((struct spdk_uuid *)ctrlr_data->hostid, &reg->hostid);
2023 		count++;
2024 	}
2025 
2026 	memcpy(req->data, payload, spdk_min(len, (cmd->cdw10 + 1) * sizeof(uint32_t)));
2027 	free(payload);
2028 
2029 exit:
2030 	req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC;
2031 	req->rsp->nvme_cpl.status.sc = status;
2032 	return;
2033 }
2034 
2035 static void
2036 spdk_nvmf_ns_reservation_complete(void *ctx)
2037 {
2038 	struct spdk_nvmf_request *req = ctx;
2039 
2040 	spdk_nvmf_request_complete(req);
2041 }
2042 
2043 static void
2044 _nvmf_ns_reservation_update_done(struct spdk_nvmf_subsystem *subsystem,
2045 				 void *cb_arg, int status)
2046 {
2047 	struct spdk_nvmf_request *req = (struct spdk_nvmf_request *)cb_arg;
2048 	struct spdk_nvmf_poll_group *group = req->qpair->group;
2049 
2050 	spdk_thread_send_msg(group->thread, spdk_nvmf_ns_reservation_complete, req);
2051 }
2052 
2053 void
2054 spdk_nvmf_ns_reservation_request(void *ctx)
2055 {
2056 	struct spdk_nvmf_request *req = (struct spdk_nvmf_request *)ctx;
2057 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
2058 	struct spdk_nvmf_ctrlr *ctrlr = req->qpair->ctrlr;
2059 	struct subsystem_update_ns_ctx *update_ctx;
2060 	uint32_t nsid;
2061 	struct spdk_nvmf_ns *ns;
2062 	bool update_sgroup = false;
2063 
2064 	nsid = cmd->nsid;
2065 	ns = _spdk_nvmf_subsystem_get_ns(ctrlr->subsys, nsid);
2066 	assert(ns != NULL);
2067 
2068 	switch (cmd->opc) {
2069 	case SPDK_NVME_OPC_RESERVATION_REGISTER:
2070 		update_sgroup = nvmf_ns_reservation_register(ns, ctrlr, req);
2071 		break;
2072 	case SPDK_NVME_OPC_RESERVATION_ACQUIRE:
2073 		update_sgroup = nvmf_ns_reservation_acquire(ns, ctrlr, req);
2074 		break;
2075 	case SPDK_NVME_OPC_RESERVATION_RELEASE:
2076 		update_sgroup = nvmf_ns_reservation_release(ns, ctrlr, req);
2077 		break;
2078 	case SPDK_NVME_OPC_RESERVATION_REPORT:
2079 		nvmf_ns_reservation_report(ns, ctrlr, req);
2080 		break;
2081 	default:
2082 		break;
2083 	}
2084 
2085 	/* update reservation information to subsystem's poll group */
2086 	if (update_sgroup) {
2087 		update_ctx = calloc(1, sizeof(*update_ctx));
2088 		if (update_ctx == NULL) {
2089 			SPDK_ERRLOG("Can't alloc subsystem poll group update context\n");
2090 			goto update_done;
2091 		}
2092 		update_ctx->subsystem = ctrlr->subsys;
2093 		update_ctx->cb_fn = _nvmf_ns_reservation_update_done;
2094 		update_ctx->cb_arg = req;
2095 
2096 		spdk_nvmf_subsystem_update_ns(ctrlr->subsys, subsystem_update_ns_done, update_ctx);
2097 		return;
2098 	}
2099 
2100 update_done:
2101 	_nvmf_ns_reservation_update_done(ctrlr->subsys, (void *)req, 0);
2102 }
2103