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