xref: /spdk/lib/nvmf/subsystem.c (revision 6a41e84c0636acb6830133fbe3bdf91004db5c4d)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation. All rights reserved.
5  *   Copyright (c) 2019 Mellanox Technologies LTD. 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/likely.h"
40 #include "spdk/string.h"
41 #include "spdk/trace.h"
42 #include "spdk/nvmf_spec.h"
43 #include "spdk/uuid.h"
44 #include "spdk/json.h"
45 #include "spdk/file.h"
46 
47 #include "spdk/bdev_module.h"
48 #include "spdk_internal/log.h"
49 #include "spdk_internal/utf.h"
50 
51 #define MODEL_NUMBER_DEFAULT "SPDK bdev Controller"
52 
53 /*
54  * States for parsing valid domains in NQNs according to RFC 1034
55  */
56 enum spdk_nvmf_nqn_domain_states {
57 	/* First character of a domain must be a letter */
58 	SPDK_NVMF_DOMAIN_ACCEPT_LETTER = 0,
59 
60 	/* Subsequent characters can be any of letter, digit, or hyphen */
61 	SPDK_NVMF_DOMAIN_ACCEPT_LDH = 1,
62 
63 	/* A domain label must end with either a letter or digit */
64 	SPDK_NVMF_DOMAIN_ACCEPT_ANY = 2
65 };
66 
67 /* Returns true if is a valid ASCII string as defined by the NVMe spec */
68 static bool
69 nvmf_valid_ascii_string(const void *buf, size_t size)
70 {
71 	const uint8_t *str = buf;
72 	size_t i;
73 
74 	for (i = 0; i < size; i++) {
75 		if (str[i] < 0x20 || str[i] > 0x7E) {
76 			return false;
77 		}
78 	}
79 
80 	return true;
81 }
82 
83 static bool
84 nvmf_valid_nqn(const char *nqn)
85 {
86 	size_t len;
87 	struct spdk_uuid uuid_value;
88 	uint32_t i;
89 	int bytes_consumed;
90 	uint32_t domain_label_length;
91 	char *reverse_domain_end;
92 	uint32_t reverse_domain_end_index;
93 	enum spdk_nvmf_nqn_domain_states domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LETTER;
94 
95 	/* Check for length requirements */
96 	len = strlen(nqn);
97 	if (len > SPDK_NVMF_NQN_MAX_LEN) {
98 		SPDK_ERRLOG("Invalid NQN \"%s\": length %zu > max %d\n", nqn, len, SPDK_NVMF_NQN_MAX_LEN);
99 		return false;
100 	}
101 
102 	/* The nqn must be at least as long as SPDK_NVMF_NQN_MIN_LEN to contain the necessary prefix. */
103 	if (len < SPDK_NVMF_NQN_MIN_LEN) {
104 		SPDK_ERRLOG("Invalid NQN \"%s\": length %zu < min %d\n", nqn, len, SPDK_NVMF_NQN_MIN_LEN);
105 		return false;
106 	}
107 
108 	/* Check for discovery controller nqn */
109 	if (!strcmp(nqn, SPDK_NVMF_DISCOVERY_NQN)) {
110 		return true;
111 	}
112 
113 	/* Check for equality with the generic nqn structure of the form "nqn.2014-08.org.nvmexpress:uuid:11111111-2222-3333-4444-555555555555" */
114 	if (!strncmp(nqn, SPDK_NVMF_NQN_UUID_PRE, SPDK_NVMF_NQN_UUID_PRE_LEN)) {
115 		if (len != SPDK_NVMF_NQN_UUID_PRE_LEN + SPDK_NVMF_UUID_STRING_LEN) {
116 			SPDK_ERRLOG("Invalid NQN \"%s\": uuid is not the correct length\n", nqn);
117 			return false;
118 		}
119 
120 		if (spdk_uuid_parse(&uuid_value, &nqn[SPDK_NVMF_NQN_UUID_PRE_LEN])) {
121 			SPDK_ERRLOG("Invalid NQN \"%s\": uuid is not formatted correctly\n", nqn);
122 			return false;
123 		}
124 		return true;
125 	}
126 
127 	/* If the nqn does not match the uuid structure, the next several checks validate the form "nqn.yyyy-mm.reverse.domain:user-string" */
128 
129 	if (strncmp(nqn, "nqn.", 4) != 0) {
130 		SPDK_ERRLOG("Invalid NQN \"%s\": NQN must begin with \"nqn.\".\n", nqn);
131 		return false;
132 	}
133 
134 	/* Check for yyyy-mm. */
135 	if (!(isdigit(nqn[4]) && isdigit(nqn[5]) && isdigit(nqn[6]) && isdigit(nqn[7]) &&
136 	      nqn[8] == '-' && isdigit(nqn[9]) && isdigit(nqn[10]) && nqn[11] == '.')) {
137 		SPDK_ERRLOG("Invalid date code in NQN \"%s\"\n", nqn);
138 		return false;
139 	}
140 
141 	reverse_domain_end = strchr(nqn, ':');
142 	if (reverse_domain_end != NULL && (reverse_domain_end_index = reverse_domain_end - nqn) < len - 1) {
143 	} else {
144 		SPDK_ERRLOG("Invalid NQN \"%s\". NQN must contain user specified name with a ':' as a prefix.\n",
145 			    nqn);
146 		return false;
147 	}
148 
149 	/* Check for valid reverse domain */
150 	domain_label_length = 0;
151 	for (i = 12; i < reverse_domain_end_index; i++) {
152 		if (domain_label_length > SPDK_DOMAIN_LABEL_MAX_LEN) {
153 			SPDK_ERRLOG("Invalid domain name in NQN \"%s\". At least one Label is too long.\n", nqn);
154 			return false;
155 		}
156 
157 		switch (domain_state) {
158 
159 		case SPDK_NVMF_DOMAIN_ACCEPT_LETTER: {
160 			if (isalpha(nqn[i])) {
161 				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_ANY;
162 				domain_label_length++;
163 				break;
164 			} else {
165 				SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must start with a letter.\n", nqn);
166 				return false;
167 			}
168 		}
169 
170 		case SPDK_NVMF_DOMAIN_ACCEPT_LDH: {
171 			if (isalpha(nqn[i]) || isdigit(nqn[i])) {
172 				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_ANY;
173 				domain_label_length++;
174 				break;
175 			} else if (nqn[i] == '-') {
176 				if (i == reverse_domain_end_index - 1) {
177 					SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must end with an alphanumeric symbol.\n",
178 						    nqn);
179 					return false;
180 				}
181 				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LDH;
182 				domain_label_length++;
183 				break;
184 			} else if (nqn[i] == '.') {
185 				SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must end with an alphanumeric symbol.\n",
186 					    nqn);
187 				return false;
188 			} else {
189 				SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must contain only [a-z,A-Z,0-9,'-','.'].\n",
190 					    nqn);
191 				return false;
192 			}
193 		}
194 
195 		case SPDK_NVMF_DOMAIN_ACCEPT_ANY: {
196 			if (isalpha(nqn[i]) || isdigit(nqn[i])) {
197 				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_ANY;
198 				domain_label_length++;
199 				break;
200 			} else if (nqn[i] == '-') {
201 				if (i == reverse_domain_end_index - 1) {
202 					SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must end with an alphanumeric symbol.\n",
203 						    nqn);
204 					return false;
205 				}
206 				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LDH;
207 				domain_label_length++;
208 				break;
209 			} else if (nqn[i] == '.') {
210 				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LETTER;
211 				domain_label_length = 0;
212 				break;
213 			} else {
214 				SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must contain only [a-z,A-Z,0-9,'-','.'].\n",
215 					    nqn);
216 				return false;
217 			}
218 		}
219 		}
220 	}
221 
222 	i = reverse_domain_end_index + 1;
223 	while (i < len) {
224 		bytes_consumed = utf8_valid(&nqn[i], &nqn[len]);
225 		if (bytes_consumed <= 0) {
226 			SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must contain only valid utf-8.\n", nqn);
227 			return false;
228 		}
229 
230 		i += bytes_consumed;
231 	}
232 	return true;
233 }
234 
235 static void subsystem_state_change_on_pg(struct spdk_io_channel_iter *i);
236 
237 struct spdk_nvmf_subsystem *
238 spdk_nvmf_subsystem_create(struct spdk_nvmf_tgt *tgt,
239 			   const char *nqn,
240 			   enum spdk_nvmf_subtype type,
241 			   uint32_t num_ns)
242 {
243 	struct spdk_nvmf_subsystem	*subsystem;
244 	uint32_t			sid;
245 
246 	if (spdk_nvmf_tgt_find_subsystem(tgt, nqn)) {
247 		SPDK_ERRLOG("Subsystem NQN '%s' already exists\n", nqn);
248 		return NULL;
249 	}
250 
251 	if (!nvmf_valid_nqn(nqn)) {
252 		return NULL;
253 	}
254 
255 	if (type == SPDK_NVMF_SUBTYPE_DISCOVERY && num_ns != 0) {
256 		SPDK_ERRLOG("Discovery subsystem cannot have namespaces.\n");
257 		return NULL;
258 	}
259 
260 	/* Find a free subsystem id (sid) */
261 	for (sid = 0; sid < tgt->max_subsystems; sid++) {
262 		if (tgt->subsystems[sid] == NULL) {
263 			break;
264 		}
265 	}
266 	if (sid >= tgt->max_subsystems) {
267 		return NULL;
268 	}
269 
270 	subsystem = calloc(1, sizeof(struct spdk_nvmf_subsystem));
271 	if (subsystem == NULL) {
272 		return NULL;
273 	}
274 
275 	subsystem->thread = spdk_get_thread();
276 	subsystem->state = SPDK_NVMF_SUBSYSTEM_INACTIVE;
277 	subsystem->tgt = tgt;
278 	subsystem->id = sid;
279 	subsystem->subtype = type;
280 	subsystem->max_nsid = num_ns;
281 	subsystem->max_allowed_nsid = num_ns;
282 	subsystem->next_cntlid = 0;
283 	snprintf(subsystem->subnqn, sizeof(subsystem->subnqn), "%s", nqn);
284 	TAILQ_INIT(&subsystem->listeners);
285 	TAILQ_INIT(&subsystem->hosts);
286 	TAILQ_INIT(&subsystem->ctrlrs);
287 
288 	if (num_ns != 0) {
289 		subsystem->ns = calloc(num_ns, sizeof(struct spdk_nvmf_ns *));
290 		if (subsystem->ns == NULL) {
291 			SPDK_ERRLOG("Namespace memory allocation failed\n");
292 			free(subsystem);
293 			return NULL;
294 		}
295 	}
296 
297 	memset(subsystem->sn, '0', sizeof(subsystem->sn) - 1);
298 	subsystem->sn[sizeof(subsystem->sn) - 1] = '\0';
299 
300 	snprintf(subsystem->mn, sizeof(subsystem->mn), "%s",
301 		 MODEL_NUMBER_DEFAULT);
302 
303 	tgt->subsystems[sid] = subsystem;
304 	tgt->discovery_genctr++;
305 
306 	return subsystem;
307 }
308 
309 static void
310 nvmf_subsystem_remove_host(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_host *host)
311 {
312 	TAILQ_REMOVE(&subsystem->hosts, host, link);
313 	free(host);
314 }
315 
316 static void
317 _nvmf_subsystem_remove_listener(struct spdk_nvmf_subsystem *subsystem,
318 				struct spdk_nvmf_subsystem_listener *listener,
319 				bool stop)
320 {
321 	struct spdk_nvmf_transport *transport;
322 
323 	if (stop) {
324 		transport = spdk_nvmf_tgt_get_transport(subsystem->tgt, listener->trid->trstring);
325 		if (transport != NULL) {
326 			spdk_nvmf_transport_stop_listen(transport, listener->trid);
327 		}
328 	}
329 
330 	TAILQ_REMOVE(&subsystem->listeners, listener, link);
331 	free(listener);
332 }
333 
334 void
335 spdk_nvmf_subsystem_destroy(struct spdk_nvmf_subsystem *subsystem)
336 {
337 	struct spdk_nvmf_host		*host, *host_tmp;
338 	struct spdk_nvmf_ctrlr		*ctrlr, *ctrlr_tmp;
339 	struct spdk_nvmf_ns		*ns;
340 
341 	if (!subsystem) {
342 		return;
343 	}
344 
345 	assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE);
346 
347 	SPDK_DEBUGLOG(SPDK_LOG_NVMF, "subsystem is %p\n", subsystem);
348 
349 	nvmf_subsystem_remove_all_listeners(subsystem, false);
350 
351 	TAILQ_FOREACH_SAFE(host, &subsystem->hosts, link, host_tmp) {
352 		nvmf_subsystem_remove_host(subsystem, host);
353 	}
354 
355 	TAILQ_FOREACH_SAFE(ctrlr, &subsystem->ctrlrs, link, ctrlr_tmp) {
356 		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 
376 /* we have to use the typedef in the function declaration to appease astyle. */
377 typedef enum spdk_nvmf_subsystem_state spdk_nvmf_subsystem_state_t;
378 
379 static spdk_nvmf_subsystem_state_t
380 nvmf_subsystem_get_intermediate_state(enum spdk_nvmf_subsystem_state current_state,
381 				      enum spdk_nvmf_subsystem_state requested_state)
382 {
383 	switch (requested_state) {
384 	case SPDK_NVMF_SUBSYSTEM_INACTIVE:
385 		return SPDK_NVMF_SUBSYSTEM_DEACTIVATING;
386 	case SPDK_NVMF_SUBSYSTEM_ACTIVE:
387 		if (current_state == SPDK_NVMF_SUBSYSTEM_PAUSED) {
388 			return SPDK_NVMF_SUBSYSTEM_RESUMING;
389 		} else {
390 			return SPDK_NVMF_SUBSYSTEM_ACTIVATING;
391 		}
392 	case SPDK_NVMF_SUBSYSTEM_PAUSED:
393 		return SPDK_NVMF_SUBSYSTEM_PAUSING;
394 	default:
395 		assert(false);
396 		return SPDK_NVMF_SUBSYSTEM_NUM_STATES;
397 	}
398 }
399 
400 static int
401 nvmf_subsystem_set_state(struct spdk_nvmf_subsystem *subsystem,
402 			 enum spdk_nvmf_subsystem_state state)
403 {
404 	enum spdk_nvmf_subsystem_state actual_old_state, expected_old_state;
405 	bool exchanged;
406 
407 	switch (state) {
408 	case SPDK_NVMF_SUBSYSTEM_INACTIVE:
409 		expected_old_state = SPDK_NVMF_SUBSYSTEM_DEACTIVATING;
410 		break;
411 	case SPDK_NVMF_SUBSYSTEM_ACTIVATING:
412 		expected_old_state = SPDK_NVMF_SUBSYSTEM_INACTIVE;
413 		break;
414 	case SPDK_NVMF_SUBSYSTEM_ACTIVE:
415 		expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING;
416 		break;
417 	case SPDK_NVMF_SUBSYSTEM_PAUSING:
418 		expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
419 		break;
420 	case SPDK_NVMF_SUBSYSTEM_PAUSED:
421 		expected_old_state = SPDK_NVMF_SUBSYSTEM_PAUSING;
422 		break;
423 	case SPDK_NVMF_SUBSYSTEM_RESUMING:
424 		expected_old_state = SPDK_NVMF_SUBSYSTEM_PAUSED;
425 		break;
426 	case SPDK_NVMF_SUBSYSTEM_DEACTIVATING:
427 		expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
428 		break;
429 	default:
430 		assert(false);
431 		return -1;
432 	}
433 
434 	actual_old_state = expected_old_state;
435 	exchanged = __atomic_compare_exchange_n(&subsystem->state, &actual_old_state, state, false,
436 						__ATOMIC_RELAXED, __ATOMIC_RELAXED);
437 	if (spdk_unlikely(exchanged == false)) {
438 		if (actual_old_state == SPDK_NVMF_SUBSYSTEM_RESUMING &&
439 		    state == SPDK_NVMF_SUBSYSTEM_ACTIVE) {
440 			expected_old_state = SPDK_NVMF_SUBSYSTEM_RESUMING;
441 		}
442 		/* This is for the case when activating the subsystem fails. */
443 		if (actual_old_state == SPDK_NVMF_SUBSYSTEM_ACTIVATING &&
444 		    state == SPDK_NVMF_SUBSYSTEM_DEACTIVATING) {
445 			expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING;
446 		}
447 		/* This is for the case when resuming the subsystem fails. */
448 		if (actual_old_state == SPDK_NVMF_SUBSYSTEM_RESUMING &&
449 		    state == SPDK_NVMF_SUBSYSTEM_PAUSING) {
450 			expected_old_state = SPDK_NVMF_SUBSYSTEM_RESUMING;
451 		}
452 		actual_old_state = expected_old_state;
453 		__atomic_compare_exchange_n(&subsystem->state, &actual_old_state, state, false,
454 					    __ATOMIC_RELAXED, __ATOMIC_RELAXED);
455 	}
456 	assert(actual_old_state == expected_old_state);
457 	return actual_old_state - expected_old_state;
458 }
459 
460 struct subsystem_state_change_ctx {
461 	struct spdk_nvmf_subsystem *subsystem;
462 
463 	enum spdk_nvmf_subsystem_state original_state;
464 
465 	enum spdk_nvmf_subsystem_state requested_state;
466 
467 	spdk_nvmf_subsystem_state_change_done cb_fn;
468 	void *cb_arg;
469 };
470 
471 static void
472 subsystem_state_change_revert_done(struct spdk_io_channel_iter *i, int status)
473 {
474 	struct subsystem_state_change_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
475 
476 	/* Nothing to be done here if the state setting fails, we are just screwed. */
477 	if (nvmf_subsystem_set_state(ctx->subsystem, ctx->requested_state)) {
478 		SPDK_ERRLOG("Unable to revert the subsystem state after operation failure.\n");
479 	}
480 
481 	ctx->subsystem->changing_state = false;
482 	if (ctx->cb_fn) {
483 		/* return a failure here. This function only exists in an error path. */
484 		ctx->cb_fn(ctx->subsystem, ctx->cb_arg, -1);
485 	}
486 	free(ctx);
487 }
488 
489 static void
490 subsystem_state_change_done(struct spdk_io_channel_iter *i, int status)
491 {
492 	struct subsystem_state_change_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
493 	enum spdk_nvmf_subsystem_state intermediate_state;
494 
495 	if (status == 0) {
496 		status = nvmf_subsystem_set_state(ctx->subsystem, ctx->requested_state);
497 		if (status) {
498 			status = -1;
499 		}
500 	}
501 
502 	if (status) {
503 		intermediate_state = nvmf_subsystem_get_intermediate_state(ctx->requested_state,
504 				     ctx->original_state);
505 		assert(intermediate_state != SPDK_NVMF_SUBSYSTEM_NUM_STATES);
506 
507 		if (nvmf_subsystem_set_state(ctx->subsystem, intermediate_state)) {
508 			goto out;
509 		}
510 		ctx->requested_state = ctx->original_state;
511 		spdk_for_each_channel(ctx->subsystem->tgt,
512 				      subsystem_state_change_on_pg,
513 				      ctx,
514 				      subsystem_state_change_revert_done);
515 		return;
516 	}
517 
518 out:
519 	ctx->subsystem->changing_state = false;
520 	if (ctx->cb_fn) {
521 		ctx->cb_fn(ctx->subsystem, ctx->cb_arg, status);
522 	}
523 	free(ctx);
524 }
525 
526 static void
527 subsystem_state_change_continue(void *ctx, int status)
528 {
529 	struct spdk_io_channel_iter *i = ctx;
530 	spdk_for_each_channel_continue(i, status);
531 }
532 
533 static void
534 subsystem_state_change_on_pg(struct spdk_io_channel_iter *i)
535 {
536 	struct subsystem_state_change_ctx *ctx;
537 	struct spdk_io_channel *ch;
538 	struct spdk_nvmf_poll_group *group;
539 
540 	ctx = spdk_io_channel_iter_get_ctx(i);
541 	ch = spdk_io_channel_iter_get_channel(i);
542 	group = spdk_io_channel_get_ctx(ch);
543 
544 	switch (ctx->requested_state) {
545 	case SPDK_NVMF_SUBSYSTEM_INACTIVE:
546 		nvmf_poll_group_remove_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i);
547 		break;
548 	case SPDK_NVMF_SUBSYSTEM_ACTIVE:
549 		if (ctx->subsystem->state == SPDK_NVMF_SUBSYSTEM_ACTIVATING) {
550 			nvmf_poll_group_add_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i);
551 		} else if (ctx->subsystem->state == SPDK_NVMF_SUBSYSTEM_RESUMING) {
552 			nvmf_poll_group_resume_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i);
553 		}
554 		break;
555 	case SPDK_NVMF_SUBSYSTEM_PAUSED:
556 		nvmf_poll_group_pause_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i);
557 		break;
558 	default:
559 		assert(false);
560 		break;
561 	}
562 }
563 
564 static int
565 nvmf_subsystem_state_change(struct spdk_nvmf_subsystem *subsystem,
566 			    enum spdk_nvmf_subsystem_state requested_state,
567 			    spdk_nvmf_subsystem_state_change_done cb_fn,
568 			    void *cb_arg)
569 {
570 	struct subsystem_state_change_ctx *ctx;
571 	enum spdk_nvmf_subsystem_state intermediate_state;
572 	int rc;
573 
574 	if (__sync_val_compare_and_swap(&subsystem->changing_state, false, true)) {
575 		return -EBUSY;
576 	}
577 
578 	/* If we are already in the requested state, just call the callback immediately. */
579 	if (subsystem->state == requested_state) {
580 		subsystem->changing_state = false;
581 		if (cb_fn) {
582 			cb_fn(subsystem, cb_arg, 0);
583 		}
584 		return 0;
585 	}
586 
587 	intermediate_state = nvmf_subsystem_get_intermediate_state(subsystem->state, requested_state);
588 	assert(intermediate_state != SPDK_NVMF_SUBSYSTEM_NUM_STATES);
589 
590 	ctx = calloc(1, sizeof(*ctx));
591 	if (!ctx) {
592 		subsystem->changing_state = false;
593 		return -ENOMEM;
594 	}
595 
596 	ctx->original_state = subsystem->state;
597 	rc = nvmf_subsystem_set_state(subsystem, intermediate_state);
598 	if (rc) {
599 		free(ctx);
600 		subsystem->changing_state = false;
601 		return rc;
602 	}
603 
604 	ctx->subsystem = subsystem;
605 	ctx->requested_state = requested_state;
606 	ctx->cb_fn = cb_fn;
607 	ctx->cb_arg = cb_arg;
608 
609 	spdk_for_each_channel(subsystem->tgt,
610 			      subsystem_state_change_on_pg,
611 			      ctx,
612 			      subsystem_state_change_done);
613 
614 	return 0;
615 }
616 
617 int
618 spdk_nvmf_subsystem_start(struct spdk_nvmf_subsystem *subsystem,
619 			  spdk_nvmf_subsystem_state_change_done cb_fn,
620 			  void *cb_arg)
621 {
622 	return nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_ACTIVE, cb_fn, cb_arg);
623 }
624 
625 int
626 spdk_nvmf_subsystem_stop(struct spdk_nvmf_subsystem *subsystem,
627 			 spdk_nvmf_subsystem_state_change_done cb_fn,
628 			 void *cb_arg)
629 {
630 	return nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_INACTIVE, cb_fn, cb_arg);
631 }
632 
633 int
634 spdk_nvmf_subsystem_pause(struct spdk_nvmf_subsystem *subsystem,
635 			  spdk_nvmf_subsystem_state_change_done cb_fn,
636 			  void *cb_arg)
637 {
638 	return nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_PAUSED, cb_fn, cb_arg);
639 }
640 
641 int
642 spdk_nvmf_subsystem_resume(struct spdk_nvmf_subsystem *subsystem,
643 			   spdk_nvmf_subsystem_state_change_done cb_fn,
644 			   void *cb_arg)
645 {
646 	return nvmf_subsystem_state_change(subsystem, SPDK_NVMF_SUBSYSTEM_ACTIVE, cb_fn, cb_arg);
647 }
648 
649 struct spdk_nvmf_subsystem *
650 spdk_nvmf_subsystem_get_first(struct spdk_nvmf_tgt *tgt)
651 {
652 	struct spdk_nvmf_subsystem	*subsystem;
653 	uint32_t sid;
654 
655 	for (sid = 0; sid < tgt->max_subsystems; sid++) {
656 		subsystem = tgt->subsystems[sid];
657 		if (subsystem) {
658 			return subsystem;
659 		}
660 	}
661 
662 	return NULL;
663 }
664 
665 struct spdk_nvmf_subsystem *
666 spdk_nvmf_subsystem_get_next(struct spdk_nvmf_subsystem *subsystem)
667 {
668 	uint32_t sid;
669 	struct spdk_nvmf_tgt *tgt;
670 
671 	if (!subsystem) {
672 		return NULL;
673 	}
674 
675 	tgt = subsystem->tgt;
676 
677 	for (sid = subsystem->id + 1; sid < tgt->max_subsystems; sid++) {
678 		subsystem = tgt->subsystems[sid];
679 		if (subsystem) {
680 			return subsystem;
681 		}
682 	}
683 
684 	return NULL;
685 }
686 
687 static struct spdk_nvmf_host *
688 nvmf_subsystem_find_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn)
689 {
690 	struct spdk_nvmf_host *host = NULL;
691 
692 	TAILQ_FOREACH(host, &subsystem->hosts, link) {
693 		if (strcmp(hostnqn, host->nqn) == 0) {
694 			return host;
695 		}
696 	}
697 
698 	return NULL;
699 }
700 
701 int
702 spdk_nvmf_subsystem_add_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn)
703 {
704 	struct spdk_nvmf_host *host;
705 
706 	if (!nvmf_valid_nqn(hostnqn)) {
707 		return -EINVAL;
708 	}
709 
710 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
711 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
712 		return -EAGAIN;
713 	}
714 
715 	if (nvmf_subsystem_find_host(subsystem, hostnqn)) {
716 		/* This subsystem already allows the specified host. */
717 		return 0;
718 	}
719 
720 	host = calloc(1, sizeof(*host));
721 	if (!host) {
722 		return -ENOMEM;
723 	}
724 
725 	snprintf(host->nqn, sizeof(host->nqn), "%s", hostnqn);
726 
727 	TAILQ_INSERT_HEAD(&subsystem->hosts, host, link);
728 	subsystem->tgt->discovery_genctr++;
729 
730 	return 0;
731 }
732 
733 int
734 spdk_nvmf_subsystem_remove_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn)
735 {
736 	struct spdk_nvmf_host *host;
737 
738 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
739 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
740 		return -EAGAIN;
741 	}
742 
743 	host = nvmf_subsystem_find_host(subsystem, hostnqn);
744 	if (host == NULL) {
745 		return -ENOENT;
746 	}
747 
748 	nvmf_subsystem_remove_host(subsystem, host);
749 	return 0;
750 }
751 
752 int
753 spdk_nvmf_subsystem_set_allow_any_host(struct spdk_nvmf_subsystem *subsystem, bool allow_any_host)
754 {
755 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
756 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
757 		return -EAGAIN;
758 	}
759 
760 	subsystem->flags.allow_any_host = allow_any_host;
761 
762 	return 0;
763 }
764 
765 bool
766 spdk_nvmf_subsystem_get_allow_any_host(const struct spdk_nvmf_subsystem *subsystem)
767 {
768 	return subsystem->flags.allow_any_host;
769 }
770 
771 bool
772 spdk_nvmf_subsystem_host_allowed(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn)
773 {
774 	if (!hostnqn) {
775 		return false;
776 	}
777 
778 	if (subsystem->flags.allow_any_host) {
779 		return true;
780 	}
781 
782 	return nvmf_subsystem_find_host(subsystem, hostnqn) != NULL;
783 }
784 
785 struct spdk_nvmf_host *
786 spdk_nvmf_subsystem_get_first_host(struct spdk_nvmf_subsystem *subsystem)
787 {
788 	return TAILQ_FIRST(&subsystem->hosts);
789 }
790 
791 
792 struct spdk_nvmf_host *
793 spdk_nvmf_subsystem_get_next_host(struct spdk_nvmf_subsystem *subsystem,
794 				  struct spdk_nvmf_host *prev_host)
795 {
796 	return TAILQ_NEXT(prev_host, link);
797 }
798 
799 const char *
800 spdk_nvmf_host_get_nqn(const struct spdk_nvmf_host *host)
801 {
802 	return host->nqn;
803 }
804 
805 struct spdk_nvmf_subsystem_listener *
806 nvmf_subsystem_find_listener(struct spdk_nvmf_subsystem *subsystem,
807 			     const struct spdk_nvme_transport_id *trid)
808 {
809 	struct spdk_nvmf_subsystem_listener *listener;
810 
811 	TAILQ_FOREACH(listener, &subsystem->listeners, link) {
812 		if (spdk_nvme_transport_id_compare(listener->trid, trid) == 0) {
813 			return listener;
814 		}
815 	}
816 
817 	return NULL;
818 }
819 
820 /**
821  * Function to be called once the target is listening.
822  *
823  * \param ctx Context argument passed to this function.
824  * \param status 0 if it completed successfully, or negative errno if it failed.
825  */
826 static void
827 _nvmf_subsystem_add_listener_done(void *ctx, int status)
828 {
829 	struct spdk_nvmf_subsystem_listener *listener = ctx;
830 
831 	if (status) {
832 		listener->cb_fn(listener->cb_arg, status);
833 		free(listener);
834 		return;
835 	}
836 
837 	TAILQ_INSERT_HEAD(&listener->subsystem->listeners, listener, link);
838 	listener->subsystem->tgt->discovery_genctr++;
839 	listener->cb_fn(listener->cb_arg, status);
840 }
841 
842 void
843 spdk_nvmf_subsystem_add_listener(struct spdk_nvmf_subsystem *subsystem,
844 				 struct spdk_nvme_transport_id *trid,
845 				 spdk_nvmf_tgt_subsystem_listen_done_fn cb_fn,
846 				 void *cb_arg)
847 {
848 	struct spdk_nvmf_transport *transport;
849 	struct spdk_nvmf_subsystem_listener *listener;
850 	struct spdk_nvmf_listener *tr_listener;
851 	int rc = 0;
852 
853 	assert(cb_fn != NULL);
854 
855 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
856 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
857 		cb_fn(cb_arg, -EAGAIN);
858 		return;
859 	}
860 
861 	if (nvmf_subsystem_find_listener(subsystem, trid)) {
862 		/* Listener already exists in this subsystem */
863 		cb_fn(cb_arg, 0);
864 		return;
865 	}
866 
867 	transport = spdk_nvmf_tgt_get_transport(subsystem->tgt, trid->trstring);
868 	if (transport == NULL) {
869 		SPDK_ERRLOG("Unknown transport type %d\n", trid->trtype);
870 		cb_fn(cb_arg, -EINVAL);
871 		return;
872 	}
873 
874 	tr_listener = nvmf_transport_find_listener(transport, trid);
875 	if (!tr_listener) {
876 		SPDK_ERRLOG("Cannot find transport listener for %s\n", trid->traddr);
877 		cb_fn(cb_arg, -EINVAL);
878 		return;
879 	}
880 
881 	listener = calloc(1, sizeof(*listener));
882 	if (!listener) {
883 		cb_fn(cb_arg, -ENOMEM);
884 		return;
885 	}
886 
887 	listener->trid = &tr_listener->trid;
888 	listener->transport = transport;
889 	listener->cb_fn = cb_fn;
890 	listener->cb_arg = cb_arg;
891 	listener->subsystem = subsystem;
892 	listener->ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
893 
894 	if (transport->ops->listen_associate != NULL) {
895 		rc = transport->ops->listen_associate(transport, subsystem, trid);
896 	}
897 
898 	_nvmf_subsystem_add_listener_done(listener, rc);
899 }
900 
901 int
902 spdk_nvmf_subsystem_remove_listener(struct spdk_nvmf_subsystem *subsystem,
903 				    const struct spdk_nvme_transport_id *trid)
904 {
905 	struct spdk_nvmf_subsystem_listener *listener;
906 
907 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
908 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
909 		return -EAGAIN;
910 	}
911 
912 	listener = nvmf_subsystem_find_listener(subsystem, trid);
913 	if (listener == NULL) {
914 		return -ENOENT;
915 	}
916 
917 	_nvmf_subsystem_remove_listener(subsystem, listener, false);
918 
919 	return 0;
920 }
921 
922 void
923 nvmf_subsystem_remove_all_listeners(struct spdk_nvmf_subsystem *subsystem,
924 				    bool stop)
925 {
926 	struct spdk_nvmf_subsystem_listener *listener, *listener_tmp;
927 
928 	TAILQ_FOREACH_SAFE(listener, &subsystem->listeners, link, listener_tmp) {
929 		_nvmf_subsystem_remove_listener(subsystem, listener, stop);
930 	}
931 }
932 
933 bool
934 spdk_nvmf_subsystem_listener_allowed(struct spdk_nvmf_subsystem *subsystem,
935 				     const struct spdk_nvme_transport_id *trid)
936 {
937 	struct spdk_nvmf_subsystem_listener *listener;
938 
939 	if (!strcmp(subsystem->subnqn, SPDK_NVMF_DISCOVERY_NQN)) {
940 		return true;
941 	}
942 
943 	TAILQ_FOREACH(listener, &subsystem->listeners, link) {
944 		if (spdk_nvme_transport_id_compare(listener->trid, trid) == 0) {
945 			return true;
946 		}
947 	}
948 
949 	return false;
950 }
951 
952 struct spdk_nvmf_subsystem_listener *
953 spdk_nvmf_subsystem_get_first_listener(struct spdk_nvmf_subsystem *subsystem)
954 {
955 	return TAILQ_FIRST(&subsystem->listeners);
956 }
957 
958 struct spdk_nvmf_subsystem_listener *
959 spdk_nvmf_subsystem_get_next_listener(struct spdk_nvmf_subsystem *subsystem,
960 				      struct spdk_nvmf_subsystem_listener *prev_listener)
961 {
962 	return TAILQ_NEXT(prev_listener, link);
963 }
964 
965 const struct spdk_nvme_transport_id *
966 spdk_nvmf_subsystem_listener_get_trid(struct spdk_nvmf_subsystem_listener *listener)
967 {
968 	return listener->trid;
969 }
970 
971 void
972 spdk_nvmf_subsystem_allow_any_listener(struct spdk_nvmf_subsystem *subsystem,
973 				       bool allow_any_listener)
974 {
975 	subsystem->flags.allow_any_listener = allow_any_listener;
976 }
977 
978 bool
979 spdk_nvmf_subsytem_any_listener_allowed(struct spdk_nvmf_subsystem *subsystem)
980 {
981 	return subsystem->flags.allow_any_listener;
982 }
983 
984 
985 struct subsystem_update_ns_ctx {
986 	struct spdk_nvmf_subsystem *subsystem;
987 
988 	spdk_nvmf_subsystem_state_change_done cb_fn;
989 	void *cb_arg;
990 };
991 
992 static void
993 subsystem_update_ns_done(struct spdk_io_channel_iter *i, int status)
994 {
995 	struct subsystem_update_ns_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
996 
997 	if (ctx->cb_fn) {
998 		ctx->cb_fn(ctx->subsystem, ctx->cb_arg, status);
999 	}
1000 	free(ctx);
1001 }
1002 
1003 static void
1004 subsystem_update_ns_on_pg(struct spdk_io_channel_iter *i)
1005 {
1006 	int rc;
1007 	struct subsystem_update_ns_ctx *ctx;
1008 	struct spdk_nvmf_poll_group *group;
1009 	struct spdk_nvmf_subsystem *subsystem;
1010 
1011 	ctx = spdk_io_channel_iter_get_ctx(i);
1012 	group = spdk_io_channel_get_ctx(spdk_io_channel_iter_get_channel(i));
1013 	subsystem = ctx->subsystem;
1014 
1015 	rc = nvmf_poll_group_update_subsystem(group, subsystem);
1016 	spdk_for_each_channel_continue(i, rc);
1017 }
1018 
1019 static int
1020 nvmf_subsystem_update_ns(struct spdk_nvmf_subsystem *subsystem, spdk_channel_for_each_cpl cpl,
1021 			 void *ctx)
1022 {
1023 	spdk_for_each_channel(subsystem->tgt,
1024 			      subsystem_update_ns_on_pg,
1025 			      ctx,
1026 			      cpl);
1027 
1028 	return 0;
1029 }
1030 
1031 static void
1032 nvmf_subsystem_ns_changed(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid)
1033 {
1034 	struct spdk_nvmf_ctrlr *ctrlr;
1035 
1036 	TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) {
1037 		nvmf_ctrlr_ns_changed(ctrlr, nsid);
1038 	}
1039 }
1040 
1041 int
1042 spdk_nvmf_subsystem_remove_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid)
1043 {
1044 	struct spdk_nvmf_ns *ns;
1045 	struct spdk_nvmf_registrant *reg, *reg_tmp;
1046 
1047 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
1048 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
1049 		assert(false);
1050 		return -1;
1051 	}
1052 
1053 	if (nsid == 0 || nsid > subsystem->max_nsid) {
1054 		return -1;
1055 	}
1056 
1057 	ns = subsystem->ns[nsid - 1];
1058 	if (!ns) {
1059 		return -1;
1060 	}
1061 
1062 	subsystem->ns[nsid - 1] = NULL;
1063 
1064 	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, reg_tmp) {
1065 		TAILQ_REMOVE(&ns->registrants, reg, link);
1066 		free(reg);
1067 	}
1068 	spdk_bdev_module_release_bdev(ns->bdev);
1069 	spdk_bdev_close(ns->desc);
1070 	if (ns->ptpl_file) {
1071 		free(ns->ptpl_file);
1072 	}
1073 	free(ns);
1074 
1075 	nvmf_subsystem_ns_changed(subsystem, nsid);
1076 
1077 	return 0;
1078 }
1079 
1080 struct subsystem_ns_change_ctx {
1081 	struct spdk_nvmf_subsystem		*subsystem;
1082 	spdk_nvmf_subsystem_state_change_done	cb_fn;
1083 	uint32_t				nsid;
1084 };
1085 
1086 static void
1087 _nvmf_ns_hot_remove(struct spdk_nvmf_subsystem *subsystem,
1088 		    void *cb_arg, int status)
1089 {
1090 	struct subsystem_ns_change_ctx *ctx = cb_arg;
1091 	int rc;
1092 
1093 	rc = spdk_nvmf_subsystem_remove_ns(subsystem, ctx->nsid);
1094 	if (rc != 0) {
1095 		SPDK_ERRLOG("Failed to make changes to NVME-oF subsystem with id: %u\n", subsystem->id);
1096 	}
1097 
1098 	spdk_nvmf_subsystem_resume(subsystem, NULL, NULL);
1099 
1100 	free(ctx);
1101 }
1102 
1103 static void
1104 nvmf_ns_change_msg(void *ns_ctx)
1105 {
1106 	struct subsystem_ns_change_ctx *ctx = ns_ctx;
1107 	int rc;
1108 
1109 	rc = spdk_nvmf_subsystem_pause(ctx->subsystem, ctx->cb_fn, ctx);
1110 	if (rc) {
1111 		if (rc == -EBUSY) {
1112 			/* Try again, this is not a permanent situation. */
1113 			spdk_thread_send_msg(spdk_get_thread(), nvmf_ns_change_msg, ctx);
1114 		} else {
1115 			free(ctx);
1116 			SPDK_ERRLOG("Unable to pause subsystem to process namespace removal!\n");
1117 		}
1118 	}
1119 }
1120 
1121 static void
1122 nvmf_ns_hot_remove(void *remove_ctx)
1123 {
1124 	struct spdk_nvmf_ns *ns = remove_ctx;
1125 	struct subsystem_ns_change_ctx *ns_ctx;
1126 	int rc;
1127 
1128 	/* We have to allocate a new context because this op
1129 	 * is asynchronous and we could lose the ns in the middle.
1130 	 */
1131 	ns_ctx = calloc(1, sizeof(struct subsystem_ns_change_ctx));
1132 	if (!ns_ctx) {
1133 		SPDK_ERRLOG("Unable to allocate context to process namespace removal!\n");
1134 		return;
1135 	}
1136 
1137 	ns_ctx->subsystem = ns->subsystem;
1138 	ns_ctx->nsid = ns->opts.nsid;
1139 	ns_ctx->cb_fn = _nvmf_ns_hot_remove;
1140 
1141 	rc = spdk_nvmf_subsystem_pause(ns->subsystem, _nvmf_ns_hot_remove, ns_ctx);
1142 	if (rc) {
1143 		if (rc == -EBUSY) {
1144 			/* Try again, this is not a permanent situation. */
1145 			spdk_thread_send_msg(spdk_get_thread(), nvmf_ns_change_msg, ns_ctx);
1146 		} else {
1147 			SPDK_ERRLOG("Unable to pause subsystem to process namespace removal!\n");
1148 			free(ns_ctx);
1149 		}
1150 	}
1151 }
1152 
1153 static void
1154 _nvmf_ns_resize(struct spdk_nvmf_subsystem *subsystem, void *cb_arg, int status)
1155 {
1156 	struct subsystem_ns_change_ctx *ctx = cb_arg;
1157 
1158 	nvmf_subsystem_ns_changed(subsystem, ctx->nsid);
1159 	spdk_nvmf_subsystem_resume(subsystem, NULL, NULL);
1160 
1161 	free(ctx);
1162 }
1163 
1164 static void
1165 nvmf_ns_resize(void *event_ctx)
1166 {
1167 	struct spdk_nvmf_ns *ns = event_ctx;
1168 	struct subsystem_ns_change_ctx *ns_ctx;
1169 	int rc;
1170 
1171 	/* We have to allocate a new context because this op
1172 	 * is asynchronous and we could lose the ns in the middle.
1173 	 */
1174 	ns_ctx = calloc(1, sizeof(struct subsystem_ns_change_ctx));
1175 	if (!ns_ctx) {
1176 		SPDK_ERRLOG("Unable to allocate context to process namespace removal!\n");
1177 		return;
1178 	}
1179 
1180 	ns_ctx->subsystem = ns->subsystem;
1181 	ns_ctx->nsid = ns->opts.nsid;
1182 	ns_ctx->cb_fn = _nvmf_ns_resize;
1183 
1184 	rc = spdk_nvmf_subsystem_pause(ns->subsystem, _nvmf_ns_resize, ns_ctx);
1185 	if (rc) {
1186 		if (rc == -EBUSY) {
1187 			/* Try again, this is not a permanent situation. */
1188 			spdk_thread_send_msg(spdk_get_thread(), nvmf_ns_change_msg, ns_ctx);
1189 		}
1190 		SPDK_ERRLOG("Unable to pause subsystem to process namespace resize!\n");
1191 		free(ns_ctx);
1192 	}
1193 }
1194 
1195 static void
1196 nvmf_ns_event(enum spdk_bdev_event_type type,
1197 	      struct spdk_bdev *bdev,
1198 	      void *event_ctx)
1199 {
1200 	SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Bdev event: type %d, name %s, subsystem_id %d, ns_id %d\n",
1201 		      type,
1202 		      bdev->name,
1203 		      ((struct spdk_nvmf_ns *)event_ctx)->subsystem->id,
1204 		      ((struct spdk_nvmf_ns *)event_ctx)->nsid);
1205 
1206 	switch (type) {
1207 	case SPDK_BDEV_EVENT_REMOVE:
1208 		nvmf_ns_hot_remove(event_ctx);
1209 		break;
1210 	case SPDK_BDEV_EVENT_RESIZE:
1211 		nvmf_ns_resize(event_ctx);
1212 		break;
1213 	default:
1214 		SPDK_NOTICELOG("Unsupported bdev event: type %d\n", type);
1215 		break;
1216 	}
1217 }
1218 
1219 void
1220 spdk_nvmf_ns_opts_get_defaults(struct spdk_nvmf_ns_opts *opts, size_t opts_size)
1221 {
1222 	/* All current fields are set to 0 by default. */
1223 	memset(opts, 0, opts_size);
1224 }
1225 
1226 /* Dummy bdev module used to to claim bdevs. */
1227 static struct spdk_bdev_module ns_bdev_module = {
1228 	.name	= "NVMe-oF Target",
1229 };
1230 
1231 static int
1232 nvmf_ns_load_reservation(const char *file, struct spdk_nvmf_reservation_info *info);
1233 static int
1234 nvmf_ns_reservation_restore(struct spdk_nvmf_ns *ns, struct spdk_nvmf_reservation_info *info);
1235 
1236 uint32_t
1237 spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bdev *bdev,
1238 			   const struct spdk_nvmf_ns_opts *user_opts, size_t opts_size,
1239 			   const char *ptpl_file)
1240 {
1241 	struct spdk_nvmf_ns_opts opts;
1242 	struct spdk_nvmf_ns *ns;
1243 	struct spdk_nvmf_reservation_info info = {0};
1244 	int rc;
1245 
1246 	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
1247 	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
1248 		return 0;
1249 	}
1250 
1251 	if (spdk_bdev_get_md_size(bdev) != 0 && !spdk_bdev_is_md_interleaved(bdev)) {
1252 		SPDK_ERRLOG("Can't attach bdev with separate metadata.\n");
1253 		return 0;
1254 	}
1255 
1256 	spdk_nvmf_ns_opts_get_defaults(&opts, sizeof(opts));
1257 	if (user_opts) {
1258 		memcpy(&opts, user_opts, spdk_min(sizeof(opts), opts_size));
1259 	}
1260 
1261 	if (spdk_mem_all_zero(&opts.uuid, sizeof(opts.uuid))) {
1262 		opts.uuid = *spdk_bdev_get_uuid(bdev);
1263 	}
1264 
1265 	if (opts.nsid == SPDK_NVME_GLOBAL_NS_TAG) {
1266 		SPDK_ERRLOG("Invalid NSID %" PRIu32 "\n", opts.nsid);
1267 		return 0;
1268 	}
1269 
1270 	if (opts.nsid == 0) {
1271 		/*
1272 		 * NSID not specified - find a free index.
1273 		 *
1274 		 * If no free slots are found, opts.nsid will be subsystem->max_nsid + 1, which will
1275 		 * expand max_nsid if possible.
1276 		 */
1277 		for (opts.nsid = 1; opts.nsid <= subsystem->max_nsid; opts.nsid++) {
1278 			if (_nvmf_subsystem_get_ns(subsystem, opts.nsid) == NULL) {
1279 				break;
1280 			}
1281 		}
1282 	}
1283 
1284 	if (_nvmf_subsystem_get_ns(subsystem, opts.nsid)) {
1285 		SPDK_ERRLOG("Requested NSID %" PRIu32 " already in use\n", opts.nsid);
1286 		return 0;
1287 	}
1288 
1289 	if (opts.nsid > subsystem->max_nsid) {
1290 		struct spdk_nvmf_ns **new_ns_array;
1291 
1292 		/* If MaxNamespaces was specified, we can't extend max_nsid beyond it. */
1293 		if (subsystem->max_allowed_nsid > 0 && opts.nsid > subsystem->max_allowed_nsid) {
1294 			SPDK_ERRLOG("Can't extend NSID range above MaxNamespaces\n");
1295 			return 0;
1296 		}
1297 
1298 		/* If a controller is connected, we can't change NN. */
1299 		if (!TAILQ_EMPTY(&subsystem->ctrlrs)) {
1300 			SPDK_ERRLOG("Can't extend NSID range while controllers are connected\n");
1301 			return 0;
1302 		}
1303 
1304 		new_ns_array = realloc(subsystem->ns, sizeof(struct spdk_nvmf_ns *) * opts.nsid);
1305 		if (new_ns_array == NULL) {
1306 			SPDK_ERRLOG("Memory allocation error while resizing namespace array.\n");
1307 			return 0;
1308 		}
1309 
1310 		memset(new_ns_array + subsystem->max_nsid, 0,
1311 		       sizeof(struct spdk_nvmf_ns *) * (opts.nsid - subsystem->max_nsid));
1312 		subsystem->ns = new_ns_array;
1313 		subsystem->max_nsid = opts.nsid;
1314 	}
1315 
1316 	ns = calloc(1, sizeof(*ns));
1317 	if (ns == NULL) {
1318 		SPDK_ERRLOG("Namespace allocation failed\n");
1319 		return 0;
1320 	}
1321 
1322 	ns->bdev = bdev;
1323 	ns->opts = opts;
1324 	ns->subsystem = subsystem;
1325 	rc = spdk_bdev_open_ext(bdev->name, true, nvmf_ns_event, ns, &ns->desc);
1326 	if (rc != 0) {
1327 		SPDK_ERRLOG("Subsystem %s: bdev %s cannot be opened, error=%d\n",
1328 			    subsystem->subnqn, spdk_bdev_get_name(bdev), rc);
1329 		free(ns);
1330 		return 0;
1331 	}
1332 	rc = spdk_bdev_module_claim_bdev(bdev, ns->desc, &ns_bdev_module);
1333 	if (rc != 0) {
1334 		spdk_bdev_close(ns->desc);
1335 		free(ns);
1336 		return 0;
1337 	}
1338 	subsystem->ns[opts.nsid - 1] = ns;
1339 	ns->nsid = opts.nsid;
1340 	TAILQ_INIT(&ns->registrants);
1341 
1342 	if (ptpl_file) {
1343 		rc = nvmf_ns_load_reservation(ptpl_file, &info);
1344 		if (!rc) {
1345 			rc = nvmf_ns_reservation_restore(ns, &info);
1346 			if (rc) {
1347 				SPDK_ERRLOG("Subsystem restore reservation failed\n");
1348 				subsystem->ns[opts.nsid - 1] = NULL;
1349 				spdk_bdev_close(ns->desc);
1350 				free(ns);
1351 				return 0;
1352 			}
1353 		}
1354 		ns->ptpl_file = strdup(ptpl_file);
1355 	}
1356 
1357 	SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Subsystem %s: bdev %s assigned nsid %" PRIu32 "\n",
1358 		      spdk_nvmf_subsystem_get_nqn(subsystem),
1359 		      spdk_bdev_get_name(bdev),
1360 		      opts.nsid);
1361 
1362 	nvmf_subsystem_ns_changed(subsystem, opts.nsid);
1363 
1364 	return opts.nsid;
1365 }
1366 
1367 static uint32_t
1368 nvmf_subsystem_get_next_allocated_nsid(struct spdk_nvmf_subsystem *subsystem,
1369 				       uint32_t prev_nsid)
1370 {
1371 	uint32_t nsid;
1372 
1373 	if (prev_nsid >= subsystem->max_nsid) {
1374 		return 0;
1375 	}
1376 
1377 	for (nsid = prev_nsid + 1; nsid <= subsystem->max_nsid; nsid++) {
1378 		if (subsystem->ns[nsid - 1]) {
1379 			return nsid;
1380 		}
1381 	}
1382 
1383 	return 0;
1384 }
1385 
1386 struct spdk_nvmf_ns *
1387 spdk_nvmf_subsystem_get_first_ns(struct spdk_nvmf_subsystem *subsystem)
1388 {
1389 	uint32_t first_nsid;
1390 
1391 	first_nsid = nvmf_subsystem_get_next_allocated_nsid(subsystem, 0);
1392 	return _nvmf_subsystem_get_ns(subsystem, first_nsid);
1393 }
1394 
1395 struct spdk_nvmf_ns *
1396 spdk_nvmf_subsystem_get_next_ns(struct spdk_nvmf_subsystem *subsystem,
1397 				struct spdk_nvmf_ns *prev_ns)
1398 {
1399 	uint32_t next_nsid;
1400 
1401 	next_nsid = nvmf_subsystem_get_next_allocated_nsid(subsystem, prev_ns->opts.nsid);
1402 	return _nvmf_subsystem_get_ns(subsystem, next_nsid);
1403 }
1404 
1405 struct spdk_nvmf_ns *
1406 spdk_nvmf_subsystem_get_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid)
1407 {
1408 	return _nvmf_subsystem_get_ns(subsystem, nsid);
1409 }
1410 
1411 uint32_t
1412 spdk_nvmf_ns_get_id(const struct spdk_nvmf_ns *ns)
1413 {
1414 	return ns->opts.nsid;
1415 }
1416 
1417 struct spdk_bdev *
1418 spdk_nvmf_ns_get_bdev(struct spdk_nvmf_ns *ns)
1419 {
1420 	return ns->bdev;
1421 }
1422 
1423 void
1424 spdk_nvmf_ns_get_opts(const struct spdk_nvmf_ns *ns, struct spdk_nvmf_ns_opts *opts,
1425 		      size_t opts_size)
1426 {
1427 	memset(opts, 0, opts_size);
1428 	memcpy(opts, &ns->opts, spdk_min(sizeof(ns->opts), opts_size));
1429 }
1430 
1431 const char *
1432 spdk_nvmf_subsystem_get_sn(const struct spdk_nvmf_subsystem *subsystem)
1433 {
1434 	return subsystem->sn;
1435 }
1436 
1437 int
1438 spdk_nvmf_subsystem_set_sn(struct spdk_nvmf_subsystem *subsystem, const char *sn)
1439 {
1440 	size_t len, max_len;
1441 
1442 	max_len = sizeof(subsystem->sn) - 1;
1443 	len = strlen(sn);
1444 	if (len > max_len) {
1445 		SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Invalid sn \"%s\": length %zu > max %zu\n",
1446 			      sn, len, max_len);
1447 		return -1;
1448 	}
1449 
1450 	if (!nvmf_valid_ascii_string(sn, len)) {
1451 		SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Non-ASCII sn\n");
1452 		SPDK_LOGDUMP(SPDK_LOG_NVMF, "sn", sn, len);
1453 		return -1;
1454 	}
1455 
1456 	snprintf(subsystem->sn, sizeof(subsystem->sn), "%s", sn);
1457 
1458 	return 0;
1459 }
1460 
1461 const char *
1462 spdk_nvmf_subsystem_get_mn(const struct spdk_nvmf_subsystem *subsystem)
1463 {
1464 	return subsystem->mn;
1465 }
1466 
1467 int
1468 spdk_nvmf_subsystem_set_mn(struct spdk_nvmf_subsystem *subsystem, const char *mn)
1469 {
1470 	size_t len, max_len;
1471 
1472 	if (mn == NULL) {
1473 		mn = MODEL_NUMBER_DEFAULT;
1474 	}
1475 	max_len = sizeof(subsystem->mn) - 1;
1476 	len = strlen(mn);
1477 	if (len > max_len) {
1478 		SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Invalid mn \"%s\": length %zu > max %zu\n",
1479 			      mn, len, max_len);
1480 		return -1;
1481 	}
1482 
1483 	if (!nvmf_valid_ascii_string(mn, len)) {
1484 		SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Non-ASCII mn\n");
1485 		SPDK_LOGDUMP(SPDK_LOG_NVMF, "mn", mn, len);
1486 		return -1;
1487 	}
1488 
1489 	snprintf(subsystem->mn, sizeof(subsystem->mn), "%s", mn);
1490 
1491 	return 0;
1492 }
1493 
1494 const char *
1495 spdk_nvmf_subsystem_get_nqn(const struct spdk_nvmf_subsystem *subsystem)
1496 {
1497 	return subsystem->subnqn;
1498 }
1499 
1500 enum spdk_nvmf_subtype spdk_nvmf_subsystem_get_type(struct spdk_nvmf_subsystem *subsystem)
1501 {
1502 	return subsystem->subtype;
1503 }
1504 
1505 uint32_t
1506 spdk_nvmf_subsystem_get_max_nsid(struct spdk_nvmf_subsystem *subsystem)
1507 {
1508 	return subsystem->max_nsid;
1509 }
1510 
1511 static uint16_t
1512 nvmf_subsystem_gen_cntlid(struct spdk_nvmf_subsystem *subsystem)
1513 {
1514 	int count;
1515 
1516 	/*
1517 	 * In the worst case, we might have to try all CNTLID values between 1 and 0xFFF0 - 1
1518 	 * before we find one that is unused (or find that all values are in use).
1519 	 */
1520 	for (count = 0; count < 0xFFF0 - 1; count++) {
1521 		subsystem->next_cntlid++;
1522 		if (subsystem->next_cntlid >= 0xFFF0) {
1523 			/* The spec reserves cntlid values in the range FFF0h to FFFFh. */
1524 			subsystem->next_cntlid = 1;
1525 		}
1526 
1527 		/* Check if a controller with this cntlid currently exists. */
1528 		if (nvmf_subsystem_get_ctrlr(subsystem, subsystem->next_cntlid) == NULL) {
1529 			/* Found unused cntlid */
1530 			return subsystem->next_cntlid;
1531 		}
1532 	}
1533 
1534 	/* All valid cntlid values are in use. */
1535 	return 0xFFFF;
1536 }
1537 
1538 int
1539 nvmf_subsystem_add_ctrlr(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *ctrlr)
1540 {
1541 	ctrlr->cntlid = nvmf_subsystem_gen_cntlid(subsystem);
1542 	if (ctrlr->cntlid == 0xFFFF) {
1543 		/* Unable to get a cntlid */
1544 		SPDK_ERRLOG("Reached max simultaneous ctrlrs\n");
1545 		return -EBUSY;
1546 	}
1547 
1548 	TAILQ_INSERT_TAIL(&subsystem->ctrlrs, ctrlr, link);
1549 
1550 	return 0;
1551 }
1552 
1553 void
1554 nvmf_subsystem_remove_ctrlr(struct spdk_nvmf_subsystem *subsystem,
1555 			    struct spdk_nvmf_ctrlr *ctrlr)
1556 {
1557 	assert(subsystem == ctrlr->subsys);
1558 	TAILQ_REMOVE(&subsystem->ctrlrs, ctrlr, link);
1559 }
1560 
1561 struct spdk_nvmf_ctrlr *
1562 nvmf_subsystem_get_ctrlr(struct spdk_nvmf_subsystem *subsystem, uint16_t cntlid)
1563 {
1564 	struct spdk_nvmf_ctrlr *ctrlr;
1565 
1566 	TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) {
1567 		if (ctrlr->cntlid == cntlid) {
1568 			return ctrlr;
1569 		}
1570 	}
1571 
1572 	return NULL;
1573 }
1574 
1575 uint32_t
1576 spdk_nvmf_subsystem_get_max_namespaces(const struct spdk_nvmf_subsystem *subsystem)
1577 {
1578 	return subsystem->max_allowed_nsid;
1579 }
1580 
1581 struct _nvmf_ns_registrant {
1582 	uint64_t		rkey;
1583 	char			*host_uuid;
1584 };
1585 
1586 struct _nvmf_ns_registrants {
1587 	size_t				num_regs;
1588 	struct _nvmf_ns_registrant	reg[SPDK_NVMF_MAX_NUM_REGISTRANTS];
1589 };
1590 
1591 struct _nvmf_ns_reservation {
1592 	bool					ptpl_activated;
1593 	enum spdk_nvme_reservation_type		rtype;
1594 	uint64_t				crkey;
1595 	char					*bdev_uuid;
1596 	char					*holder_uuid;
1597 	struct _nvmf_ns_registrants		regs;
1598 };
1599 
1600 static const struct spdk_json_object_decoder nvmf_ns_pr_reg_decoders[] = {
1601 	{"rkey", offsetof(struct _nvmf_ns_registrant, rkey), spdk_json_decode_uint64},
1602 	{"host_uuid", offsetof(struct _nvmf_ns_registrant, host_uuid), spdk_json_decode_string},
1603 };
1604 
1605 static int
1606 nvmf_decode_ns_pr_reg(const struct spdk_json_val *val, void *out)
1607 {
1608 	struct _nvmf_ns_registrant *reg = out;
1609 
1610 	return spdk_json_decode_object(val, nvmf_ns_pr_reg_decoders,
1611 				       SPDK_COUNTOF(nvmf_ns_pr_reg_decoders), reg);
1612 }
1613 
1614 static int
1615 nvmf_decode_ns_pr_regs(const struct spdk_json_val *val, void *out)
1616 {
1617 	struct _nvmf_ns_registrants *regs = out;
1618 
1619 	return spdk_json_decode_array(val, nvmf_decode_ns_pr_reg, regs->reg,
1620 				      SPDK_NVMF_MAX_NUM_REGISTRANTS, &regs->num_regs,
1621 				      sizeof(struct _nvmf_ns_registrant));
1622 }
1623 
1624 static const struct spdk_json_object_decoder nvmf_ns_pr_decoders[] = {
1625 	{"ptpl", offsetof(struct _nvmf_ns_reservation, ptpl_activated), spdk_json_decode_bool, true},
1626 	{"rtype", offsetof(struct _nvmf_ns_reservation, rtype), spdk_json_decode_uint32, true},
1627 	{"crkey", offsetof(struct _nvmf_ns_reservation, crkey), spdk_json_decode_uint64, true},
1628 	{"bdev_uuid", offsetof(struct _nvmf_ns_reservation, bdev_uuid), spdk_json_decode_string},
1629 	{"holder_uuid", offsetof(struct _nvmf_ns_reservation, holder_uuid), spdk_json_decode_string, true},
1630 	{"registrants", offsetof(struct _nvmf_ns_reservation, regs), nvmf_decode_ns_pr_regs},
1631 };
1632 
1633 static int
1634 nvmf_ns_load_reservation(const char *file, struct spdk_nvmf_reservation_info *info)
1635 {
1636 	FILE *fd;
1637 	size_t json_size;
1638 	ssize_t values_cnt, rc;
1639 	void *json = NULL, *end;
1640 	struct spdk_json_val *values = NULL;
1641 	struct _nvmf_ns_reservation res = {};
1642 	uint32_t i;
1643 
1644 	fd = fopen(file, "r");
1645 	/* It's not an error if the file does not exist */
1646 	if (!fd) {
1647 		SPDK_NOTICELOG("File %s does not exist\n", file);
1648 		return -ENOENT;
1649 	}
1650 
1651 	/* Load all persist file contents into a local buffer */
1652 	json = spdk_posix_file_load(fd, &json_size);
1653 	fclose(fd);
1654 	if (!json) {
1655 		SPDK_ERRLOG("Load persit file %s failed\n", file);
1656 		return -ENOMEM;
1657 	}
1658 
1659 	rc = spdk_json_parse(json, json_size, NULL, 0, &end, 0);
1660 	if (rc < 0) {
1661 		SPDK_NOTICELOG("Parsing JSON configuration failed (%zd)\n", rc);
1662 		goto exit;
1663 	}
1664 
1665 	values_cnt = rc;
1666 	values = calloc(values_cnt, sizeof(struct spdk_json_val));
1667 	if (values == NULL) {
1668 		goto exit;
1669 	}
1670 
1671 	rc = spdk_json_parse(json, json_size, values, values_cnt, &end, 0);
1672 	if (rc != values_cnt) {
1673 		SPDK_ERRLOG("Parsing JSON configuration failed (%zd)\n", rc);
1674 		goto exit;
1675 	}
1676 
1677 	/* Decode json */
1678 	if (spdk_json_decode_object(values, nvmf_ns_pr_decoders,
1679 				    SPDK_COUNTOF(nvmf_ns_pr_decoders),
1680 				    &res)) {
1681 		SPDK_ERRLOG("Invalid objects in the persist file %s\n", file);
1682 		rc = -EINVAL;
1683 		goto exit;
1684 	}
1685 
1686 	if (res.regs.num_regs > SPDK_NVMF_MAX_NUM_REGISTRANTS) {
1687 		SPDK_ERRLOG("Can only support up to %u registrants\n", SPDK_NVMF_MAX_NUM_REGISTRANTS);
1688 		rc = -ERANGE;
1689 		goto exit;
1690 	}
1691 
1692 	rc = 0;
1693 	info->ptpl_activated = res.ptpl_activated;
1694 	info->rtype = res.rtype;
1695 	info->crkey = res.crkey;
1696 	snprintf(info->bdev_uuid, sizeof(info->bdev_uuid), "%s", res.bdev_uuid);
1697 	snprintf(info->holder_uuid, sizeof(info->holder_uuid), "%s", res.holder_uuid);
1698 	info->num_regs = res.regs.num_regs;
1699 	for (i = 0; i < res.regs.num_regs; i++) {
1700 		info->registrants[i].rkey = res.regs.reg[i].rkey;
1701 		snprintf(info->registrants[i].host_uuid, sizeof(info->registrants[i].host_uuid), "%s",
1702 			 res.regs.reg[i].host_uuid);
1703 	}
1704 
1705 exit:
1706 	free(json);
1707 	free(values);
1708 	free(res.bdev_uuid);
1709 	free(res.holder_uuid);
1710 	for (i = 0; i < res.regs.num_regs; i++) {
1711 		free(res.regs.reg[i].host_uuid);
1712 	}
1713 
1714 	return rc;
1715 }
1716 
1717 static bool
1718 nvmf_ns_reservation_all_registrants_type(struct spdk_nvmf_ns *ns);
1719 
1720 static int
1721 nvmf_ns_reservation_restore(struct spdk_nvmf_ns *ns, struct spdk_nvmf_reservation_info *info)
1722 {
1723 	uint32_t i;
1724 	struct spdk_nvmf_registrant *reg, *holder = NULL;
1725 	struct spdk_uuid bdev_uuid, holder_uuid;
1726 
1727 	SPDK_DEBUGLOG(SPDK_LOG_NVMF, "NSID %u, PTPL %u, Number of registrants %u\n",
1728 		      ns->nsid, info->ptpl_activated, info->num_regs);
1729 
1730 	/* it's not an error */
1731 	if (!info->ptpl_activated || !info->num_regs) {
1732 		return 0;
1733 	}
1734 
1735 	spdk_uuid_parse(&bdev_uuid, info->bdev_uuid);
1736 	if (spdk_uuid_compare(&bdev_uuid, spdk_bdev_get_uuid(ns->bdev))) {
1737 		SPDK_ERRLOG("Existing bdev UUID is not same with configuration file\n");
1738 		return -EINVAL;
1739 	}
1740 
1741 	ns->crkey = info->crkey;
1742 	ns->rtype = info->rtype;
1743 	ns->ptpl_activated = info->ptpl_activated;
1744 	spdk_uuid_parse(&holder_uuid, info->holder_uuid);
1745 
1746 	SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Bdev UUID %s\n", info->bdev_uuid);
1747 	if (info->rtype) {
1748 		SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Holder UUID %s, RTYPE %u, RKEY 0x%"PRIx64"\n",
1749 			      info->holder_uuid, info->rtype, info->crkey);
1750 	}
1751 
1752 	for (i = 0; i < info->num_regs; i++) {
1753 		reg = calloc(1, sizeof(*reg));
1754 		if (!reg) {
1755 			return -ENOMEM;
1756 		}
1757 		spdk_uuid_parse(&reg->hostid, info->registrants[i].host_uuid);
1758 		reg->rkey = info->registrants[i].rkey;
1759 		TAILQ_INSERT_TAIL(&ns->registrants, reg, link);
1760 		if (!spdk_uuid_compare(&holder_uuid, &reg->hostid)) {
1761 			holder = reg;
1762 		}
1763 		SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Registrant RKEY 0x%"PRIx64", Host UUID %s\n",
1764 			      info->registrants[i].rkey, info->registrants[i].host_uuid);
1765 	}
1766 
1767 	if (nvmf_ns_reservation_all_registrants_type(ns)) {
1768 		ns->holder = TAILQ_FIRST(&ns->registrants);
1769 	} else {
1770 		ns->holder = holder;
1771 	}
1772 
1773 	return 0;
1774 }
1775 
1776 static int
1777 nvmf_ns_json_write_cb(void *cb_ctx, const void *data, size_t size)
1778 {
1779 	char *file = cb_ctx;
1780 	size_t rc;
1781 	FILE *fd;
1782 
1783 	fd = fopen(file, "w");
1784 	if (!fd) {
1785 		SPDK_ERRLOG("Can't open file %s for write\n", file);
1786 		return -ENOENT;
1787 	}
1788 	rc = fwrite(data, 1, size, fd);
1789 	fclose(fd);
1790 
1791 	return rc == size ? 0 : -1;
1792 }
1793 
1794 static int
1795 nvmf_ns_reservation_update(const char *file, struct spdk_nvmf_reservation_info *info)
1796 {
1797 	struct spdk_json_write_ctx *w;
1798 	uint32_t i;
1799 	int rc = 0;
1800 
1801 	w = spdk_json_write_begin(nvmf_ns_json_write_cb, (void *)file, 0);
1802 	if (w == NULL) {
1803 		return -ENOMEM;
1804 	}
1805 	/* clear the configuration file */
1806 	if (!info->ptpl_activated) {
1807 		goto exit;
1808 	}
1809 
1810 	spdk_json_write_object_begin(w);
1811 	spdk_json_write_named_bool(w, "ptpl", info->ptpl_activated);
1812 	spdk_json_write_named_uint32(w, "rtype", info->rtype);
1813 	spdk_json_write_named_uint64(w, "crkey", info->crkey);
1814 	spdk_json_write_named_string(w, "bdev_uuid", info->bdev_uuid);
1815 	spdk_json_write_named_string(w, "holder_uuid", info->holder_uuid);
1816 
1817 	spdk_json_write_named_array_begin(w, "registrants");
1818 	for (i = 0; i < info->num_regs; i++) {
1819 		spdk_json_write_object_begin(w);
1820 		spdk_json_write_named_uint64(w, "rkey", info->registrants[i].rkey);
1821 		spdk_json_write_named_string(w, "host_uuid", info->registrants[i].host_uuid);
1822 		spdk_json_write_object_end(w);
1823 	}
1824 	spdk_json_write_array_end(w);
1825 	spdk_json_write_object_end(w);
1826 
1827 exit:
1828 	rc = spdk_json_write_end(w);
1829 	return rc;
1830 }
1831 
1832 static int
1833 nvmf_ns_update_reservation_info(struct spdk_nvmf_ns *ns)
1834 {
1835 	struct spdk_nvmf_reservation_info info;
1836 	struct spdk_nvmf_registrant *reg, *tmp;
1837 	uint32_t i = 0;
1838 
1839 	assert(ns != NULL);
1840 
1841 	if (!ns->bdev || !ns->ptpl_file) {
1842 		return 0;
1843 	}
1844 
1845 	memset(&info, 0, sizeof(info));
1846 	spdk_uuid_fmt_lower(info.bdev_uuid, sizeof(info.bdev_uuid), spdk_bdev_get_uuid(ns->bdev));
1847 
1848 	if (ns->rtype) {
1849 		info.rtype = ns->rtype;
1850 		info.crkey = ns->crkey;
1851 		if (!nvmf_ns_reservation_all_registrants_type(ns)) {
1852 			assert(ns->holder != NULL);
1853 			spdk_uuid_fmt_lower(info.holder_uuid, sizeof(info.holder_uuid), &ns->holder->hostid);
1854 		}
1855 	}
1856 
1857 	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) {
1858 		spdk_uuid_fmt_lower(info.registrants[i].host_uuid, sizeof(info.registrants[i].host_uuid),
1859 				    &reg->hostid);
1860 		info.registrants[i++].rkey = reg->rkey;
1861 	}
1862 
1863 	info.num_regs = i;
1864 	info.ptpl_activated = ns->ptpl_activated;
1865 
1866 	return nvmf_ns_reservation_update(ns->ptpl_file, &info);
1867 }
1868 
1869 static struct spdk_nvmf_registrant *
1870 nvmf_ns_reservation_get_registrant(struct spdk_nvmf_ns *ns,
1871 				   struct spdk_uuid *uuid)
1872 {
1873 	struct spdk_nvmf_registrant *reg, *tmp;
1874 
1875 	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) {
1876 		if (!spdk_uuid_compare(&reg->hostid, uuid)) {
1877 			return reg;
1878 		}
1879 	}
1880 
1881 	return NULL;
1882 }
1883 
1884 /* Generate reservation notice log to registered HostID controllers */
1885 static void
1886 nvmf_subsystem_gen_ctrlr_notification(struct spdk_nvmf_subsystem *subsystem,
1887 				      struct spdk_nvmf_ns *ns,
1888 				      struct spdk_uuid *hostid_list,
1889 				      uint32_t num_hostid,
1890 				      enum spdk_nvme_reservation_notification_log_page_type type)
1891 {
1892 	struct spdk_nvmf_ctrlr *ctrlr;
1893 	uint32_t i;
1894 
1895 	for (i = 0; i < num_hostid; i++) {
1896 		TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) {
1897 			if (!spdk_uuid_compare(&ctrlr->hostid, &hostid_list[i])) {
1898 				nvmf_ctrlr_reservation_notice_log(ctrlr, ns, type);
1899 			}
1900 		}
1901 	}
1902 }
1903 
1904 /* Get all registrants' hostid other than the controller who issued the command */
1905 static uint32_t
1906 nvmf_ns_reservation_get_all_other_hostid(struct spdk_nvmf_ns *ns,
1907 		struct spdk_uuid *hostid_list,
1908 		uint32_t max_num_hostid,
1909 		struct spdk_uuid *current_hostid)
1910 {
1911 	struct spdk_nvmf_registrant *reg, *tmp;
1912 	uint32_t num_hostid = 0;
1913 
1914 	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) {
1915 		if (spdk_uuid_compare(&reg->hostid, current_hostid)) {
1916 			if (num_hostid == max_num_hostid) {
1917 				assert(false);
1918 				return max_num_hostid;
1919 			}
1920 			hostid_list[num_hostid++] = reg->hostid;
1921 		}
1922 	}
1923 
1924 	return num_hostid;
1925 }
1926 
1927 /* Calculate the unregistered HostID list according to list
1928  * prior to execute preempt command and list after executing
1929  * preempt command.
1930  */
1931 static uint32_t
1932 nvmf_ns_reservation_get_unregistered_hostid(struct spdk_uuid *old_hostid_list,
1933 		uint32_t old_num_hostid,
1934 		struct spdk_uuid *remaining_hostid_list,
1935 		uint32_t remaining_num_hostid)
1936 {
1937 	struct spdk_uuid temp_hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS];
1938 	uint32_t i, j, num_hostid = 0;
1939 	bool found;
1940 
1941 	if (!remaining_num_hostid) {
1942 		return old_num_hostid;
1943 	}
1944 
1945 	for (i = 0; i < old_num_hostid; i++) {
1946 		found = false;
1947 		for (j = 0; j < remaining_num_hostid; j++) {
1948 			if (!spdk_uuid_compare(&old_hostid_list[i], &remaining_hostid_list[j])) {
1949 				found = true;
1950 				break;
1951 			}
1952 		}
1953 		if (!found) {
1954 			spdk_uuid_copy(&temp_hostid_list[num_hostid++], &old_hostid_list[i]);
1955 		}
1956 	}
1957 
1958 	if (num_hostid) {
1959 		memcpy(old_hostid_list, temp_hostid_list, sizeof(struct spdk_uuid) * num_hostid);
1960 	}
1961 
1962 	return num_hostid;
1963 }
1964 
1965 /* current reservation type is all registrants or not */
1966 static bool
1967 nvmf_ns_reservation_all_registrants_type(struct spdk_nvmf_ns *ns)
1968 {
1969 	return (ns->rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS ||
1970 		ns->rtype == SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_ALL_REGS);
1971 }
1972 
1973 /* current registrant is reservation holder or not */
1974 static bool
1975 nvmf_ns_reservation_registrant_is_holder(struct spdk_nvmf_ns *ns,
1976 		struct spdk_nvmf_registrant *reg)
1977 {
1978 	if (!reg) {
1979 		return false;
1980 	}
1981 
1982 	if (nvmf_ns_reservation_all_registrants_type(ns)) {
1983 		return true;
1984 	}
1985 
1986 	return (ns->holder == reg);
1987 }
1988 
1989 static int
1990 nvmf_ns_reservation_add_registrant(struct spdk_nvmf_ns *ns,
1991 				   struct spdk_nvmf_ctrlr *ctrlr,
1992 				   uint64_t nrkey)
1993 {
1994 	struct spdk_nvmf_registrant *reg;
1995 
1996 	reg = calloc(1, sizeof(*reg));
1997 	if (!reg) {
1998 		return -ENOMEM;
1999 	}
2000 
2001 	reg->rkey = nrkey;
2002 	/* set hostid for the registrant */
2003 	spdk_uuid_copy(&reg->hostid, &ctrlr->hostid);
2004 	TAILQ_INSERT_TAIL(&ns->registrants, reg, link);
2005 	ns->gen++;
2006 
2007 	return 0;
2008 }
2009 
2010 static void
2011 nvmf_ns_reservation_release_reservation(struct spdk_nvmf_ns *ns)
2012 {
2013 	ns->rtype = 0;
2014 	ns->crkey = 0;
2015 	ns->holder = NULL;
2016 }
2017 
2018 /* release the reservation if the last registrant was removed */
2019 static void
2020 nvmf_ns_reservation_check_release_on_remove_registrant(struct spdk_nvmf_ns *ns,
2021 		struct spdk_nvmf_registrant *reg)
2022 {
2023 	struct spdk_nvmf_registrant *next_reg;
2024 
2025 	/* no reservation holder */
2026 	if (!ns->holder) {
2027 		assert(ns->rtype == 0);
2028 		return;
2029 	}
2030 
2031 	next_reg = TAILQ_FIRST(&ns->registrants);
2032 	if (next_reg && nvmf_ns_reservation_all_registrants_type(ns)) {
2033 		/* the next valid registrant is the new holder now */
2034 		ns->holder = next_reg;
2035 	} else if (nvmf_ns_reservation_registrant_is_holder(ns, reg)) {
2036 		/* release the reservation */
2037 		nvmf_ns_reservation_release_reservation(ns);
2038 	}
2039 }
2040 
2041 static void
2042 nvmf_ns_reservation_remove_registrant(struct spdk_nvmf_ns *ns,
2043 				      struct spdk_nvmf_registrant *reg)
2044 {
2045 	TAILQ_REMOVE(&ns->registrants, reg, link);
2046 	nvmf_ns_reservation_check_release_on_remove_registrant(ns, reg);
2047 	free(reg);
2048 	ns->gen++;
2049 	return;
2050 }
2051 
2052 static uint32_t
2053 nvmf_ns_reservation_remove_registrants_by_key(struct spdk_nvmf_ns *ns,
2054 		uint64_t rkey)
2055 {
2056 	struct spdk_nvmf_registrant *reg, *tmp;
2057 	uint32_t count = 0;
2058 
2059 	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) {
2060 		if (reg->rkey == rkey) {
2061 			nvmf_ns_reservation_remove_registrant(ns, reg);
2062 			count++;
2063 		}
2064 	}
2065 	return count;
2066 }
2067 
2068 static uint32_t
2069 nvmf_ns_reservation_remove_all_other_registrants(struct spdk_nvmf_ns *ns,
2070 		struct spdk_nvmf_registrant *reg)
2071 {
2072 	struct spdk_nvmf_registrant *reg_tmp, *reg_tmp2;
2073 	uint32_t count = 0;
2074 
2075 	TAILQ_FOREACH_SAFE(reg_tmp, &ns->registrants, link, reg_tmp2) {
2076 		if (reg_tmp != reg) {
2077 			nvmf_ns_reservation_remove_registrant(ns, reg_tmp);
2078 			count++;
2079 		}
2080 	}
2081 	return count;
2082 }
2083 
2084 static uint32_t
2085 nvmf_ns_reservation_clear_all_registrants(struct spdk_nvmf_ns *ns)
2086 {
2087 	struct spdk_nvmf_registrant *reg, *reg_tmp;
2088 	uint32_t count = 0;
2089 
2090 	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, reg_tmp) {
2091 		nvmf_ns_reservation_remove_registrant(ns, reg);
2092 		count++;
2093 	}
2094 	return count;
2095 }
2096 
2097 static void
2098 nvmf_ns_reservation_acquire_reservation(struct spdk_nvmf_ns *ns, uint64_t rkey,
2099 					enum spdk_nvme_reservation_type rtype,
2100 					struct spdk_nvmf_registrant *holder)
2101 {
2102 	ns->rtype = rtype;
2103 	ns->crkey = rkey;
2104 	assert(ns->holder == NULL);
2105 	ns->holder = holder;
2106 }
2107 
2108 static bool
2109 nvmf_ns_reservation_register(struct spdk_nvmf_ns *ns,
2110 			     struct spdk_nvmf_ctrlr *ctrlr,
2111 			     struct spdk_nvmf_request *req)
2112 {
2113 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
2114 	uint8_t rrega, iekey, cptpl, rtype;
2115 	struct spdk_nvme_reservation_register_data key;
2116 	struct spdk_nvmf_registrant *reg;
2117 	uint8_t status = SPDK_NVME_SC_SUCCESS;
2118 	bool update_sgroup = false;
2119 	struct spdk_uuid hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS];
2120 	uint32_t num_hostid = 0;
2121 	int rc;
2122 
2123 	rrega = cmd->cdw10_bits.resv_register.rrega;
2124 	iekey = cmd->cdw10_bits.resv_register.iekey;
2125 	cptpl = cmd->cdw10_bits.resv_register.cptpl;
2126 
2127 	if (req->data && req->length >= sizeof(key)) {
2128 		memcpy(&key, req->data, sizeof(key));
2129 	} else {
2130 		SPDK_ERRLOG("No key provided. Failing request.\n");
2131 		status = SPDK_NVME_SC_INVALID_FIELD;
2132 		goto exit;
2133 	}
2134 
2135 	SPDK_DEBUGLOG(SPDK_LOG_NVMF, "REGISTER: RREGA %u, IEKEY %u, CPTPL %u, "
2136 		      "NRKEY 0x%"PRIx64", NRKEY 0x%"PRIx64"\n",
2137 		      rrega, iekey, cptpl, key.crkey, key.nrkey);
2138 
2139 	if (cptpl == SPDK_NVME_RESERVE_PTPL_CLEAR_POWER_ON) {
2140 		/* Ture to OFF state, and need to be updated in the configuration file */
2141 		if (ns->ptpl_activated) {
2142 			ns->ptpl_activated = 0;
2143 			update_sgroup = true;
2144 		}
2145 	} else if (cptpl == SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS) {
2146 		if (ns->ptpl_file == NULL) {
2147 			status = SPDK_NVME_SC_INVALID_FIELD;
2148 			goto exit;
2149 		} else if (ns->ptpl_activated == 0) {
2150 			ns->ptpl_activated = 1;
2151 			update_sgroup = true;
2152 		}
2153 	}
2154 
2155 	/* current Host Identifier has registrant or not */
2156 	reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid);
2157 
2158 	switch (rrega) {
2159 	case SPDK_NVME_RESERVE_REGISTER_KEY:
2160 		if (!reg) {
2161 			/* register new controller */
2162 			if (key.nrkey == 0) {
2163 				SPDK_ERRLOG("Can't register zeroed new key\n");
2164 				status = SPDK_NVME_SC_INVALID_FIELD;
2165 				goto exit;
2166 			}
2167 			rc = nvmf_ns_reservation_add_registrant(ns, ctrlr, key.nrkey);
2168 			if (rc < 0) {
2169 				status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
2170 				goto exit;
2171 			}
2172 			update_sgroup = true;
2173 		} else {
2174 			/* register with same key is not an error */
2175 			if (reg->rkey != key.nrkey) {
2176 				SPDK_ERRLOG("The same host already register a "
2177 					    "key with 0x%"PRIx64"\n",
2178 					    reg->rkey);
2179 				status = SPDK_NVME_SC_RESERVATION_CONFLICT;
2180 				goto exit;
2181 			}
2182 		}
2183 		break;
2184 	case SPDK_NVME_RESERVE_UNREGISTER_KEY:
2185 		if (!reg || (!iekey && reg->rkey != key.crkey)) {
2186 			SPDK_ERRLOG("No registrant or current key doesn't match "
2187 				    "with existing registrant key\n");
2188 			status = SPDK_NVME_SC_RESERVATION_CONFLICT;
2189 			goto exit;
2190 		}
2191 
2192 		rtype = ns->rtype;
2193 		num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, hostid_list,
2194 				SPDK_NVMF_MAX_NUM_REGISTRANTS,
2195 				&ctrlr->hostid);
2196 
2197 		nvmf_ns_reservation_remove_registrant(ns, reg);
2198 
2199 		if (!ns->rtype && num_hostid && (rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY ||
2200 						 rtype == SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY)) {
2201 			nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns,
2202 							      hostid_list,
2203 							      num_hostid,
2204 							      SPDK_NVME_RESERVATION_RELEASED);
2205 		}
2206 		update_sgroup = true;
2207 		break;
2208 	case SPDK_NVME_RESERVE_REPLACE_KEY:
2209 		if (!reg || (!iekey && reg->rkey != key.crkey)) {
2210 			SPDK_ERRLOG("No registrant or current key doesn't match "
2211 				    "with existing registrant key\n");
2212 			status = SPDK_NVME_SC_RESERVATION_CONFLICT;
2213 			goto exit;
2214 		}
2215 		if (key.nrkey == 0) {
2216 			SPDK_ERRLOG("Can't register zeroed new key\n");
2217 			status = SPDK_NVME_SC_INVALID_FIELD;
2218 			goto exit;
2219 		}
2220 		reg->rkey = key.nrkey;
2221 		update_sgroup = true;
2222 		break;
2223 	default:
2224 		status = SPDK_NVME_SC_INVALID_FIELD;
2225 		goto exit;
2226 	}
2227 
2228 exit:
2229 	if (update_sgroup) {
2230 		rc = nvmf_ns_update_reservation_info(ns);
2231 		if (rc != 0) {
2232 			status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
2233 		}
2234 	}
2235 	req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC;
2236 	req->rsp->nvme_cpl.status.sc = status;
2237 	return update_sgroup;
2238 }
2239 
2240 static bool
2241 nvmf_ns_reservation_acquire(struct spdk_nvmf_ns *ns,
2242 			    struct spdk_nvmf_ctrlr *ctrlr,
2243 			    struct spdk_nvmf_request *req)
2244 {
2245 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
2246 	uint8_t racqa, iekey, rtype;
2247 	struct spdk_nvme_reservation_acquire_data key;
2248 	struct spdk_nvmf_registrant *reg;
2249 	bool all_regs = false;
2250 	uint32_t count = 0;
2251 	bool update_sgroup = true;
2252 	struct spdk_uuid hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS];
2253 	uint32_t num_hostid = 0;
2254 	struct spdk_uuid new_hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS];
2255 	uint32_t new_num_hostid = 0;
2256 	bool reservation_released = false;
2257 	uint8_t status = SPDK_NVME_SC_SUCCESS;
2258 
2259 	racqa = cmd->cdw10_bits.resv_acquire.racqa;
2260 	iekey = cmd->cdw10_bits.resv_acquire.iekey;
2261 	rtype = cmd->cdw10_bits.resv_acquire.rtype;
2262 
2263 	if (req->data && req->length >= sizeof(key)) {
2264 		memcpy(&key, req->data, sizeof(key));
2265 	} else {
2266 		SPDK_ERRLOG("No key provided. Failing request.\n");
2267 		status = SPDK_NVME_SC_INVALID_FIELD;
2268 		goto exit;
2269 	}
2270 
2271 	SPDK_DEBUGLOG(SPDK_LOG_NVMF, "ACQUIRE: RACQA %u, IEKEY %u, RTYPE %u, "
2272 		      "NRKEY 0x%"PRIx64", PRKEY 0x%"PRIx64"\n",
2273 		      racqa, iekey, rtype, key.crkey, key.prkey);
2274 
2275 	if (iekey || rtype > SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_ALL_REGS) {
2276 		SPDK_ERRLOG("Ignore existing key field set to 1\n");
2277 		status = SPDK_NVME_SC_INVALID_FIELD;
2278 		update_sgroup = false;
2279 		goto exit;
2280 	}
2281 
2282 	reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid);
2283 	/* must be registrant and CRKEY must match */
2284 	if (!reg || reg->rkey != key.crkey) {
2285 		SPDK_ERRLOG("No registrant or current key doesn't match "
2286 			    "with existing registrant key\n");
2287 		status = SPDK_NVME_SC_RESERVATION_CONFLICT;
2288 		update_sgroup = false;
2289 		goto exit;
2290 	}
2291 
2292 	all_regs = nvmf_ns_reservation_all_registrants_type(ns);
2293 
2294 	switch (racqa) {
2295 	case SPDK_NVME_RESERVE_ACQUIRE:
2296 		/* it's not an error for the holder to acquire same reservation type again */
2297 		if (nvmf_ns_reservation_registrant_is_holder(ns, reg) && ns->rtype == rtype) {
2298 			/* do nothing */
2299 			update_sgroup = false;
2300 		} else if (ns->holder == NULL) {
2301 			/* fisrt time to acquire the reservation */
2302 			nvmf_ns_reservation_acquire_reservation(ns, key.crkey, rtype, reg);
2303 		} else {
2304 			SPDK_ERRLOG("Invalid rtype or current registrant is not holder\n");
2305 			status = SPDK_NVME_SC_RESERVATION_CONFLICT;
2306 			update_sgroup = false;
2307 			goto exit;
2308 		}
2309 		break;
2310 	case SPDK_NVME_RESERVE_PREEMPT:
2311 		/* no reservation holder */
2312 		if (!ns->holder) {
2313 			/* unregister with PRKEY */
2314 			nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey);
2315 			break;
2316 		}
2317 		num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, hostid_list,
2318 				SPDK_NVMF_MAX_NUM_REGISTRANTS,
2319 				&ctrlr->hostid);
2320 
2321 		/* only 1 reservation holder and reservation key is valid */
2322 		if (!all_regs) {
2323 			/* preempt itself */
2324 			if (nvmf_ns_reservation_registrant_is_holder(ns, reg) &&
2325 			    ns->crkey == key.prkey) {
2326 				ns->rtype = rtype;
2327 				reservation_released = true;
2328 				break;
2329 			}
2330 
2331 			if (ns->crkey == key.prkey) {
2332 				nvmf_ns_reservation_remove_registrant(ns, ns->holder);
2333 				nvmf_ns_reservation_acquire_reservation(ns, key.crkey, rtype, reg);
2334 				reservation_released = true;
2335 			} else if (key.prkey != 0) {
2336 				nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey);
2337 			} else {
2338 				/* PRKEY is zero */
2339 				SPDK_ERRLOG("Current PRKEY is zero\n");
2340 				status = SPDK_NVME_SC_RESERVATION_CONFLICT;
2341 				update_sgroup = false;
2342 				goto exit;
2343 			}
2344 		} else {
2345 			/* release all other registrants except for the current one */
2346 			if (key.prkey == 0) {
2347 				nvmf_ns_reservation_remove_all_other_registrants(ns, reg);
2348 				assert(ns->holder == reg);
2349 			} else {
2350 				count = nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey);
2351 				if (count == 0) {
2352 					SPDK_ERRLOG("PRKEY doesn't match any registrant\n");
2353 					status = SPDK_NVME_SC_RESERVATION_CONFLICT;
2354 					update_sgroup = false;
2355 					goto exit;
2356 				}
2357 			}
2358 		}
2359 		break;
2360 	default:
2361 		status = SPDK_NVME_SC_INVALID_FIELD;
2362 		update_sgroup = false;
2363 		break;
2364 	}
2365 
2366 exit:
2367 	if (update_sgroup && racqa == SPDK_NVME_RESERVE_PREEMPT) {
2368 		new_num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, new_hostid_list,
2369 				 SPDK_NVMF_MAX_NUM_REGISTRANTS,
2370 				 &ctrlr->hostid);
2371 		/* Preempt notification occurs on the unregistered controllers
2372 		 * other than the controller who issued the command.
2373 		 */
2374 		num_hostid = nvmf_ns_reservation_get_unregistered_hostid(hostid_list,
2375 				num_hostid,
2376 				new_hostid_list,
2377 				new_num_hostid);
2378 		if (num_hostid) {
2379 			nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns,
2380 							      hostid_list,
2381 							      num_hostid,
2382 							      SPDK_NVME_REGISTRATION_PREEMPTED);
2383 
2384 		}
2385 		/* Reservation released notification occurs on the
2386 		 * controllers which are the remaining registrants other than
2387 		 * the controller who issued the command.
2388 		 */
2389 		if (reservation_released && new_num_hostid) {
2390 			nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns,
2391 							      new_hostid_list,
2392 							      new_num_hostid,
2393 							      SPDK_NVME_RESERVATION_RELEASED);
2394 
2395 		}
2396 	}
2397 	if (update_sgroup && ns->ptpl_activated) {
2398 		if (nvmf_ns_update_reservation_info(ns)) {
2399 			status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
2400 		}
2401 	}
2402 	req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC;
2403 	req->rsp->nvme_cpl.status.sc = status;
2404 	return update_sgroup;
2405 }
2406 
2407 static bool
2408 nvmf_ns_reservation_release(struct spdk_nvmf_ns *ns,
2409 			    struct spdk_nvmf_ctrlr *ctrlr,
2410 			    struct spdk_nvmf_request *req)
2411 {
2412 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
2413 	uint8_t rrela, iekey, rtype;
2414 	struct spdk_nvmf_registrant *reg;
2415 	uint64_t crkey;
2416 	uint8_t status = SPDK_NVME_SC_SUCCESS;
2417 	bool update_sgroup = true;
2418 	struct spdk_uuid hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS];
2419 	uint32_t num_hostid = 0;
2420 
2421 	rrela = cmd->cdw10_bits.resv_release.rrela;
2422 	iekey = cmd->cdw10_bits.resv_release.iekey;
2423 	rtype = cmd->cdw10_bits.resv_release.rtype;
2424 
2425 	if (req->data && req->length >= sizeof(crkey)) {
2426 		memcpy(&crkey, req->data, sizeof(crkey));
2427 	} else {
2428 		SPDK_ERRLOG("No key provided. Failing request.\n");
2429 		status = SPDK_NVME_SC_INVALID_FIELD;
2430 		goto exit;
2431 	}
2432 
2433 	SPDK_DEBUGLOG(SPDK_LOG_NVMF, "RELEASE: RRELA %u, IEKEY %u, RTYPE %u, "
2434 		      "CRKEY 0x%"PRIx64"\n",  rrela, iekey, rtype, crkey);
2435 
2436 	if (iekey) {
2437 		SPDK_ERRLOG("Ignore existing key field set to 1\n");
2438 		status = SPDK_NVME_SC_INVALID_FIELD;
2439 		update_sgroup = false;
2440 		goto exit;
2441 	}
2442 
2443 	reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid);
2444 	if (!reg || reg->rkey != crkey) {
2445 		SPDK_ERRLOG("No registrant or current key doesn't match "
2446 			    "with existing registrant key\n");
2447 		status = SPDK_NVME_SC_RESERVATION_CONFLICT;
2448 		update_sgroup = false;
2449 		goto exit;
2450 	}
2451 
2452 	num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, hostid_list,
2453 			SPDK_NVMF_MAX_NUM_REGISTRANTS,
2454 			&ctrlr->hostid);
2455 
2456 	switch (rrela) {
2457 	case SPDK_NVME_RESERVE_RELEASE:
2458 		if (!ns->holder) {
2459 			SPDK_DEBUGLOG(SPDK_LOG_NVMF, "RELEASE: no holder\n");
2460 			update_sgroup = false;
2461 			goto exit;
2462 		}
2463 		if (ns->rtype != rtype) {
2464 			SPDK_ERRLOG("Type doesn't match\n");
2465 			status = SPDK_NVME_SC_INVALID_FIELD;
2466 			update_sgroup = false;
2467 			goto exit;
2468 		}
2469 		if (!nvmf_ns_reservation_registrant_is_holder(ns, reg)) {
2470 			/* not the reservation holder, this isn't an error */
2471 			update_sgroup = false;
2472 			goto exit;
2473 		}
2474 
2475 		rtype = ns->rtype;
2476 		nvmf_ns_reservation_release_reservation(ns);
2477 
2478 		if (num_hostid && rtype != SPDK_NVME_RESERVE_WRITE_EXCLUSIVE &&
2479 		    rtype != SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS) {
2480 			nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns,
2481 							      hostid_list,
2482 							      num_hostid,
2483 							      SPDK_NVME_RESERVATION_RELEASED);
2484 		}
2485 		break;
2486 	case SPDK_NVME_RESERVE_CLEAR:
2487 		nvmf_ns_reservation_clear_all_registrants(ns);
2488 		if (num_hostid) {
2489 			nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns,
2490 							      hostid_list,
2491 							      num_hostid,
2492 							      SPDK_NVME_RESERVATION_PREEMPTED);
2493 		}
2494 		break;
2495 	default:
2496 		status = SPDK_NVME_SC_INVALID_FIELD;
2497 		update_sgroup = false;
2498 		goto exit;
2499 	}
2500 
2501 exit:
2502 	if (update_sgroup && ns->ptpl_activated) {
2503 		if (nvmf_ns_update_reservation_info(ns)) {
2504 			status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
2505 		}
2506 	}
2507 	req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC;
2508 	req->rsp->nvme_cpl.status.sc = status;
2509 	return update_sgroup;
2510 }
2511 
2512 static void
2513 nvmf_ns_reservation_report(struct spdk_nvmf_ns *ns,
2514 			   struct spdk_nvmf_ctrlr *ctrlr,
2515 			   struct spdk_nvmf_request *req)
2516 {
2517 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
2518 	struct spdk_nvmf_subsystem *subsystem = ctrlr->subsys;
2519 	struct spdk_nvmf_ctrlr *ctrlr_tmp;
2520 	struct spdk_nvmf_registrant *reg, *tmp;
2521 	struct spdk_nvme_reservation_status_extended_data *status_data;
2522 	struct spdk_nvme_registered_ctrlr_extended_data *ctrlr_data;
2523 	uint8_t *payload;
2524 	uint32_t len, count = 0;
2525 	uint32_t regctl = 0;
2526 	uint8_t status = SPDK_NVME_SC_SUCCESS;
2527 
2528 	if (req->data == NULL) {
2529 		SPDK_ERRLOG("No data transfer specified for request. "
2530 			    " Unable to transfer back response.\n");
2531 		status = SPDK_NVME_SC_INVALID_FIELD;
2532 		goto exit;
2533 	}
2534 
2535 	if (!cmd->cdw11_bits.resv_report.eds) {
2536 		SPDK_ERRLOG("NVMeoF uses extended controller data structure, "
2537 			    "please set EDS bit in cdw11 and try again\n");
2538 		status = SPDK_NVME_SC_HOSTID_INCONSISTENT_FORMAT;
2539 		goto exit;
2540 	}
2541 
2542 	/* Get number of registerd controllers, one Host may have more than
2543 	 * one controller based on different ports.
2544 	 */
2545 	TAILQ_FOREACH(ctrlr_tmp, &subsystem->ctrlrs, link) {
2546 		reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr_tmp->hostid);
2547 		if (reg) {
2548 			regctl++;
2549 		}
2550 	}
2551 
2552 	len = sizeof(*status_data) + sizeof(*ctrlr_data) * regctl;
2553 	payload = calloc(1, len);
2554 	if (!payload) {
2555 		status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
2556 		goto exit;
2557 	}
2558 
2559 	status_data = (struct spdk_nvme_reservation_status_extended_data *)payload;
2560 	status_data->data.gen = ns->gen;
2561 	status_data->data.rtype = ns->rtype;
2562 	status_data->data.regctl = regctl;
2563 	status_data->data.ptpls = ns->ptpl_activated;
2564 
2565 	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) {
2566 		assert(count <= regctl);
2567 		ctrlr_data = (struct spdk_nvme_registered_ctrlr_extended_data *)
2568 			     (payload + sizeof(*status_data) + sizeof(*ctrlr_data) * count);
2569 		/* Set to 0xffffh for dynamic controller */
2570 		ctrlr_data->cntlid = 0xffff;
2571 		ctrlr_data->rcsts.status = (ns->holder == reg) ? true : false;
2572 		ctrlr_data->rkey = reg->rkey;
2573 		spdk_uuid_copy((struct spdk_uuid *)ctrlr_data->hostid, &reg->hostid);
2574 		count++;
2575 	}
2576 
2577 	memcpy(req->data, payload, spdk_min(len, (cmd->cdw10 + 1) * sizeof(uint32_t)));
2578 	free(payload);
2579 
2580 exit:
2581 	req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC;
2582 	req->rsp->nvme_cpl.status.sc = status;
2583 	return;
2584 }
2585 
2586 static void
2587 nvmf_ns_reservation_complete(void *ctx)
2588 {
2589 	struct spdk_nvmf_request *req = ctx;
2590 
2591 	spdk_nvmf_request_complete(req);
2592 }
2593 
2594 static void
2595 _nvmf_ns_reservation_update_done(struct spdk_nvmf_subsystem *subsystem,
2596 				 void *cb_arg, int status)
2597 {
2598 	struct spdk_nvmf_request *req = (struct spdk_nvmf_request *)cb_arg;
2599 	struct spdk_nvmf_poll_group *group = req->qpair->group;
2600 
2601 	spdk_thread_send_msg(group->thread, nvmf_ns_reservation_complete, req);
2602 }
2603 
2604 void
2605 nvmf_ns_reservation_request(void *ctx)
2606 {
2607 	struct spdk_nvmf_request *req = (struct spdk_nvmf_request *)ctx;
2608 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
2609 	struct spdk_nvmf_ctrlr *ctrlr = req->qpair->ctrlr;
2610 	struct subsystem_update_ns_ctx *update_ctx;
2611 	uint32_t nsid;
2612 	struct spdk_nvmf_ns *ns;
2613 	bool update_sgroup = false;
2614 
2615 	nsid = cmd->nsid;
2616 	ns = _nvmf_subsystem_get_ns(ctrlr->subsys, nsid);
2617 	assert(ns != NULL);
2618 
2619 	switch (cmd->opc) {
2620 	case SPDK_NVME_OPC_RESERVATION_REGISTER:
2621 		update_sgroup = nvmf_ns_reservation_register(ns, ctrlr, req);
2622 		break;
2623 	case SPDK_NVME_OPC_RESERVATION_ACQUIRE:
2624 		update_sgroup = nvmf_ns_reservation_acquire(ns, ctrlr, req);
2625 		break;
2626 	case SPDK_NVME_OPC_RESERVATION_RELEASE:
2627 		update_sgroup = nvmf_ns_reservation_release(ns, ctrlr, req);
2628 		break;
2629 	case SPDK_NVME_OPC_RESERVATION_REPORT:
2630 		nvmf_ns_reservation_report(ns, ctrlr, req);
2631 		break;
2632 	default:
2633 		break;
2634 	}
2635 
2636 	/* update reservation information to subsystem's poll group */
2637 	if (update_sgroup) {
2638 		update_ctx = calloc(1, sizeof(*update_ctx));
2639 		if (update_ctx == NULL) {
2640 			SPDK_ERRLOG("Can't alloc subsystem poll group update context\n");
2641 			goto update_done;
2642 		}
2643 		update_ctx->subsystem = ctrlr->subsys;
2644 		update_ctx->cb_fn = _nvmf_ns_reservation_update_done;
2645 		update_ctx->cb_arg = req;
2646 
2647 		nvmf_subsystem_update_ns(ctrlr->subsys, subsystem_update_ns_done, update_ctx);
2648 		return;
2649 	}
2650 
2651 update_done:
2652 	_nvmf_ns_reservation_update_done(ctrlr->subsys, (void *)req, 0);
2653 }
2654 
2655 int
2656 spdk_nvmf_subsystem_set_ana_reporting(struct spdk_nvmf_subsystem *subsystem,
2657 				      bool ana_reporting)
2658 {
2659 	if (subsystem->state != SPDK_NVMF_SUBSYSTEM_INACTIVE) {
2660 		return -EAGAIN;
2661 	}
2662 
2663 	subsystem->flags.ana_reporting = ana_reporting;
2664 
2665 	return 0;
2666 }
2667 
2668 struct subsystem_listener_update_ctx {
2669 	struct spdk_nvmf_subsystem_listener *listener;
2670 
2671 	spdk_nvmf_tgt_subsystem_listen_done_fn cb_fn;
2672 	void *cb_arg;
2673 };
2674 
2675 static void
2676 subsystem_listener_update_done(struct spdk_io_channel_iter *i, int status)
2677 {
2678 	struct subsystem_listener_update_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
2679 
2680 	if (ctx->cb_fn) {
2681 		ctx->cb_fn(ctx->cb_arg, status);
2682 	}
2683 	free(ctx);
2684 }
2685 
2686 static void
2687 subsystem_listener_update_on_pg(struct spdk_io_channel_iter *i)
2688 {
2689 	struct subsystem_listener_update_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
2690 	struct spdk_nvmf_subsystem_listener *listener;
2691 	struct spdk_nvmf_poll_group *group;
2692 	struct spdk_nvmf_ctrlr *ctrlr;
2693 
2694 	listener = ctx->listener;
2695 	group = spdk_io_channel_get_ctx(spdk_io_channel_iter_get_channel(i));
2696 
2697 	TAILQ_FOREACH(ctrlr, &listener->subsystem->ctrlrs, link) {
2698 		if (ctrlr->admin_qpair->group == group && ctrlr->listener == listener) {
2699 			nvmf_ctrlr_async_event_ana_change_notice(ctrlr);
2700 		}
2701 	}
2702 
2703 	spdk_for_each_channel_continue(i, 0);
2704 }
2705 
2706 void
2707 nvmf_subsystem_set_ana_state(struct spdk_nvmf_subsystem *subsystem,
2708 			     const struct spdk_nvme_transport_id *trid,
2709 			     enum spdk_nvme_ana_state ana_state,
2710 			     spdk_nvmf_tgt_subsystem_listen_done_fn cb_fn, void *cb_arg)
2711 {
2712 	struct spdk_nvmf_subsystem_listener *listener;
2713 	struct subsystem_listener_update_ctx *ctx;
2714 
2715 	assert(cb_fn != NULL);
2716 	assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
2717 	       subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED);
2718 
2719 	if (!subsystem->flags.ana_reporting) {
2720 		SPDK_ERRLOG("ANA reporting is disabled\n");
2721 		cb_fn(cb_arg, -EINVAL);
2722 		return;
2723 	}
2724 
2725 	/* ANA Change state is not used, ANA Persistent Loss state
2726 	 * is not supported yet.
2727 	 */
2728 	if (!(ana_state == SPDK_NVME_ANA_OPTIMIZED_STATE ||
2729 	      ana_state == SPDK_NVME_ANA_NON_OPTIMIZED_STATE ||
2730 	      ana_state == SPDK_NVME_ANA_INACCESSIBLE_STATE)) {
2731 		SPDK_ERRLOG("ANA state %d is not supported\n", ana_state);
2732 		cb_fn(cb_arg, -ENOTSUP);
2733 		return;
2734 	}
2735 
2736 	listener = nvmf_subsystem_find_listener(subsystem, trid);
2737 	if (!listener) {
2738 		SPDK_ERRLOG("Unable to find listener.\n");
2739 		cb_fn(cb_arg, -EINVAL);
2740 		return;
2741 	}
2742 
2743 	if (listener->ana_state == ana_state) {
2744 		cb_fn(cb_arg, 0);
2745 		return;
2746 	}
2747 
2748 	ctx = calloc(1, sizeof(*ctx));
2749 	if (!ctx) {
2750 		SPDK_ERRLOG("Unable to allocate context\n");
2751 		cb_fn(cb_arg, -ENOMEM);
2752 		return;
2753 	}
2754 
2755 	listener->ana_state = ana_state;
2756 	listener->ana_state_change_count++;
2757 
2758 	ctx->listener = listener;
2759 	ctx->cb_fn = cb_fn;
2760 	ctx->cb_arg = cb_arg;
2761 
2762 	spdk_for_each_channel(subsystem->tgt,
2763 			      subsystem_listener_update_on_pg,
2764 			      ctx,
2765 			      subsystem_listener_update_done);
2766 }
2767