xref: /spdk/lib/nvmf/subsystem.c (revision b43c2605f17c995370bc9629019bc73dc4324d45)
1  /*   SPDX-License-Identifier: BSD-3-Clause
2   *   Copyright (C) 2016 Intel Corporation. All rights reserved.
3   *   Copyright (c) 2019 Mellanox Technologies LTD. All rights reserved.
4   *   Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
5   */
6  
7  #include "spdk/stdinc.h"
8  
9  #include "nvmf_internal.h"
10  #include "transport.h"
11  
12  #include "spdk/assert.h"
13  #include "spdk/likely.h"
14  #include "spdk/string.h"
15  #include "spdk/trace.h"
16  #include "spdk/nvmf_spec.h"
17  #include "spdk/uuid.h"
18  #include "spdk/json.h"
19  #include "spdk/file.h"
20  #include "spdk/bit_array.h"
21  #include "spdk/bdev.h"
22  
23  #define __SPDK_BDEV_MODULE_ONLY
24  #include "spdk/bdev_module.h"
25  #include "spdk/log.h"
26  #include "spdk_internal/utf.h"
27  #include "spdk_internal/usdt.h"
28  
29  #define MODEL_NUMBER_DEFAULT "SPDK bdev Controller"
30  #define NVMF_SUBSYSTEM_DEFAULT_NAMESPACES 32
31  
32  /*
33   * States for parsing valid domains in NQNs according to RFC 1034
34   */
35  enum spdk_nvmf_nqn_domain_states {
36  	/* First character of a domain must be a letter */
37  	SPDK_NVMF_DOMAIN_ACCEPT_LETTER = 0,
38  
39  	/* Subsequent characters can be any of letter, digit, or hyphen */
40  	SPDK_NVMF_DOMAIN_ACCEPT_LDH = 1,
41  
42  	/* A domain label must end with either a letter or digit */
43  	SPDK_NVMF_DOMAIN_ACCEPT_ANY = 2
44  };
45  
46  static int _nvmf_subsystem_destroy(struct spdk_nvmf_subsystem *subsystem);
47  
48  /* Returns true if is a valid ASCII string as defined by the NVMe spec */
49  static bool
50  nvmf_valid_ascii_string(const void *buf, size_t size)
51  {
52  	const uint8_t *str = buf;
53  	size_t i;
54  
55  	for (i = 0; i < size; i++) {
56  		if (str[i] < 0x20 || str[i] > 0x7E) {
57  			return false;
58  		}
59  	}
60  
61  	return true;
62  }
63  
64  bool
65  nvmf_nqn_is_valid(const char *nqn)
66  {
67  	size_t len;
68  	struct spdk_uuid uuid_value;
69  	uint32_t i;
70  	int bytes_consumed;
71  	uint32_t domain_label_length;
72  	char *reverse_domain_end;
73  	uint32_t reverse_domain_end_index;
74  	enum spdk_nvmf_nqn_domain_states domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LETTER;
75  
76  	/* Check for length requirements */
77  	len = strlen(nqn);
78  	if (len > SPDK_NVMF_NQN_MAX_LEN) {
79  		SPDK_ERRLOG("Invalid NQN \"%s\": length %zu > max %d\n", nqn, len, SPDK_NVMF_NQN_MAX_LEN);
80  		return false;
81  	}
82  
83  	/* The nqn must be at least as long as SPDK_NVMF_NQN_MIN_LEN to contain the necessary prefix. */
84  	if (len < SPDK_NVMF_NQN_MIN_LEN) {
85  		SPDK_ERRLOG("Invalid NQN \"%s\": length %zu < min %d\n", nqn, len, SPDK_NVMF_NQN_MIN_LEN);
86  		return false;
87  	}
88  
89  	/* Check for discovery controller nqn */
90  	if (!strcmp(nqn, SPDK_NVMF_DISCOVERY_NQN)) {
91  		return true;
92  	}
93  
94  	/* Check for equality with the generic nqn structure of the form "nqn.2014-08.org.nvmexpress:uuid:11111111-2222-3333-4444-555555555555" */
95  	if (!strncmp(nqn, SPDK_NVMF_NQN_UUID_PRE, SPDK_NVMF_NQN_UUID_PRE_LEN)) {
96  		if (len != SPDK_NVMF_NQN_UUID_PRE_LEN + SPDK_NVMF_UUID_STRING_LEN) {
97  			SPDK_ERRLOG("Invalid NQN \"%s\": uuid is not the correct length\n", nqn);
98  			return false;
99  		}
100  
101  		if (spdk_uuid_parse(&uuid_value, &nqn[SPDK_NVMF_NQN_UUID_PRE_LEN])) {
102  			SPDK_ERRLOG("Invalid NQN \"%s\": uuid is not formatted correctly\n", nqn);
103  			return false;
104  		}
105  		return true;
106  	}
107  
108  	/* If the nqn does not match the uuid structure, the next several checks validate the form "nqn.yyyy-mm.reverse.domain:user-string" */
109  
110  	if (strncmp(nqn, "nqn.", 4) != 0) {
111  		SPDK_ERRLOG("Invalid NQN \"%s\": NQN must begin with \"nqn.\".\n", nqn);
112  		return false;
113  	}
114  
115  	/* Check for yyyy-mm. */
116  	if (!(isdigit(nqn[4]) && isdigit(nqn[5]) && isdigit(nqn[6]) && isdigit(nqn[7]) &&
117  	      nqn[8] == '-' && isdigit(nqn[9]) && isdigit(nqn[10]) && nqn[11] == '.')) {
118  		SPDK_ERRLOG("Invalid date code in NQN \"%s\"\n", nqn);
119  		return false;
120  	}
121  
122  	reverse_domain_end = strchr(nqn, ':');
123  	if (reverse_domain_end != NULL && (reverse_domain_end_index = reverse_domain_end - nqn) < len - 1) {
124  	} else {
125  		SPDK_ERRLOG("Invalid NQN \"%s\". NQN must contain user specified name with a ':' as a prefix.\n",
126  			    nqn);
127  		return false;
128  	}
129  
130  	/* Check for valid reverse domain */
131  	domain_label_length = 0;
132  	for (i = 12; i < reverse_domain_end_index; i++) {
133  		if (domain_label_length > SPDK_DOMAIN_LABEL_MAX_LEN) {
134  			SPDK_ERRLOG("Invalid domain name in NQN \"%s\". At least one Label is too long.\n", nqn);
135  			return false;
136  		}
137  
138  		switch (domain_state) {
139  
140  		case SPDK_NVMF_DOMAIN_ACCEPT_LETTER: {
141  			if (isalpha(nqn[i])) {
142  				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_ANY;
143  				domain_label_length++;
144  				break;
145  			} else {
146  				SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must start with a letter.\n", nqn);
147  				return false;
148  			}
149  		}
150  
151  		case SPDK_NVMF_DOMAIN_ACCEPT_LDH: {
152  			if (isalpha(nqn[i]) || isdigit(nqn[i])) {
153  				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_ANY;
154  				domain_label_length++;
155  				break;
156  			} else if (nqn[i] == '-') {
157  				if (i == reverse_domain_end_index - 1) {
158  					SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must end with an alphanumeric symbol.\n",
159  						    nqn);
160  					return false;
161  				}
162  				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LDH;
163  				domain_label_length++;
164  				break;
165  			} else if (nqn[i] == '.') {
166  				SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must end with an alphanumeric symbol.\n",
167  					    nqn);
168  				return false;
169  			} else {
170  				SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must contain only [a-z,A-Z,0-9,'-','.'].\n",
171  					    nqn);
172  				return false;
173  			}
174  		}
175  
176  		case SPDK_NVMF_DOMAIN_ACCEPT_ANY: {
177  			if (isalpha(nqn[i]) || isdigit(nqn[i])) {
178  				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_ANY;
179  				domain_label_length++;
180  				break;
181  			} else if (nqn[i] == '-') {
182  				if (i == reverse_domain_end_index - 1) {
183  					SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must end with an alphanumeric symbol.\n",
184  						    nqn);
185  					return false;
186  				}
187  				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LDH;
188  				domain_label_length++;
189  				break;
190  			} else if (nqn[i] == '.') {
191  				domain_state = SPDK_NVMF_DOMAIN_ACCEPT_LETTER;
192  				domain_label_length = 0;
193  				break;
194  			} else {
195  				SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must contain only [a-z,A-Z,0-9,'-','.'].\n",
196  					    nqn);
197  				return false;
198  			}
199  		}
200  		}
201  	}
202  
203  	i = reverse_domain_end_index + 1;
204  	while (i < len) {
205  		bytes_consumed = utf8_valid(&nqn[i], &nqn[len]);
206  		if (bytes_consumed <= 0) {
207  			SPDK_ERRLOG("Invalid domain name in NQN \"%s\". Label names must contain only valid utf-8.\n", nqn);
208  			return false;
209  		}
210  
211  		i += bytes_consumed;
212  	}
213  	return true;
214  }
215  
216  static void subsystem_state_change_on_pg(struct spdk_io_channel_iter *i);
217  
218  struct spdk_nvmf_subsystem *
219  spdk_nvmf_subsystem_create(struct spdk_nvmf_tgt *tgt,
220  			   const char *nqn,
221  			   enum spdk_nvmf_subtype type,
222  			   uint32_t num_ns)
223  {
224  	struct spdk_nvmf_subsystem	*subsystem;
225  	uint32_t			sid;
226  
227  	if (spdk_nvmf_tgt_find_subsystem(tgt, nqn)) {
228  		SPDK_ERRLOG("Subsystem NQN '%s' already exists\n", nqn);
229  		return NULL;
230  	}
231  
232  	if (!nvmf_nqn_is_valid(nqn)) {
233  		SPDK_ERRLOG("Subsystem NQN '%s' is invalid\n", nqn);
234  		return NULL;
235  	}
236  
237  	if (type == SPDK_NVMF_SUBTYPE_DISCOVERY_CURRENT ||
238  	    type == SPDK_NVMF_SUBTYPE_DISCOVERY) {
239  		if (num_ns != 0) {
240  			SPDK_ERRLOG("Discovery subsystem cannot have namespaces.\n");
241  			return NULL;
242  		}
243  	} else if (num_ns == 0) {
244  		num_ns = NVMF_SUBSYSTEM_DEFAULT_NAMESPACES;
245  	}
246  
247  	/* Find a free subsystem id (sid) */
248  	sid = spdk_bit_array_find_first_clear(tgt->subsystem_ids, 0);
249  	if (sid == UINT32_MAX) {
250  		SPDK_ERRLOG("No free subsystem IDs are available for subsystem creation\n");
251  		return NULL;
252  	}
253  	subsystem = calloc(1, sizeof(struct spdk_nvmf_subsystem));
254  	if (subsystem == NULL) {
255  		SPDK_ERRLOG("Subsystem memory allocation failed\n");
256  		return NULL;
257  	}
258  
259  	subsystem->thread = spdk_get_thread();
260  	subsystem->state = SPDK_NVMF_SUBSYSTEM_INACTIVE;
261  	subsystem->tgt = tgt;
262  	subsystem->id = sid;
263  	subsystem->subtype = type;
264  	subsystem->max_nsid = num_ns;
265  	subsystem->next_cntlid = 1;
266  	subsystem->min_cntlid = NVMF_MIN_CNTLID;
267  	subsystem->max_cntlid = NVMF_MAX_CNTLID;
268  	snprintf(subsystem->subnqn, sizeof(subsystem->subnqn), "%s", nqn);
269  	pthread_mutex_init(&subsystem->mutex, NULL);
270  	TAILQ_INIT(&subsystem->listeners);
271  	TAILQ_INIT(&subsystem->hosts);
272  	TAILQ_INIT(&subsystem->ctrlrs);
273  	TAILQ_INIT(&subsystem->state_changes);
274  	subsystem->used_listener_ids = spdk_bit_array_create(NVMF_MAX_LISTENERS_PER_SUBSYSTEM);
275  	if (subsystem->used_listener_ids == NULL) {
276  		pthread_mutex_destroy(&subsystem->mutex);
277  		free(subsystem);
278  		SPDK_ERRLOG("Listener id array memory allocation failed\n");
279  		return NULL;
280  	}
281  
282  	if (num_ns != 0) {
283  		subsystem->ns = calloc(num_ns, sizeof(struct spdk_nvmf_ns *));
284  		if (subsystem->ns == NULL) {
285  			SPDK_ERRLOG("Namespace memory allocation failed\n");
286  			pthread_mutex_destroy(&subsystem->mutex);
287  			spdk_bit_array_free(&subsystem->used_listener_ids);
288  			free(subsystem);
289  			return NULL;
290  		}
291  		subsystem->ana_group = calloc(num_ns, sizeof(uint32_t));
292  		if (subsystem->ana_group == NULL) {
293  			SPDK_ERRLOG("ANA group memory allocation failed\n");
294  			pthread_mutex_destroy(&subsystem->mutex);
295  			free(subsystem->ns);
296  			spdk_bit_array_free(&subsystem->used_listener_ids);
297  			free(subsystem);
298  			return NULL;
299  		}
300  	}
301  
302  	memset(subsystem->sn, '0', sizeof(subsystem->sn) - 1);
303  	subsystem->sn[sizeof(subsystem->sn) - 1] = '\0';
304  
305  	snprintf(subsystem->mn, sizeof(subsystem->mn), "%s",
306  		 MODEL_NUMBER_DEFAULT);
307  
308  	spdk_bit_array_set(tgt->subsystem_ids, sid);
309  	RB_INSERT(subsystem_tree, &tgt->subsystems, subsystem);
310  
311  	SPDK_DTRACE_PROBE1(nvmf_subsystem_create, subsystem->subnqn);
312  
313  	return subsystem;
314  }
315  
316  static void
317  nvmf_host_free(struct spdk_nvmf_host *host)
318  {
319  	spdk_keyring_put_key(host->dhchap_key);
320  	spdk_keyring_put_key(host->dhchap_ctrlr_key);
321  	free(host);
322  }
323  
324  /* Must hold subsystem->mutex while calling this function */
325  static void
326  nvmf_subsystem_remove_host(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_host *host)
327  {
328  	TAILQ_REMOVE(&subsystem->hosts, host, link);
329  	nvmf_host_free(host);
330  }
331  
332  static void
333  _nvmf_subsystem_remove_listener(struct spdk_nvmf_subsystem *subsystem,
334  				struct spdk_nvmf_subsystem_listener *listener,
335  				bool stop)
336  {
337  	struct spdk_nvmf_transport *transport;
338  	struct spdk_nvmf_ctrlr *ctrlr;
339  
340  	if (stop) {
341  		transport = spdk_nvmf_tgt_get_transport(subsystem->tgt, listener->trid->trstring);
342  		if (transport != NULL) {
343  			spdk_nvmf_transport_stop_listen(transport, listener->trid);
344  		}
345  	}
346  
347  	TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) {
348  		if (ctrlr->listener == listener) {
349  			ctrlr->listener = NULL;
350  		}
351  	}
352  
353  	TAILQ_REMOVE(&subsystem->listeners, listener, link);
354  	if (spdk_nvmf_subsystem_is_discovery(listener->subsystem)) {
355  		nvmf_tgt_update_mdns_prr(listener->subsystem->tgt);
356  	}
357  	spdk_nvmf_send_discovery_log_notice(listener->subsystem->tgt, NULL);
358  	free(listener->ana_state);
359  	spdk_bit_array_clear(subsystem->used_listener_ids, listener->id);
360  	free(listener->opts.sock_impl);
361  	free(listener);
362  }
363  
364  static void
365  _nvmf_subsystem_destroy_msg(void *cb_arg)
366  {
367  	struct spdk_nvmf_subsystem *subsystem = cb_arg;
368  
369  	_nvmf_subsystem_destroy(subsystem);
370  }
371  
372  static int
373  _nvmf_subsystem_destroy(struct spdk_nvmf_subsystem *subsystem)
374  {
375  	struct nvmf_subsystem_state_change_ctx *ctx;
376  	struct spdk_nvmf_ns		*ns;
377  	nvmf_subsystem_destroy_cb	async_destroy_cb = NULL;
378  	void				*async_destroy_cb_arg = NULL;
379  	int				rc;
380  
381  	if (!TAILQ_EMPTY(&subsystem->ctrlrs)) {
382  		SPDK_DEBUGLOG(nvmf, "subsystem %p %s has active controllers\n", subsystem, subsystem->subnqn);
383  		subsystem->async_destroy = true;
384  		rc = spdk_thread_send_msg(subsystem->thread, _nvmf_subsystem_destroy_msg, subsystem);
385  		if (rc) {
386  			SPDK_ERRLOG("Failed to send thread msg, rc %d\n", rc);
387  			assert(0);
388  			return rc;
389  		}
390  		return -EINPROGRESS;
391  	}
392  
393  	ns = spdk_nvmf_subsystem_get_first_ns(subsystem);
394  	while (ns != NULL) {
395  		struct spdk_nvmf_ns *next_ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns);
396  
397  		spdk_nvmf_subsystem_remove_ns(subsystem, ns->opts.nsid);
398  		ns = next_ns;
399  	}
400  
401  	while ((ctx = TAILQ_FIRST(&subsystem->state_changes))) {
402  		SPDK_WARNLOG("subsystem %s has pending state change requests\n", subsystem->subnqn);
403  		TAILQ_REMOVE(&subsystem->state_changes, ctx, link);
404  		if (ctx->cb_fn != NULL) {
405  			ctx->cb_fn(subsystem, ctx->cb_arg, -ECANCELED);
406  		}
407  		free(ctx);
408  	}
409  
410  	free(subsystem->ns);
411  	free(subsystem->ana_group);
412  
413  	RB_REMOVE(subsystem_tree, &subsystem->tgt->subsystems, subsystem);
414  	assert(spdk_bit_array_get(subsystem->tgt->subsystem_ids, subsystem->id) == true);
415  	spdk_bit_array_clear(subsystem->tgt->subsystem_ids, subsystem->id);
416  
417  	pthread_mutex_destroy(&subsystem->mutex);
418  
419  	spdk_bit_array_free(&subsystem->used_listener_ids);
420  
421  	if (subsystem->async_destroy) {
422  		async_destroy_cb = subsystem->async_destroy_cb;
423  		async_destroy_cb_arg = subsystem->async_destroy_cb_arg;
424  	}
425  
426  	free(subsystem);
427  
428  	if (async_destroy_cb) {
429  		async_destroy_cb(async_destroy_cb_arg);
430  	}
431  
432  	return 0;
433  }
434  
435  static struct spdk_nvmf_ns *
436  _nvmf_subsystem_get_first_zoned_ns(struct spdk_nvmf_subsystem *subsystem)
437  {
438  	struct spdk_nvmf_ns *ns = spdk_nvmf_subsystem_get_first_ns(subsystem);
439  	while (ns != NULL) {
440  		if (ns->csi == SPDK_NVME_CSI_ZNS) {
441  			return ns;
442  		}
443  		ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns);
444  	}
445  	return NULL;
446  }
447  
448  int
449  spdk_nvmf_subsystem_destroy(struct spdk_nvmf_subsystem *subsystem, nvmf_subsystem_destroy_cb cpl_cb,
450  			    void *cpl_cb_arg)
451  {
452  	struct spdk_nvmf_host *host, *host_tmp;
453  	struct spdk_nvmf_transport *transport;
454  
455  	if (!subsystem) {
456  		return -EINVAL;
457  	}
458  
459  	SPDK_DTRACE_PROBE1(nvmf_subsystem_destroy, subsystem->subnqn);
460  
461  	assert(spdk_get_thread() == subsystem->thread);
462  
463  	if (subsystem->state != SPDK_NVMF_SUBSYSTEM_INACTIVE) {
464  		SPDK_ERRLOG("Subsystem can only be destroyed in inactive state, %s state %d\n",
465  			    subsystem->subnqn, subsystem->state);
466  		return -EAGAIN;
467  	}
468  	if (subsystem->destroying) {
469  		SPDK_ERRLOG("Subsystem destruction is already started\n");
470  		assert(0);
471  		return -EALREADY;
472  	}
473  
474  	subsystem->destroying = true;
475  
476  	SPDK_DEBUGLOG(nvmf, "subsystem is %p %s\n", subsystem, subsystem->subnqn);
477  
478  	nvmf_subsystem_remove_all_listeners(subsystem, false);
479  
480  	pthread_mutex_lock(&subsystem->mutex);
481  
482  	TAILQ_FOREACH_SAFE(host, &subsystem->hosts, link, host_tmp) {
483  		for (transport = spdk_nvmf_transport_get_first(subsystem->tgt); transport;
484  		     transport = spdk_nvmf_transport_get_next(transport)) {
485  			if (transport->ops->subsystem_remove_host) {
486  				transport->ops->subsystem_remove_host(transport, subsystem, host->nqn);
487  			}
488  		}
489  		nvmf_subsystem_remove_host(subsystem, host);
490  	}
491  
492  	pthread_mutex_unlock(&subsystem->mutex);
493  
494  	subsystem->async_destroy_cb = cpl_cb;
495  	subsystem->async_destroy_cb_arg = cpl_cb_arg;
496  
497  	return _nvmf_subsystem_destroy(subsystem);
498  }
499  
500  /* we have to use the typedef in the function declaration to appease astyle. */
501  typedef enum spdk_nvmf_subsystem_state spdk_nvmf_subsystem_state_t;
502  
503  static spdk_nvmf_subsystem_state_t
504  nvmf_subsystem_get_intermediate_state(enum spdk_nvmf_subsystem_state current_state,
505  				      enum spdk_nvmf_subsystem_state requested_state)
506  {
507  	switch (requested_state) {
508  	case SPDK_NVMF_SUBSYSTEM_INACTIVE:
509  		return SPDK_NVMF_SUBSYSTEM_DEACTIVATING;
510  	case SPDK_NVMF_SUBSYSTEM_ACTIVE:
511  		if (current_state == SPDK_NVMF_SUBSYSTEM_PAUSED) {
512  			return SPDK_NVMF_SUBSYSTEM_RESUMING;
513  		} else {
514  			return SPDK_NVMF_SUBSYSTEM_ACTIVATING;
515  		}
516  	case SPDK_NVMF_SUBSYSTEM_PAUSED:
517  		return SPDK_NVMF_SUBSYSTEM_PAUSING;
518  	default:
519  		assert(false);
520  		return SPDK_NVMF_SUBSYSTEM_NUM_STATES;
521  	}
522  }
523  
524  static int
525  nvmf_subsystem_set_state(struct spdk_nvmf_subsystem *subsystem,
526  			 enum spdk_nvmf_subsystem_state state)
527  {
528  	enum spdk_nvmf_subsystem_state actual_old_state, expected_old_state;
529  	bool exchanged;
530  
531  	switch (state) {
532  	case SPDK_NVMF_SUBSYSTEM_INACTIVE:
533  		expected_old_state = SPDK_NVMF_SUBSYSTEM_DEACTIVATING;
534  		break;
535  	case SPDK_NVMF_SUBSYSTEM_ACTIVATING:
536  		expected_old_state = SPDK_NVMF_SUBSYSTEM_INACTIVE;
537  		break;
538  	case SPDK_NVMF_SUBSYSTEM_ACTIVE:
539  		expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING;
540  		break;
541  	case SPDK_NVMF_SUBSYSTEM_PAUSING:
542  		expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
543  		break;
544  	case SPDK_NVMF_SUBSYSTEM_PAUSED:
545  		expected_old_state = SPDK_NVMF_SUBSYSTEM_PAUSING;
546  		break;
547  	case SPDK_NVMF_SUBSYSTEM_RESUMING:
548  		expected_old_state = SPDK_NVMF_SUBSYSTEM_PAUSED;
549  		break;
550  	case SPDK_NVMF_SUBSYSTEM_DEACTIVATING:
551  		expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
552  		break;
553  	default:
554  		assert(false);
555  		return -1;
556  	}
557  
558  	actual_old_state = expected_old_state;
559  	exchanged = __atomic_compare_exchange_n(&subsystem->state, &actual_old_state, state, false,
560  						__ATOMIC_RELAXED, __ATOMIC_RELAXED);
561  	if (spdk_unlikely(exchanged == false)) {
562  		if (actual_old_state == SPDK_NVMF_SUBSYSTEM_RESUMING &&
563  		    state == SPDK_NVMF_SUBSYSTEM_ACTIVE) {
564  			expected_old_state = SPDK_NVMF_SUBSYSTEM_RESUMING;
565  		}
566  		/* This is for the case when activating the subsystem fails. */
567  		if (actual_old_state == SPDK_NVMF_SUBSYSTEM_ACTIVATING &&
568  		    state == SPDK_NVMF_SUBSYSTEM_DEACTIVATING) {
569  			expected_old_state = SPDK_NVMF_SUBSYSTEM_ACTIVATING;
570  		}
571  		/* This is for the case when resuming the subsystem fails. */
572  		if (actual_old_state == SPDK_NVMF_SUBSYSTEM_RESUMING &&
573  		    state == SPDK_NVMF_SUBSYSTEM_PAUSING) {
574  			expected_old_state = SPDK_NVMF_SUBSYSTEM_RESUMING;
575  		}
576  		/* This is for the case when stopping paused subsystem */
577  		if (actual_old_state == SPDK_NVMF_SUBSYSTEM_PAUSED &&
578  		    state == SPDK_NVMF_SUBSYSTEM_DEACTIVATING) {
579  			expected_old_state = SPDK_NVMF_SUBSYSTEM_PAUSED;
580  		}
581  		actual_old_state = expected_old_state;
582  		__atomic_compare_exchange_n(&subsystem->state, &actual_old_state, state, false,
583  					    __ATOMIC_RELAXED, __ATOMIC_RELAXED);
584  	}
585  	assert(actual_old_state == expected_old_state);
586  	return actual_old_state - expected_old_state;
587  }
588  
589  static void nvmf_subsystem_do_state_change(struct nvmf_subsystem_state_change_ctx *ctx);
590  
591  static void
592  _nvmf_subsystem_state_change_complete(void *_ctx)
593  {
594  	struct nvmf_subsystem_state_change_ctx *next, *ctx = _ctx;
595  	struct spdk_nvmf_subsystem *subsystem = ctx->subsystem;
596  
597  	pthread_mutex_lock(&subsystem->mutex);
598  	assert(TAILQ_FIRST(&subsystem->state_changes) == ctx);
599  	TAILQ_REMOVE(&subsystem->state_changes, ctx, link);
600  	next = TAILQ_FIRST(&subsystem->state_changes);
601  	pthread_mutex_unlock(&subsystem->mutex);
602  
603  	if (ctx->cb_fn != NULL) {
604  		ctx->cb_fn(subsystem, ctx->cb_arg, ctx->status);
605  	}
606  	free(ctx);
607  
608  	if (next != NULL) {
609  		nvmf_subsystem_do_state_change(next);
610  	}
611  }
612  
613  static void
614  nvmf_subsystem_state_change_complete(struct nvmf_subsystem_state_change_ctx *ctx, int status)
615  {
616  	ctx->status = status;
617  	spdk_thread_exec_msg(ctx->thread, _nvmf_subsystem_state_change_complete, ctx);
618  }
619  
620  static void
621  subsystem_state_change_revert_done(struct spdk_io_channel_iter *i, int status)
622  {
623  	struct nvmf_subsystem_state_change_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
624  
625  	/* Nothing to be done here if the state setting fails, we are just screwed. */
626  	if (nvmf_subsystem_set_state(ctx->subsystem, ctx->requested_state)) {
627  		SPDK_ERRLOG("Unable to revert the subsystem state after operation failure.\n");
628  	}
629  
630  	/* return a failure here. This function only exists in an error path. */
631  	nvmf_subsystem_state_change_complete(ctx, -1);
632  }
633  
634  static void
635  subsystem_state_change_done(struct spdk_io_channel_iter *i, int status)
636  {
637  	struct nvmf_subsystem_state_change_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
638  	enum spdk_nvmf_subsystem_state intermediate_state;
639  
640  	SPDK_DTRACE_PROBE4(nvmf_subsystem_change_state_done, ctx->subsystem->subnqn,
641  			   ctx->requested_state, ctx->original_state, status);
642  
643  	if (status == 0) {
644  		status = nvmf_subsystem_set_state(ctx->subsystem, ctx->requested_state);
645  		if (status) {
646  			status = -1;
647  		}
648  	}
649  
650  	if (status) {
651  		intermediate_state = nvmf_subsystem_get_intermediate_state(ctx->requested_state,
652  				     ctx->original_state);
653  		assert(intermediate_state != SPDK_NVMF_SUBSYSTEM_NUM_STATES);
654  
655  		if (nvmf_subsystem_set_state(ctx->subsystem, intermediate_state)) {
656  			goto out;
657  		}
658  		ctx->requested_state = ctx->original_state;
659  		spdk_for_each_channel(ctx->subsystem->tgt,
660  				      subsystem_state_change_on_pg,
661  				      ctx,
662  				      subsystem_state_change_revert_done);
663  		return;
664  	}
665  
666  out:
667  	nvmf_subsystem_state_change_complete(ctx, status);
668  }
669  
670  static void
671  subsystem_state_change_continue(void *ctx, int status)
672  {
673  	struct spdk_io_channel_iter *i = ctx;
674  	struct nvmf_subsystem_state_change_ctx *_ctx __attribute__((unused));
675  
676  	_ctx = spdk_io_channel_iter_get_ctx(i);
677  	SPDK_DTRACE_PROBE3(nvmf_pg_change_state_done, _ctx->subsystem->subnqn,
678  			   _ctx->requested_state, spdk_thread_get_id(spdk_get_thread()));
679  
680  	spdk_for_each_channel_continue(i, status);
681  }
682  
683  static void
684  subsystem_state_change_on_pg(struct spdk_io_channel_iter *i)
685  {
686  	struct nvmf_subsystem_state_change_ctx *ctx;
687  	struct spdk_io_channel *ch;
688  	struct spdk_nvmf_poll_group *group;
689  
690  	ctx = spdk_io_channel_iter_get_ctx(i);
691  	ch = spdk_io_channel_iter_get_channel(i);
692  	group = spdk_io_channel_get_ctx(ch);
693  
694  	SPDK_DTRACE_PROBE3(nvmf_pg_change_state, ctx->subsystem->subnqn,
695  			   ctx->requested_state, spdk_thread_get_id(spdk_get_thread()));
696  	switch (ctx->requested_state) {
697  	case SPDK_NVMF_SUBSYSTEM_INACTIVE:
698  		nvmf_poll_group_remove_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i);
699  		break;
700  	case SPDK_NVMF_SUBSYSTEM_ACTIVE:
701  		if (ctx->subsystem->state == SPDK_NVMF_SUBSYSTEM_ACTIVATING) {
702  			nvmf_poll_group_add_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i);
703  		} else if (ctx->subsystem->state == SPDK_NVMF_SUBSYSTEM_RESUMING) {
704  			nvmf_poll_group_resume_subsystem(group, ctx->subsystem, subsystem_state_change_continue, i);
705  		}
706  		break;
707  	case SPDK_NVMF_SUBSYSTEM_PAUSED:
708  		nvmf_poll_group_pause_subsystem(group, ctx->subsystem, ctx->nsid, subsystem_state_change_continue,
709  						i);
710  		break;
711  	default:
712  		assert(false);
713  		break;
714  	}
715  }
716  
717  static void
718  nvmf_subsystem_do_state_change(struct nvmf_subsystem_state_change_ctx *ctx)
719  {
720  	struct spdk_nvmf_subsystem *subsystem = ctx->subsystem;
721  	enum spdk_nvmf_subsystem_state intermediate_state;
722  	int rc;
723  
724  	SPDK_DTRACE_PROBE3(nvmf_subsystem_change_state, subsystem->subnqn,
725  			   ctx->requested_state, subsystem->state);
726  
727  	/* If we are already in the requested state, just call the callback immediately. */
728  	if (subsystem->state == ctx->requested_state) {
729  		nvmf_subsystem_state_change_complete(ctx, 0);
730  		return;
731  	}
732  
733  	intermediate_state = nvmf_subsystem_get_intermediate_state(subsystem->state,
734  			     ctx->requested_state);
735  	assert(intermediate_state != SPDK_NVMF_SUBSYSTEM_NUM_STATES);
736  
737  	ctx->original_state = subsystem->state;
738  	rc = nvmf_subsystem_set_state(subsystem, intermediate_state);
739  	if (rc) {
740  		nvmf_subsystem_state_change_complete(ctx, -1);
741  		return;
742  	}
743  
744  	spdk_for_each_channel(subsystem->tgt,
745  			      subsystem_state_change_on_pg,
746  			      ctx,
747  			      subsystem_state_change_done);
748  }
749  
750  
751  static int
752  nvmf_subsystem_state_change(struct spdk_nvmf_subsystem *subsystem,
753  			    uint32_t nsid,
754  			    enum spdk_nvmf_subsystem_state requested_state,
755  			    spdk_nvmf_subsystem_state_change_done cb_fn,
756  			    void *cb_arg)
757  {
758  	struct nvmf_subsystem_state_change_ctx *ctx;
759  	struct spdk_thread *thread;
760  
761  	thread = spdk_get_thread();
762  	if (thread == NULL) {
763  		return -EINVAL;
764  	}
765  
766  	ctx = calloc(1, sizeof(*ctx));
767  	if (!ctx) {
768  		return -ENOMEM;
769  	}
770  
771  	ctx->subsystem = subsystem;
772  	ctx->nsid = nsid;
773  	ctx->requested_state = requested_state;
774  	ctx->cb_fn = cb_fn;
775  	ctx->cb_arg = cb_arg;
776  	ctx->thread = thread;
777  
778  	pthread_mutex_lock(&subsystem->mutex);
779  	TAILQ_INSERT_TAIL(&subsystem->state_changes, ctx, link);
780  	if (ctx != TAILQ_FIRST(&subsystem->state_changes)) {
781  		pthread_mutex_unlock(&subsystem->mutex);
782  		return 0;
783  	}
784  	pthread_mutex_unlock(&subsystem->mutex);
785  
786  	nvmf_subsystem_do_state_change(ctx);
787  
788  	return 0;
789  }
790  
791  int
792  spdk_nvmf_subsystem_start(struct spdk_nvmf_subsystem *subsystem,
793  			  spdk_nvmf_subsystem_state_change_done cb_fn,
794  			  void *cb_arg)
795  {
796  	return nvmf_subsystem_state_change(subsystem, 0, SPDK_NVMF_SUBSYSTEM_ACTIVE, cb_fn, cb_arg);
797  }
798  
799  int
800  spdk_nvmf_subsystem_stop(struct spdk_nvmf_subsystem *subsystem,
801  			 spdk_nvmf_subsystem_state_change_done cb_fn,
802  			 void *cb_arg)
803  {
804  	return nvmf_subsystem_state_change(subsystem, 0, SPDK_NVMF_SUBSYSTEM_INACTIVE, cb_fn, cb_arg);
805  }
806  
807  int
808  spdk_nvmf_subsystem_pause(struct spdk_nvmf_subsystem *subsystem,
809  			  uint32_t nsid,
810  			  spdk_nvmf_subsystem_state_change_done cb_fn,
811  			  void *cb_arg)
812  {
813  	return nvmf_subsystem_state_change(subsystem, nsid, SPDK_NVMF_SUBSYSTEM_PAUSED, cb_fn, cb_arg);
814  }
815  
816  int
817  spdk_nvmf_subsystem_resume(struct spdk_nvmf_subsystem *subsystem,
818  			   spdk_nvmf_subsystem_state_change_done cb_fn,
819  			   void *cb_arg)
820  {
821  	return nvmf_subsystem_state_change(subsystem, 0, SPDK_NVMF_SUBSYSTEM_ACTIVE, cb_fn, cb_arg);
822  }
823  
824  struct spdk_nvmf_subsystem *
825  spdk_nvmf_subsystem_get_first(struct spdk_nvmf_tgt *tgt)
826  {
827  	return RB_MIN(subsystem_tree, &tgt->subsystems);
828  }
829  
830  struct spdk_nvmf_subsystem *
831  spdk_nvmf_subsystem_get_next(struct spdk_nvmf_subsystem *subsystem)
832  {
833  	if (!subsystem) {
834  		return NULL;
835  	}
836  
837  	return RB_NEXT(subsystem_tree, &tgt->subsystems, subsystem);
838  }
839  
840  static int
841  nvmf_ns_add_host(struct spdk_nvmf_ns *ns, const char *hostnqn)
842  {
843  	struct spdk_nvmf_host *host;
844  
845  	host = calloc(1, sizeof(*host));
846  	if (!host) {
847  		return -ENOMEM;
848  	}
849  	snprintf(host->nqn, sizeof(host->nqn), "%s", hostnqn);
850  	TAILQ_INSERT_HEAD(&ns->hosts, host, link);
851  	return 0;
852  }
853  
854  static void
855  nvmf_ns_remove_host(struct spdk_nvmf_ns *ns, struct spdk_nvmf_host *host)
856  {
857  	TAILQ_REMOVE(&ns->hosts, host, link);
858  	free(host);
859  }
860  
861  static void
862  _async_event_ns_notice(void *_ctrlr)
863  {
864  	struct spdk_nvmf_ctrlr *ctrlr = _ctrlr;
865  
866  	nvmf_ctrlr_async_event_ns_notice(ctrlr);
867  }
868  
869  static void
870  send_async_event_ns_notice(struct spdk_nvmf_ctrlr *ctrlr)
871  {
872  	spdk_thread_send_msg(ctrlr->thread, _async_event_ns_notice, ctrlr);
873  }
874  
875  static int
876  nvmf_ns_visible(struct spdk_nvmf_subsystem *subsystem,
877  		uint32_t nsid,
878  		const char *hostnqn,
879  		bool visible)
880  {
881  	struct spdk_nvmf_ns *ns;
882  	struct spdk_nvmf_ctrlr *ctrlr;
883  	struct spdk_nvmf_host *host;
884  	int rc;
885  
886  	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
887  	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
888  		assert(false);
889  		return -1;
890  	}
891  
892  	if (hostnqn == NULL || !nvmf_nqn_is_valid(hostnqn)) {
893  		return -EINVAL;
894  	}
895  
896  	if (nsid == 0 || nsid > subsystem->max_nsid) {
897  		return -EINVAL;
898  	}
899  
900  	ns = subsystem->ns[nsid - 1];
901  	if (!ns) {
902  		return -ENOENT;
903  	}
904  
905  	if (ns->always_visible) {
906  		/* No individual host control */
907  		return -EPERM;
908  	}
909  
910  	/* Save host info to use for any future controllers. */
911  	host = nvmf_ns_find_host(ns, hostnqn);
912  	if (visible && host == NULL) {
913  		rc = nvmf_ns_add_host(ns, hostnqn);
914  		if (rc) {
915  			return rc;
916  		}
917  	} else if (!visible && host != NULL) {
918  		nvmf_ns_remove_host(ns, host);
919  	}
920  
921  	/* Also apply to existing controllers. */
922  	TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) {
923  		if (strcmp(hostnqn, ctrlr->hostnqn) ||
924  		    nvmf_ctrlr_ns_is_visible(ctrlr, nsid) == visible) {
925  			continue;
926  		}
927  		nvmf_ctrlr_ns_set_visible(ctrlr, nsid, visible);
928  		send_async_event_ns_notice(ctrlr);
929  		nvmf_ctrlr_ns_changed(ctrlr, nsid);
930  	}
931  
932  	return 0;
933  }
934  
935  int
936  spdk_nvmf_ns_add_host(struct spdk_nvmf_subsystem *subsystem,
937  		      uint32_t nsid,
938  		      const char *hostnqn,
939  		      uint32_t flags)
940  {
941  	SPDK_DTRACE_PROBE4(spdk_nvmf_ns_add_host,
942  			   subsystem->subnqn,
943  			   nsid,
944  			   hostnqn,
945  			   flags);
946  	return nvmf_ns_visible(subsystem, nsid, hostnqn, true);
947  }
948  
949  int
950  spdk_nvmf_ns_remove_host(struct spdk_nvmf_subsystem *subsystem,
951  			 uint32_t nsid,
952  			 const char *hostnqn,
953  			 uint32_t flags)
954  {
955  	SPDK_DTRACE_PROBE4(spdk_nvmf_ns_remove_host,
956  			   subsystem->subnqn,
957  			   nsid,
958  			   hostnqn,
959  			   flags);
960  	return nvmf_ns_visible(subsystem, nsid, hostnqn, false);
961  }
962  
963  /* Must hold subsystem->mutex while calling this function */
964  static struct spdk_nvmf_host *
965  nvmf_subsystem_find_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn)
966  {
967  	struct spdk_nvmf_host *host = NULL;
968  
969  	TAILQ_FOREACH(host, &subsystem->hosts, link) {
970  		if (strcmp(hostnqn, host->nqn) == 0) {
971  			return host;
972  		}
973  	}
974  
975  	return NULL;
976  }
977  
978  int
979  spdk_nvmf_subsystem_add_host_ext(struct spdk_nvmf_subsystem *subsystem,
980  				 const char *hostnqn, struct spdk_nvmf_host_opts *opts)
981  {
982  	struct spdk_nvmf_host *host;
983  	struct spdk_nvmf_transport *transport;
984  	struct spdk_key *key;
985  	int rc;
986  
987  	if (!nvmf_nqn_is_valid(hostnqn)) {
988  		return -EINVAL;
989  	}
990  
991  	pthread_mutex_lock(&subsystem->mutex);
992  
993  	if (nvmf_subsystem_find_host(subsystem, hostnqn)) {
994  		/* This subsystem already allows the specified host. */
995  		pthread_mutex_unlock(&subsystem->mutex);
996  		return -EINVAL;
997  	}
998  
999  	host = calloc(1, sizeof(*host));
1000  	if (!host) {
1001  		pthread_mutex_unlock(&subsystem->mutex);
1002  		return -ENOMEM;
1003  	}
1004  
1005  	key = SPDK_GET_FIELD(opts, dhchap_key, NULL);
1006  	if (key != NULL) {
1007  		if (!nvmf_auth_is_supported()) {
1008  			SPDK_ERRLOG("NVMe in-band authentication is unsupported\n");
1009  			pthread_mutex_unlock(&subsystem->mutex);
1010  			nvmf_host_free(host);
1011  			return -EINVAL;
1012  		}
1013  		host->dhchap_key = spdk_key_dup(key);
1014  		if (host->dhchap_key == NULL) {
1015  			pthread_mutex_unlock(&subsystem->mutex);
1016  			nvmf_host_free(host);
1017  			return -EINVAL;
1018  		}
1019  		key = SPDK_GET_FIELD(opts, dhchap_ctrlr_key, NULL);
1020  		if (key != NULL) {
1021  			host->dhchap_ctrlr_key = spdk_key_dup(key);
1022  			if (host->dhchap_ctrlr_key == NULL) {
1023  				pthread_mutex_unlock(&subsystem->mutex);
1024  				nvmf_host_free(host);
1025  				return -EINVAL;
1026  			}
1027  		}
1028  	} else if (SPDK_GET_FIELD(opts, dhchap_ctrlr_key, NULL) != NULL) {
1029  		SPDK_ERRLOG("DH-HMAC-CHAP controller key requires host key to be set\n");
1030  		pthread_mutex_unlock(&subsystem->mutex);
1031  		nvmf_host_free(host);
1032  		return -EINVAL;
1033  	}
1034  
1035  	snprintf(host->nqn, sizeof(host->nqn), "%s", hostnqn);
1036  
1037  	SPDK_DTRACE_PROBE2(nvmf_subsystem_add_host, subsystem->subnqn, host->nqn);
1038  
1039  	TAILQ_INSERT_HEAD(&subsystem->hosts, host, link);
1040  
1041  	if (!TAILQ_EMPTY(&subsystem->listeners)) {
1042  		spdk_nvmf_send_discovery_log_notice(subsystem->tgt, hostnqn);
1043  	}
1044  
1045  	for (transport = spdk_nvmf_transport_get_first(subsystem->tgt); transport;
1046  	     transport = spdk_nvmf_transport_get_next(transport)) {
1047  		if (transport->ops->subsystem_add_host) {
1048  			rc = transport->ops->subsystem_add_host(transport, subsystem, hostnqn,
1049  								SPDK_GET_FIELD(opts, params, NULL));
1050  			if (rc) {
1051  				SPDK_ERRLOG("Unable to add host to %s transport\n", transport->ops->name);
1052  				/* Remove this host from all transports we've managed to add it to. */
1053  				pthread_mutex_unlock(&subsystem->mutex);
1054  				spdk_nvmf_subsystem_remove_host(subsystem, hostnqn);
1055  				return rc;
1056  			}
1057  		}
1058  	}
1059  
1060  	pthread_mutex_unlock(&subsystem->mutex);
1061  
1062  	return 0;
1063  }
1064  
1065  int
1066  spdk_nvmf_subsystem_add_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn,
1067  			     const struct spdk_json_val *params)
1068  {
1069  	struct spdk_nvmf_host_opts opts = {};
1070  
1071  	opts.size = SPDK_SIZEOF(&opts, params);
1072  	opts.params = params;
1073  
1074  	return spdk_nvmf_subsystem_add_host_ext(subsystem, hostnqn, &opts);
1075  }
1076  
1077  int
1078  spdk_nvmf_subsystem_remove_host(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn)
1079  {
1080  	struct spdk_nvmf_host *host;
1081  	struct spdk_nvmf_transport *transport;
1082  
1083  	pthread_mutex_lock(&subsystem->mutex);
1084  
1085  	host = nvmf_subsystem_find_host(subsystem, hostnqn);
1086  	if (host == NULL) {
1087  		pthread_mutex_unlock(&subsystem->mutex);
1088  		return -ENOENT;
1089  	}
1090  
1091  	SPDK_DTRACE_PROBE2(nvmf_subsystem_remove_host, subsystem->subnqn, host->nqn);
1092  
1093  	nvmf_subsystem_remove_host(subsystem, host);
1094  
1095  	if (!TAILQ_EMPTY(&subsystem->listeners)) {
1096  		spdk_nvmf_send_discovery_log_notice(subsystem->tgt, hostnqn);
1097  	}
1098  
1099  	for (transport = spdk_nvmf_transport_get_first(subsystem->tgt); transport;
1100  	     transport = spdk_nvmf_transport_get_next(transport)) {
1101  		if (transport->ops->subsystem_remove_host) {
1102  			transport->ops->subsystem_remove_host(transport, subsystem, hostnqn);
1103  		}
1104  	}
1105  
1106  	pthread_mutex_unlock(&subsystem->mutex);
1107  
1108  	return 0;
1109  }
1110  
1111  int
1112  spdk_nvmf_subsystem_set_keys(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn,
1113  			     struct spdk_nvmf_subsystem_key_opts *opts)
1114  {
1115  	struct spdk_nvmf_host *host;
1116  	struct spdk_key *key, *ckey;
1117  
1118  	if (!nvmf_auth_is_supported()) {
1119  		SPDK_ERRLOG("NVMe in-band authentication is unsupported\n");
1120  		return -EINVAL;
1121  	}
1122  
1123  	pthread_mutex_lock(&subsystem->mutex);
1124  	host = nvmf_subsystem_find_host(subsystem, hostnqn);
1125  	if (host == NULL) {
1126  		pthread_mutex_unlock(&subsystem->mutex);
1127  		return -EINVAL;
1128  	}
1129  
1130  	if (SPDK_GET_FIELD(opts, dhchap_key, host->dhchap_key) == NULL &&
1131  	    SPDK_GET_FIELD(opts, dhchap_ctrlr_key, host->dhchap_ctrlr_key) != NULL) {
1132  		SPDK_ERRLOG("DH-HMAC-CHAP controller key requires host key to be set\n");
1133  		pthread_mutex_unlock(&subsystem->mutex);
1134  		return -EINVAL;
1135  	}
1136  	key = SPDK_GET_FIELD(opts, dhchap_key, NULL);
1137  	if (key != NULL) {
1138  		key = spdk_key_dup(key);
1139  		if (key == NULL) {
1140  			pthread_mutex_unlock(&subsystem->mutex);
1141  			return -EINVAL;
1142  		}
1143  	}
1144  	ckey = SPDK_GET_FIELD(opts, dhchap_ctrlr_key, NULL);
1145  	if (ckey != NULL) {
1146  		ckey = spdk_key_dup(ckey);
1147  		if (ckey == NULL) {
1148  			pthread_mutex_unlock(&subsystem->mutex);
1149  			spdk_keyring_put_key(key);
1150  			return -EINVAL;
1151  		}
1152  	}
1153  	if (SPDK_FIELD_VALID(opts, dhchap_key)) {
1154  		spdk_keyring_put_key(host->dhchap_key);
1155  		host->dhchap_key = key;
1156  	}
1157  	if (SPDK_FIELD_VALID(opts, dhchap_ctrlr_key)) {
1158  		spdk_keyring_put_key(host->dhchap_ctrlr_key);
1159  		host->dhchap_ctrlr_key = ckey;
1160  	}
1161  	pthread_mutex_unlock(&subsystem->mutex);
1162  
1163  	return 0;
1164  }
1165  
1166  struct nvmf_subsystem_disconnect_host_ctx {
1167  	struct spdk_nvmf_subsystem		*subsystem;
1168  	char					*hostnqn;
1169  	spdk_nvmf_tgt_subsystem_listen_done_fn	cb_fn;
1170  	void					*cb_arg;
1171  };
1172  
1173  static void
1174  nvmf_subsystem_disconnect_host_fini(struct spdk_io_channel_iter *i, int status)
1175  {
1176  	struct nvmf_subsystem_disconnect_host_ctx *ctx;
1177  
1178  	ctx = spdk_io_channel_iter_get_ctx(i);
1179  
1180  	if (ctx->cb_fn) {
1181  		ctx->cb_fn(ctx->cb_arg, status);
1182  	}
1183  	free(ctx->hostnqn);
1184  	free(ctx);
1185  }
1186  
1187  static void
1188  nvmf_subsystem_disconnect_qpairs_by_host(struct spdk_io_channel_iter *i)
1189  {
1190  	struct nvmf_subsystem_disconnect_host_ctx *ctx;
1191  	struct spdk_nvmf_poll_group *group;
1192  	struct spdk_io_channel *ch;
1193  	struct spdk_nvmf_qpair *qpair, *tmp_qpair;
1194  	struct spdk_nvmf_ctrlr *ctrlr;
1195  
1196  	ctx = spdk_io_channel_iter_get_ctx(i);
1197  	ch = spdk_io_channel_iter_get_channel(i);
1198  	group = spdk_io_channel_get_ctx(ch);
1199  
1200  	TAILQ_FOREACH_SAFE(qpair, &group->qpairs, link, tmp_qpair) {
1201  		ctrlr = qpair->ctrlr;
1202  
1203  		if (ctrlr == NULL || ctrlr->subsys != ctx->subsystem) {
1204  			continue;
1205  		}
1206  
1207  		if (strncmp(ctrlr->hostnqn, ctx->hostnqn, sizeof(ctrlr->hostnqn)) == 0) {
1208  			/* Right now this does not wait for the queue pairs to actually disconnect. */
1209  			spdk_nvmf_qpair_disconnect(qpair);
1210  		}
1211  	}
1212  	spdk_for_each_channel_continue(i, 0);
1213  }
1214  
1215  int
1216  spdk_nvmf_subsystem_disconnect_host(struct spdk_nvmf_subsystem *subsystem,
1217  				    const char *hostnqn,
1218  				    spdk_nvmf_tgt_subsystem_listen_done_fn cb_fn,
1219  				    void *cb_arg)
1220  {
1221  	struct nvmf_subsystem_disconnect_host_ctx *ctx;
1222  
1223  	ctx = calloc(1, sizeof(struct nvmf_subsystem_disconnect_host_ctx));
1224  	if (ctx == NULL) {
1225  		return -ENOMEM;
1226  	}
1227  
1228  	ctx->hostnqn = strdup(hostnqn);
1229  	if (ctx->hostnqn == NULL) {
1230  		free(ctx);
1231  		return -ENOMEM;
1232  	}
1233  
1234  	ctx->subsystem = subsystem;
1235  	ctx->cb_fn = cb_fn;
1236  	ctx->cb_arg = cb_arg;
1237  
1238  	spdk_for_each_channel(subsystem->tgt, nvmf_subsystem_disconnect_qpairs_by_host, ctx,
1239  			      nvmf_subsystem_disconnect_host_fini);
1240  
1241  	return 0;
1242  }
1243  
1244  int
1245  spdk_nvmf_subsystem_set_allow_any_host(struct spdk_nvmf_subsystem *subsystem, bool allow_any_host)
1246  {
1247  	if (subsystem->allow_any_host == allow_any_host) {
1248  		return 0;
1249  	}
1250  
1251  	pthread_mutex_lock(&subsystem->mutex);
1252  	subsystem->allow_any_host = allow_any_host;
1253  	if (!TAILQ_EMPTY(&subsystem->listeners)) {
1254  		spdk_nvmf_send_discovery_log_notice(subsystem->tgt, NULL);
1255  	}
1256  	pthread_mutex_unlock(&subsystem->mutex);
1257  
1258  	return 0;
1259  }
1260  
1261  bool
1262  spdk_nvmf_subsystem_get_allow_any_host(const struct spdk_nvmf_subsystem *subsystem)
1263  {
1264  	bool allow_any_host;
1265  	struct spdk_nvmf_subsystem *sub;
1266  
1267  	/* Technically, taking the mutex modifies data in the subsystem. But the const
1268  	 * is still important to convey that this doesn't mutate any other data. Cast
1269  	 * it away to work around this. */
1270  	sub = (struct spdk_nvmf_subsystem *)subsystem;
1271  
1272  	pthread_mutex_lock(&sub->mutex);
1273  	allow_any_host = sub->allow_any_host;
1274  	pthread_mutex_unlock(&sub->mutex);
1275  
1276  	return allow_any_host;
1277  }
1278  
1279  bool
1280  spdk_nvmf_subsystem_host_allowed(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn)
1281  {
1282  	bool allowed;
1283  
1284  	if (!hostnqn) {
1285  		return false;
1286  	}
1287  
1288  	pthread_mutex_lock(&subsystem->mutex);
1289  
1290  	if (subsystem->allow_any_host) {
1291  		pthread_mutex_unlock(&subsystem->mutex);
1292  		return true;
1293  	}
1294  
1295  	allowed =  nvmf_subsystem_find_host(subsystem, hostnqn) != NULL;
1296  	pthread_mutex_unlock(&subsystem->mutex);
1297  
1298  	return allowed;
1299  }
1300  
1301  bool
1302  nvmf_subsystem_host_auth_required(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn)
1303  {
1304  	struct spdk_nvmf_host *host;
1305  	bool status;
1306  
1307  	pthread_mutex_lock(&subsystem->mutex);
1308  	host = nvmf_subsystem_find_host(subsystem, hostnqn);
1309  	status = host != NULL && host->dhchap_key != NULL;
1310  	pthread_mutex_unlock(&subsystem->mutex);
1311  
1312  	return status;
1313  }
1314  
1315  struct spdk_key *
1316  nvmf_subsystem_get_dhchap_key(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn,
1317  			      enum nvmf_auth_key_type type)
1318  {
1319  	struct spdk_nvmf_host *host;
1320  	struct spdk_key *key = NULL;
1321  
1322  	pthread_mutex_lock(&subsystem->mutex);
1323  	host = nvmf_subsystem_find_host(subsystem, hostnqn);
1324  	if (host != NULL) {
1325  		switch (type) {
1326  		case NVMF_AUTH_KEY_HOST:
1327  			key = host->dhchap_key;
1328  			break;
1329  		case NVMF_AUTH_KEY_CTRLR:
1330  			key = host->dhchap_ctrlr_key;
1331  			break;
1332  		}
1333  		if (key != NULL) {
1334  			key = spdk_key_dup(key);
1335  		}
1336  	}
1337  	pthread_mutex_unlock(&subsystem->mutex);
1338  
1339  	return key;
1340  }
1341  
1342  struct spdk_nvmf_host *
1343  spdk_nvmf_subsystem_get_first_host(struct spdk_nvmf_subsystem *subsystem)
1344  {
1345  	return TAILQ_FIRST(&subsystem->hosts);
1346  }
1347  
1348  
1349  struct spdk_nvmf_host *
1350  spdk_nvmf_subsystem_get_next_host(struct spdk_nvmf_subsystem *subsystem,
1351  				  struct spdk_nvmf_host *prev_host)
1352  {
1353  	return TAILQ_NEXT(prev_host, link);
1354  }
1355  
1356  const char *
1357  spdk_nvmf_host_get_nqn(const struct spdk_nvmf_host *host)
1358  {
1359  	return host->nqn;
1360  }
1361  
1362  struct spdk_nvmf_subsystem_listener *
1363  nvmf_subsystem_find_listener(struct spdk_nvmf_subsystem *subsystem,
1364  			     const struct spdk_nvme_transport_id *trid)
1365  {
1366  	struct spdk_nvmf_subsystem_listener *listener;
1367  
1368  	TAILQ_FOREACH(listener, &subsystem->listeners, link) {
1369  		if (spdk_nvme_transport_id_compare(listener->trid, trid) == 0) {
1370  			return listener;
1371  		}
1372  	}
1373  
1374  	return NULL;
1375  }
1376  
1377  /**
1378   * Function to be called once the target is listening.
1379   *
1380   * \param ctx Context argument passed to this function.
1381   * \param status 0 if it completed successfully, or negative errno if it failed.
1382   */
1383  static void
1384  _nvmf_subsystem_add_listener_done(void *ctx, int status)
1385  {
1386  	struct spdk_nvmf_subsystem_listener *listener = ctx;
1387  
1388  	if (status) {
1389  		listener->cb_fn(listener->cb_arg, status);
1390  		free(listener);
1391  		return;
1392  	}
1393  
1394  	TAILQ_INSERT_HEAD(&listener->subsystem->listeners, listener, link);
1395  
1396  	if (spdk_nvmf_subsystem_is_discovery(listener->subsystem)) {
1397  		status = nvmf_tgt_update_mdns_prr(listener->subsystem->tgt);
1398  		if (status) {
1399  			TAILQ_REMOVE(&listener->subsystem->listeners, listener, link);
1400  			listener->cb_fn(listener->cb_arg, status);
1401  			free(listener);
1402  			return;
1403  		}
1404  	}
1405  
1406  	spdk_nvmf_send_discovery_log_notice(listener->subsystem->tgt, NULL);
1407  	listener->cb_fn(listener->cb_arg, status);
1408  }
1409  
1410  void
1411  spdk_nvmf_subsystem_listener_opts_init(struct spdk_nvmf_listener_opts *opts, size_t size)
1412  {
1413  	if (opts == NULL) {
1414  		SPDK_ERRLOG("opts should not be NULL\n");
1415  		assert(false);
1416  		return;
1417  	}
1418  	if (size == 0) {
1419  		SPDK_ERRLOG("size should not be zero\n");
1420  		assert(false);
1421  		return;
1422  	}
1423  
1424  	memset(opts, 0, size);
1425  	opts->opts_size = size;
1426  
1427  #define FIELD_OK(field) \
1428  	offsetof(struct spdk_nvmf_listener_opts, field) + sizeof(opts->field) <= size
1429  
1430  #define SET_FIELD(field, value) \
1431  	if (FIELD_OK(field)) { \
1432  		opts->field = value; \
1433  	} \
1434  
1435  	SET_FIELD(secure_channel, false);
1436  	SET_FIELD(ana_state, SPDK_NVME_ANA_OPTIMIZED_STATE);
1437  	SET_FIELD(sock_impl, NULL);
1438  
1439  #undef FIELD_OK
1440  #undef SET_FIELD
1441  }
1442  
1443  static int
1444  listener_opts_copy(struct spdk_nvmf_listener_opts *src, struct spdk_nvmf_listener_opts *dst)
1445  {
1446  	if (src->opts_size == 0) {
1447  		SPDK_ERRLOG("source structure size should not be zero\n");
1448  		assert(false);
1449  		return -EINVAL;
1450  	}
1451  
1452  	memset(dst, 0, sizeof(*dst));
1453  	dst->opts_size = src->opts_size;
1454  
1455  #define FIELD_OK(field) \
1456  	offsetof(struct spdk_nvmf_listener_opts, field) + sizeof(src->field) <= src->opts_size
1457  
1458  #define SET_FIELD(field) \
1459  	if (FIELD_OK(field)) { \
1460  		dst->field = src->field; \
1461  	} \
1462  
1463  	SET_FIELD(secure_channel);
1464  	SET_FIELD(ana_state);
1465  	SET_FIELD(sock_impl);
1466  	/* We should not remove this statement, but need to update the assert statement
1467  	 * if we add a new field, and also add a corresponding SET_FIELD statement. */
1468  	SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_listener_opts) == 24, "Incorrect size");
1469  
1470  #undef SET_FIELD
1471  #undef FIELD_OK
1472  
1473  	return 0;
1474  }
1475  
1476  static void
1477  _nvmf_subsystem_add_listener(struct spdk_nvmf_subsystem *subsystem,
1478  			     struct spdk_nvme_transport_id *trid,
1479  			     spdk_nvmf_tgt_subsystem_listen_done_fn cb_fn,
1480  			     void *cb_arg, struct spdk_nvmf_listener_opts *opts)
1481  {
1482  	struct spdk_nvmf_transport *transport;
1483  	struct spdk_nvmf_subsystem_listener *listener;
1484  	struct spdk_nvmf_listener *tr_listener;
1485  	uint32_t i;
1486  	uint32_t id;
1487  	int rc = 0;
1488  
1489  	assert(cb_fn != NULL);
1490  
1491  	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
1492  	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
1493  		cb_fn(cb_arg, -EAGAIN);
1494  		return;
1495  	}
1496  
1497  	if (nvmf_subsystem_find_listener(subsystem, trid)) {
1498  		/* Listener already exists in this subsystem */
1499  		cb_fn(cb_arg, 0);
1500  		return;
1501  	}
1502  
1503  	transport = spdk_nvmf_tgt_get_transport(subsystem->tgt, trid->trstring);
1504  	if (!transport) {
1505  		SPDK_ERRLOG("Unable to find %s transport. The transport must be created first also make sure it is properly registered.\n",
1506  			    trid->trstring);
1507  		cb_fn(cb_arg, -EINVAL);
1508  		return;
1509  	}
1510  
1511  	tr_listener = nvmf_transport_find_listener(transport, trid);
1512  	if (!tr_listener) {
1513  		SPDK_ERRLOG("Cannot find transport listener for %s\n", trid->traddr);
1514  		cb_fn(cb_arg, -EINVAL);
1515  		return;
1516  	}
1517  
1518  	listener = calloc(1, sizeof(*listener));
1519  	if (!listener) {
1520  		cb_fn(cb_arg, -ENOMEM);
1521  		return;
1522  	}
1523  
1524  	listener->trid = &tr_listener->trid;
1525  	listener->transport = transport;
1526  	listener->cb_fn = cb_fn;
1527  	listener->cb_arg = cb_arg;
1528  	listener->subsystem = subsystem;
1529  	listener->ana_state = calloc(subsystem->max_nsid, sizeof(enum spdk_nvme_ana_state));
1530  	if (!listener->ana_state) {
1531  		free(listener);
1532  		cb_fn(cb_arg, -ENOMEM);
1533  		return;
1534  	}
1535  
1536  	spdk_nvmf_subsystem_listener_opts_init(&listener->opts, sizeof(listener->opts));
1537  	if (opts != NULL) {
1538  		rc = listener_opts_copy(opts, &listener->opts);
1539  		if (rc) {
1540  			SPDK_ERRLOG("Unable to copy listener options\n");
1541  			free(listener->ana_state);
1542  			free(listener);
1543  			cb_fn(cb_arg, -EINVAL);
1544  			return;
1545  		}
1546  	}
1547  
1548  	id = spdk_bit_array_find_first_clear(subsystem->used_listener_ids, 0);
1549  	if (id == UINT32_MAX) {
1550  		SPDK_ERRLOG("Cannot add any more listeners\n");
1551  		free(listener->ana_state);
1552  		free(listener->opts.sock_impl);
1553  		free(listener);
1554  		cb_fn(cb_arg, -EINVAL);
1555  		return;
1556  	}
1557  
1558  	spdk_bit_array_set(subsystem->used_listener_ids, id);
1559  	listener->id = id;
1560  
1561  	for (i = 0; i < subsystem->max_nsid; i++) {
1562  		listener->ana_state[i] = listener->opts.ana_state;
1563  	}
1564  
1565  	if (transport->ops->listen_associate != NULL) {
1566  		rc = transport->ops->listen_associate(transport, subsystem, trid);
1567  	}
1568  
1569  	SPDK_DTRACE_PROBE4(nvmf_subsystem_add_listener, subsystem->subnqn, listener->trid->trtype,
1570  			   listener->trid->traddr, listener->trid->trsvcid);
1571  
1572  	_nvmf_subsystem_add_listener_done(listener, rc);
1573  }
1574  
1575  void
1576  spdk_nvmf_subsystem_add_listener(struct spdk_nvmf_subsystem *subsystem,
1577  				 struct spdk_nvme_transport_id *trid,
1578  				 spdk_nvmf_tgt_subsystem_listen_done_fn cb_fn,
1579  				 void *cb_arg)
1580  {
1581  	_nvmf_subsystem_add_listener(subsystem, trid, cb_fn, cb_arg, NULL);
1582  }
1583  
1584  void
1585  spdk_nvmf_subsystem_add_listener_ext(struct spdk_nvmf_subsystem *subsystem,
1586  				     struct spdk_nvme_transport_id *trid,
1587  				     spdk_nvmf_tgt_subsystem_listen_done_fn cb_fn,
1588  				     void *cb_arg, struct spdk_nvmf_listener_opts *opts)
1589  {
1590  	_nvmf_subsystem_add_listener(subsystem, trid, cb_fn, cb_arg, opts);
1591  }
1592  
1593  int
1594  spdk_nvmf_subsystem_remove_listener(struct spdk_nvmf_subsystem *subsystem,
1595  				    const struct spdk_nvme_transport_id *trid)
1596  {
1597  	struct spdk_nvmf_subsystem_listener *listener;
1598  
1599  	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
1600  	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
1601  		return -EAGAIN;
1602  	}
1603  
1604  	listener = nvmf_subsystem_find_listener(subsystem, trid);
1605  	if (listener == NULL) {
1606  		return -ENOENT;
1607  	}
1608  
1609  	SPDK_DTRACE_PROBE4(nvmf_subsystem_remove_listener, subsystem->subnqn, listener->trid->trtype,
1610  			   listener->trid->traddr, listener->trid->trsvcid);
1611  
1612  	_nvmf_subsystem_remove_listener(subsystem, listener, false);
1613  
1614  	return 0;
1615  }
1616  
1617  void
1618  nvmf_subsystem_remove_all_listeners(struct spdk_nvmf_subsystem *subsystem,
1619  				    bool stop)
1620  {
1621  	struct spdk_nvmf_subsystem_listener *listener, *listener_tmp;
1622  
1623  	TAILQ_FOREACH_SAFE(listener, &subsystem->listeners, link, listener_tmp) {
1624  		_nvmf_subsystem_remove_listener(subsystem, listener, stop);
1625  	}
1626  }
1627  
1628  bool
1629  spdk_nvmf_subsystem_listener_allowed(struct spdk_nvmf_subsystem *subsystem,
1630  				     const struct spdk_nvme_transport_id *trid)
1631  {
1632  	struct spdk_nvmf_subsystem_listener *listener;
1633  
1634  	TAILQ_FOREACH(listener, &subsystem->listeners, link) {
1635  		if (spdk_nvme_transport_id_compare(listener->trid, trid) == 0) {
1636  			return true;
1637  		}
1638  	}
1639  
1640  	if (!strcmp(subsystem->subnqn, SPDK_NVMF_DISCOVERY_NQN)) {
1641  		SPDK_WARNLOG("Allowing connection to discovery subsystem on %s/%s/%s, "
1642  			     "even though this listener was not added to the discovery "
1643  			     "subsystem.  This behavior is deprecated and will be removed "
1644  			     "in a future release.\n",
1645  			     spdk_nvme_transport_id_trtype_str(trid->trtype), trid->traddr, trid->trsvcid);
1646  		return true;
1647  	}
1648  
1649  	return false;
1650  }
1651  
1652  struct spdk_nvmf_subsystem_listener *
1653  spdk_nvmf_subsystem_get_first_listener(struct spdk_nvmf_subsystem *subsystem)
1654  {
1655  	return TAILQ_FIRST(&subsystem->listeners);
1656  }
1657  
1658  struct spdk_nvmf_subsystem_listener *
1659  spdk_nvmf_subsystem_get_next_listener(struct spdk_nvmf_subsystem *subsystem,
1660  				      struct spdk_nvmf_subsystem_listener *prev_listener)
1661  {
1662  	return TAILQ_NEXT(prev_listener, link);
1663  }
1664  
1665  const struct spdk_nvme_transport_id *
1666  spdk_nvmf_subsystem_listener_get_trid(struct spdk_nvmf_subsystem_listener *listener)
1667  {
1668  	return listener->trid;
1669  }
1670  
1671  void
1672  spdk_nvmf_subsystem_allow_any_listener(struct spdk_nvmf_subsystem *subsystem,
1673  				       bool allow_any_listener)
1674  {
1675  	subsystem->flags.allow_any_listener = allow_any_listener;
1676  }
1677  
1678  bool
1679  spdk_nvmf_subsystem_any_listener_allowed(struct spdk_nvmf_subsystem *subsystem)
1680  {
1681  	return subsystem->flags.allow_any_listener;
1682  }
1683  
1684  struct subsystem_update_ns_ctx {
1685  	struct spdk_nvmf_subsystem *subsystem;
1686  
1687  	spdk_nvmf_subsystem_state_change_done cb_fn;
1688  	void *cb_arg;
1689  };
1690  
1691  static void
1692  subsystem_update_ns_done(struct spdk_io_channel_iter *i, int status)
1693  {
1694  	struct subsystem_update_ns_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
1695  
1696  	if (ctx->cb_fn) {
1697  		ctx->cb_fn(ctx->subsystem, ctx->cb_arg, status);
1698  	}
1699  	free(ctx);
1700  }
1701  
1702  static void
1703  subsystem_update_ns_on_pg(struct spdk_io_channel_iter *i)
1704  {
1705  	int rc;
1706  	struct subsystem_update_ns_ctx *ctx;
1707  	struct spdk_nvmf_poll_group *group;
1708  	struct spdk_nvmf_subsystem *subsystem;
1709  
1710  	ctx = spdk_io_channel_iter_get_ctx(i);
1711  	group = spdk_io_channel_get_ctx(spdk_io_channel_iter_get_channel(i));
1712  	subsystem = ctx->subsystem;
1713  
1714  	rc = nvmf_poll_group_update_subsystem(group, subsystem);
1715  	spdk_for_each_channel_continue(i, rc);
1716  }
1717  
1718  static int
1719  nvmf_subsystem_update_ns(struct spdk_nvmf_subsystem *subsystem,
1720  			 spdk_nvmf_subsystem_state_change_done cb_fn, void *cb_arg)
1721  {
1722  	struct subsystem_update_ns_ctx *ctx;
1723  
1724  	ctx = calloc(1, sizeof(*ctx));
1725  	if (ctx == NULL) {
1726  		SPDK_ERRLOG("Can't alloc subsystem poll group update context\n");
1727  		return -ENOMEM;
1728  	}
1729  	ctx->subsystem = subsystem;
1730  	ctx->cb_fn = cb_fn;
1731  	ctx->cb_arg = cb_arg;
1732  
1733  	spdk_for_each_channel(subsystem->tgt,
1734  			      subsystem_update_ns_on_pg,
1735  			      ctx,
1736  			      subsystem_update_ns_done);
1737  	return 0;
1738  }
1739  
1740  static void
1741  nvmf_subsystem_ns_changed(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid)
1742  {
1743  	struct spdk_nvmf_ctrlr *ctrlr;
1744  
1745  	TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) {
1746  		if (nvmf_ctrlr_ns_is_visible(ctrlr, nsid)) {
1747  			nvmf_ctrlr_ns_changed(ctrlr, nsid);
1748  		}
1749  	}
1750  }
1751  
1752  static uint32_t nvmf_ns_reservation_clear_all_registrants(struct spdk_nvmf_ns *ns);
1753  
1754  int
1755  spdk_nvmf_subsystem_remove_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid)
1756  {
1757  	struct spdk_nvmf_transport *transport;
1758  	struct spdk_nvmf_ns *ns;
1759  	struct spdk_nvmf_host *host, *tmp;
1760  	struct spdk_nvmf_ctrlr *ctrlr;
1761  
1762  	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
1763  	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
1764  		assert(false);
1765  		return -1;
1766  	}
1767  
1768  	if (nsid == 0 || nsid > subsystem->max_nsid) {
1769  		return -1;
1770  	}
1771  
1772  	ns = subsystem->ns[nsid - 1];
1773  	if (!ns) {
1774  		return -1;
1775  	}
1776  
1777  	subsystem->ns[nsid - 1] = NULL;
1778  
1779  	assert(ns->anagrpid - 1 < subsystem->max_nsid);
1780  	assert(subsystem->ana_group[ns->anagrpid - 1] > 0);
1781  
1782  	subsystem->ana_group[ns->anagrpid - 1]--;
1783  
1784  	TAILQ_FOREACH_SAFE(host, &ns->hosts, link, tmp) {
1785  		nvmf_ns_remove_host(ns, host);
1786  	}
1787  
1788  	free(ns->ptpl_file);
1789  	nvmf_ns_reservation_clear_all_registrants(ns);
1790  	spdk_bdev_module_release_bdev(ns->bdev);
1791  	spdk_bdev_close(ns->desc);
1792  	free(ns);
1793  
1794  	if (subsystem->fdp_supported && !spdk_nvmf_subsystem_get_first_ns(subsystem)) {
1795  		subsystem->fdp_supported = false;
1796  		SPDK_DEBUGLOG(nvmf, "Subsystem with id: %u doesn't have FDP capability.\n",
1797  			      subsystem->id);
1798  	}
1799  
1800  	for (transport = spdk_nvmf_transport_get_first(subsystem->tgt); transport;
1801  	     transport = spdk_nvmf_transport_get_next(transport)) {
1802  		if (transport->ops->subsystem_remove_ns) {
1803  			transport->ops->subsystem_remove_ns(transport, subsystem, nsid);
1804  		}
1805  	}
1806  
1807  	nvmf_subsystem_ns_changed(subsystem, nsid);
1808  
1809  	TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) {
1810  		nvmf_ctrlr_ns_set_visible(ctrlr, nsid, false);
1811  	}
1812  
1813  	return 0;
1814  }
1815  
1816  struct subsystem_ns_change_ctx {
1817  	struct spdk_nvmf_subsystem		*subsystem;
1818  	spdk_nvmf_subsystem_state_change_done	cb_fn;
1819  	uint32_t				nsid;
1820  };
1821  
1822  static void
1823  _nvmf_ns_hot_remove(struct spdk_nvmf_subsystem *subsystem,
1824  		    void *cb_arg, int status)
1825  {
1826  	struct subsystem_ns_change_ctx *ctx = cb_arg;
1827  	int rc;
1828  
1829  	rc = spdk_nvmf_subsystem_remove_ns(subsystem, ctx->nsid);
1830  	if (rc != 0) {
1831  		SPDK_ERRLOG("Failed to make changes to NVME-oF subsystem with id: %u\n", subsystem->id);
1832  	}
1833  
1834  	rc = spdk_nvmf_subsystem_resume(subsystem, NULL, NULL);
1835  	if (rc != 0) {
1836  		SPDK_ERRLOG("Failed to resume NVME-oF subsystem with id: %u\n", subsystem->id);
1837  	}
1838  
1839  	free(ctx);
1840  }
1841  
1842  static void
1843  nvmf_ns_change_msg(void *ns_ctx)
1844  {
1845  	struct subsystem_ns_change_ctx *ctx = ns_ctx;
1846  	int rc;
1847  
1848  	SPDK_DTRACE_PROBE2(nvmf_ns_change, ctx->nsid, ctx->subsystem->subnqn);
1849  
1850  	rc = spdk_nvmf_subsystem_pause(ctx->subsystem, ctx->nsid, ctx->cb_fn, ctx);
1851  	if (rc) {
1852  		if (rc == -EBUSY) {
1853  			/* Try again, this is not a permanent situation. */
1854  			spdk_thread_send_msg(spdk_get_thread(), nvmf_ns_change_msg, ctx);
1855  		} else {
1856  			free(ctx);
1857  			SPDK_ERRLOG("Unable to pause subsystem to process namespace removal!\n");
1858  		}
1859  	}
1860  }
1861  
1862  static void
1863  nvmf_ns_hot_remove(void *remove_ctx)
1864  {
1865  	struct spdk_nvmf_ns *ns = remove_ctx;
1866  	struct subsystem_ns_change_ctx *ns_ctx;
1867  	int rc;
1868  
1869  	/* We have to allocate a new context because this op
1870  	 * is asynchronous and we could lose the ns in the middle.
1871  	 */
1872  	ns_ctx = calloc(1, sizeof(struct subsystem_ns_change_ctx));
1873  	if (!ns_ctx) {
1874  		SPDK_ERRLOG("Unable to allocate context to process namespace removal!\n");
1875  		return;
1876  	}
1877  
1878  	ns_ctx->subsystem = ns->subsystem;
1879  	ns_ctx->nsid = ns->opts.nsid;
1880  	ns_ctx->cb_fn = _nvmf_ns_hot_remove;
1881  
1882  	rc = spdk_nvmf_subsystem_pause(ns->subsystem, ns_ctx->nsid, _nvmf_ns_hot_remove, ns_ctx);
1883  	if (rc) {
1884  		if (rc == -EBUSY) {
1885  			/* Try again, this is not a permanent situation. */
1886  			spdk_thread_send_msg(spdk_get_thread(), nvmf_ns_change_msg, ns_ctx);
1887  		} else {
1888  			SPDK_ERRLOG("Unable to pause subsystem to process namespace removal!\n");
1889  			free(ns_ctx);
1890  		}
1891  	}
1892  }
1893  
1894  static void
1895  _nvmf_ns_resize(struct spdk_nvmf_subsystem *subsystem, void *cb_arg, int status)
1896  {
1897  	struct subsystem_ns_change_ctx *ctx = cb_arg;
1898  
1899  	nvmf_subsystem_ns_changed(subsystem, ctx->nsid);
1900  	if (spdk_nvmf_subsystem_resume(subsystem, NULL, NULL) != 0) {
1901  		SPDK_ERRLOG("Failed to resume NVME-oF subsystem with id: %u\n", subsystem->id);
1902  	}
1903  
1904  	free(ctx);
1905  }
1906  
1907  static void
1908  nvmf_ns_resize(void *event_ctx)
1909  {
1910  	struct spdk_nvmf_ns *ns = event_ctx;
1911  	struct subsystem_ns_change_ctx *ns_ctx;
1912  	int rc;
1913  
1914  	/* We have to allocate a new context because this op
1915  	 * is asynchronous and we could lose the ns in the middle.
1916  	 */
1917  	ns_ctx = calloc(1, sizeof(struct subsystem_ns_change_ctx));
1918  	if (!ns_ctx) {
1919  		SPDK_ERRLOG("Unable to allocate context to process namespace removal!\n");
1920  		return;
1921  	}
1922  
1923  	ns_ctx->subsystem = ns->subsystem;
1924  	ns_ctx->nsid = ns->opts.nsid;
1925  	ns_ctx->cb_fn = _nvmf_ns_resize;
1926  
1927  	/* Specify 0 for the nsid here, because we do not need to pause the namespace.
1928  	 * Namespaces can only be resized bigger, so there is no need to quiesce I/O.
1929  	 */
1930  	rc = spdk_nvmf_subsystem_pause(ns->subsystem, 0, _nvmf_ns_resize, ns_ctx);
1931  	if (rc) {
1932  		if (rc == -EBUSY) {
1933  			/* Try again, this is not a permanent situation. */
1934  			spdk_thread_send_msg(spdk_get_thread(), nvmf_ns_change_msg, ns_ctx);
1935  		} else {
1936  			SPDK_ERRLOG("Unable to pause subsystem to process namespace resize!\n");
1937  			free(ns_ctx);
1938  		}
1939  	}
1940  }
1941  
1942  static void
1943  nvmf_ns_event(enum spdk_bdev_event_type type,
1944  	      struct spdk_bdev *bdev,
1945  	      void *event_ctx)
1946  {
1947  	SPDK_DEBUGLOG(nvmf, "Bdev event: type %d, name %s, subsystem_id %d, ns_id %d\n",
1948  		      type,
1949  		      spdk_bdev_get_name(bdev),
1950  		      ((struct spdk_nvmf_ns *)event_ctx)->subsystem->id,
1951  		      ((struct spdk_nvmf_ns *)event_ctx)->nsid);
1952  
1953  	switch (type) {
1954  	case SPDK_BDEV_EVENT_REMOVE:
1955  		nvmf_ns_hot_remove(event_ctx);
1956  		break;
1957  	case SPDK_BDEV_EVENT_RESIZE:
1958  		nvmf_ns_resize(event_ctx);
1959  		break;
1960  	default:
1961  		SPDK_NOTICELOG("Unsupported bdev event: type %d\n", type);
1962  		break;
1963  	}
1964  }
1965  
1966  void
1967  spdk_nvmf_ns_opts_get_defaults(struct spdk_nvmf_ns_opts *opts, size_t opts_size)
1968  {
1969  	if (!opts) {
1970  		SPDK_ERRLOG("opts should not be NULL.\n");
1971  		return;
1972  	}
1973  
1974  	if (!opts_size) {
1975  		SPDK_ERRLOG("opts_size should not be zero.\n");
1976  		return;
1977  	}
1978  
1979  	memset(opts, 0, opts_size);
1980  	opts->opts_size = opts_size;
1981  
1982  #define FIELD_OK(field) \
1983  	offsetof(struct spdk_nvmf_ns_opts, field) + sizeof(opts->field) <= opts_size
1984  
1985  #define SET_FIELD(field, value) \
1986  	if (FIELD_OK(field)) { \
1987  		opts->field = value; \
1988  	} \
1989  
1990  	/* All current fields are set to 0 by default. */
1991  	SET_FIELD(nsid, 0);
1992  	if (FIELD_OK(nguid)) {
1993  		memset(opts->nguid, 0, sizeof(opts->nguid));
1994  	}
1995  	if (FIELD_OK(eui64)) {
1996  		memset(opts->eui64, 0, sizeof(opts->eui64));
1997  	}
1998  	if (FIELD_OK(uuid)) {
1999  		spdk_uuid_set_null(&opts->uuid);
2000  	}
2001  	SET_FIELD(anagrpid, 0);
2002  	SET_FIELD(transport_specific, NULL);
2003  	SET_FIELD(hide_metadata, false);
2004  
2005  #undef FIELD_OK
2006  #undef SET_FIELD
2007  }
2008  
2009  static void
2010  nvmf_ns_opts_copy(struct spdk_nvmf_ns_opts *opts,
2011  		  const struct spdk_nvmf_ns_opts *user_opts,
2012  		  size_t opts_size)
2013  {
2014  #define FIELD_OK(field)	\
2015  	offsetof(struct spdk_nvmf_ns_opts, field) + sizeof(opts->field) <= user_opts->opts_size
2016  
2017  #define SET_FIELD(field) \
2018  	if (FIELD_OK(field)) { \
2019  		opts->field = user_opts->field;	\
2020  	} \
2021  
2022  	SET_FIELD(nsid);
2023  	if (FIELD_OK(nguid)) {
2024  		memcpy(opts->nguid, user_opts->nguid, sizeof(opts->nguid));
2025  	}
2026  	if (FIELD_OK(eui64)) {
2027  		memcpy(opts->eui64, user_opts->eui64, sizeof(opts->eui64));
2028  	}
2029  	if (FIELD_OK(uuid)) {
2030  		spdk_uuid_copy(&opts->uuid, &user_opts->uuid);
2031  	}
2032  	SET_FIELD(anagrpid);
2033  	SET_FIELD(no_auto_visible);
2034  	SET_FIELD(transport_specific);
2035  	SET_FIELD(hide_metadata);
2036  
2037  	opts->opts_size = user_opts->opts_size;
2038  
2039  	/* We should not remove this statement, but need to update the assert statement
2040  	 * if we add a new field, and also add a corresponding SET_FIELD statement.
2041  	 */
2042  	SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_ns_opts) == 73, "Incorrect size");
2043  
2044  #undef FIELD_OK
2045  #undef SET_FIELD
2046  }
2047  
2048  /* Dummy bdev module used to to claim bdevs. */
2049  static struct spdk_bdev_module ns_bdev_module = {
2050  	.name	= "NVMe-oF Target",
2051  };
2052  
2053  static int nvmf_ns_reservation_update(const struct spdk_nvmf_ns *ns,
2054  				      const struct spdk_nvmf_reservation_info *info);
2055  static int nvmf_ns_reservation_load(const struct spdk_nvmf_ns *ns,
2056  				    struct spdk_nvmf_reservation_info *info);
2057  static int nvmf_ns_reservation_restore(struct spdk_nvmf_ns *ns,
2058  				       struct spdk_nvmf_reservation_info *info);
2059  
2060  bool
2061  nvmf_subsystem_zone_append_supported(struct spdk_nvmf_subsystem *subsystem)
2062  {
2063  	struct spdk_nvmf_ns *ns;
2064  
2065  	for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem);
2066  	     ns != NULL;
2067  	     ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns)) {
2068  		if (spdk_bdev_is_zoned(ns->bdev) &&
2069  		    spdk_bdev_io_type_supported(ns->bdev, SPDK_BDEV_IO_TYPE_ZONE_APPEND)) {
2070  			return true;
2071  		}
2072  	}
2073  
2074  	return false;
2075  }
2076  
2077  uint32_t
2078  spdk_nvmf_subsystem_add_ns_ext(struct spdk_nvmf_subsystem *subsystem, const char *bdev_name,
2079  			       const struct spdk_nvmf_ns_opts *user_opts, size_t opts_size,
2080  			       const char *ptpl_file)
2081  {
2082  	struct spdk_nvmf_transport *transport;
2083  	struct spdk_nvmf_ns_opts opts;
2084  	struct spdk_bdev_open_opts open_opts = {};
2085  	struct spdk_nvmf_ns *ns, *first_ns;
2086  	struct spdk_nvmf_ctrlr *ctrlr;
2087  	struct spdk_nvmf_reservation_info info = {0};
2088  	int rc;
2089  	bool zone_append_supported;
2090  	uint64_t max_zone_append_size_kib;
2091  
2092  	if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
2093  	      subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED)) {
2094  		return 0;
2095  	}
2096  
2097  	spdk_nvmf_ns_opts_get_defaults(&opts, sizeof(opts));
2098  	if (user_opts) {
2099  		nvmf_ns_opts_copy(&opts, user_opts, opts_size);
2100  	}
2101  
2102  	if (opts.nsid == SPDK_NVME_GLOBAL_NS_TAG) {
2103  		SPDK_ERRLOG("Invalid NSID %" PRIu32 "\n", opts.nsid);
2104  		return 0;
2105  	}
2106  
2107  	if (opts.nsid == 0) {
2108  		/*
2109  		 * NSID not specified - find a free index.
2110  		 *
2111  		 * If no free slots are found, return error.
2112  		 */
2113  		for (opts.nsid = 1; opts.nsid <= subsystem->max_nsid; opts.nsid++) {
2114  			if (_nvmf_subsystem_get_ns(subsystem, opts.nsid) == NULL) {
2115  				break;
2116  			}
2117  		}
2118  		if (opts.nsid > subsystem->max_nsid) {
2119  			SPDK_ERRLOG("No free namespace slot available in the subsystem\n");
2120  			return 0;
2121  		}
2122  	}
2123  
2124  	if (opts.nsid > subsystem->max_nsid) {
2125  		SPDK_ERRLOG("NSID greater than maximum not allowed\n");
2126  		return 0;
2127  	}
2128  
2129  	if (_nvmf_subsystem_get_ns(subsystem, opts.nsid)) {
2130  		SPDK_ERRLOG("Requested NSID %" PRIu32 " already in use\n", opts.nsid);
2131  		return 0;
2132  	}
2133  
2134  	if (opts.anagrpid == 0) {
2135  		opts.anagrpid = opts.nsid;
2136  	}
2137  
2138  	if (opts.anagrpid > subsystem->max_nsid) {
2139  		SPDK_ERRLOG("ANAGRPID greater than maximum NSID not allowed\n");
2140  		return 0;
2141  	}
2142  
2143  	ns = calloc(1, sizeof(*ns));
2144  	if (ns == NULL) {
2145  		SPDK_ERRLOG("Namespace allocation failed\n");
2146  		return 0;
2147  	}
2148  
2149  	TAILQ_INIT(&ns->hosts);
2150  	ns->always_visible = !opts.no_auto_visible;
2151  	TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) {
2152  		nvmf_ctrlr_ns_set_visible(ctrlr, opts.nsid, ns->always_visible);
2153  	}
2154  
2155  	spdk_bdev_open_opts_init(&open_opts, sizeof(open_opts));
2156  	open_opts.hide_metadata = opts.hide_metadata;
2157  
2158  	rc = spdk_bdev_open_ext_v2(bdev_name, true, nvmf_ns_event, ns, &open_opts, &ns->desc);
2159  	if (rc != 0) {
2160  		SPDK_ERRLOG("Subsystem %s: bdev %s cannot be opened, error=%d\n",
2161  			    subsystem->subnqn, bdev_name, rc);
2162  		free(ns);
2163  		return 0;
2164  	}
2165  
2166  	ns->bdev = spdk_bdev_desc_get_bdev(ns->desc);
2167  
2168  	if (spdk_bdev_desc_get_md_size(ns->desc) != 0) {
2169  		if (!spdk_bdev_desc_is_md_interleaved(ns->desc)) {
2170  			SPDK_ERRLOG("Can't attach bdev with separate metadata.\n");
2171  			spdk_bdev_close(ns->desc);
2172  			free(ns);
2173  			return 0;
2174  		}
2175  
2176  		if (spdk_bdev_desc_get_md_size(ns->desc) > SPDK_BDEV_MAX_INTERLEAVED_MD_SIZE) {
2177  			SPDK_ERRLOG("Maximum supported interleaved md size %u, current md size %u\n",
2178  				    SPDK_BDEV_MAX_INTERLEAVED_MD_SIZE,
2179  				    spdk_bdev_desc_get_md_size(ns->desc));
2180  			spdk_bdev_close(ns->desc);
2181  			free(ns);
2182  			return 0;
2183  		}
2184  	}
2185  
2186  	rc = spdk_bdev_module_claim_bdev(ns->bdev, ns->desc, &ns_bdev_module);
2187  	if (rc != 0) {
2188  		spdk_bdev_close(ns->desc);
2189  		free(ns);
2190  		return 0;
2191  	}
2192  
2193  	ns->passthru_nsid = spdk_bdev_get_nvme_nsid(ns->bdev);
2194  	if (subsystem->passthrough && ns->passthru_nsid == 0) {
2195  		SPDK_ERRLOG("Only bdev_nvme namespaces can be added to a passthrough subsystem.\n");
2196  		goto err;
2197  	}
2198  
2199  	/* Cache the zcopy capability of the bdev device */
2200  	ns->zcopy = spdk_bdev_io_type_supported(ns->bdev, SPDK_BDEV_IO_TYPE_ZCOPY);
2201  
2202  	if (spdk_uuid_is_null(&opts.uuid)) {
2203  		opts.uuid = *spdk_bdev_get_uuid(ns->bdev);
2204  	}
2205  
2206  	/* if nguid descriptor is supported by bdev module (nvme) then uuid = nguid */
2207  	if (spdk_mem_all_zero(opts.nguid, sizeof(opts.nguid))) {
2208  		SPDK_STATIC_ASSERT(sizeof(opts.nguid) == sizeof(opts.uuid), "size mismatch");
2209  		memcpy(opts.nguid, spdk_bdev_get_uuid(ns->bdev), sizeof(opts.nguid));
2210  	}
2211  
2212  	if (spdk_bdev_is_zoned(ns->bdev)) {
2213  		SPDK_DEBUGLOG(nvmf, "The added namespace is backed by a zoned block device.\n");
2214  		ns->csi = SPDK_NVME_CSI_ZNS;
2215  
2216  		zone_append_supported = spdk_bdev_io_type_supported(ns->bdev,
2217  					SPDK_BDEV_IO_TYPE_ZONE_APPEND);
2218  		max_zone_append_size_kib = spdk_bdev_get_max_zone_append_size(ns->bdev) *
2219  					   spdk_bdev_desc_get_block_size(ns->desc);
2220  
2221  		if (_nvmf_subsystem_get_first_zoned_ns(subsystem) != NULL &&
2222  		    (nvmf_subsystem_zone_append_supported(subsystem) != zone_append_supported ||
2223  		     subsystem->max_zone_append_size_kib != max_zone_append_size_kib)) {
2224  			SPDK_ERRLOG("Namespaces with different zone append support or different zone append size are not allowed.\n");
2225  			goto err;
2226  		}
2227  
2228  		subsystem->max_zone_append_size_kib = max_zone_append_size_kib;
2229  	}
2230  
2231  	first_ns = spdk_nvmf_subsystem_get_first_ns(subsystem);
2232  	if (!first_ns) {
2233  		if (spdk_bdev_get_nvme_ctratt(ns->bdev).bits.fdps) {
2234  			SPDK_DEBUGLOG(nvmf, "Subsystem with id: %u has FDP capability.\n",
2235  				      subsystem->id);
2236  			subsystem->fdp_supported = true;
2237  		}
2238  	} else {
2239  		if (spdk_bdev_get_nvme_ctratt(first_ns->bdev).bits.fdps !=
2240  		    spdk_bdev_get_nvme_ctratt(ns->bdev).bits.fdps) {
2241  			SPDK_ERRLOG("Subsystem with id: %u can%s FDP namespace.\n", subsystem->id,
2242  				    spdk_bdev_get_nvme_ctratt(first_ns->bdev).bits.fdps ? " only add" : "not add");
2243  			goto err;
2244  		}
2245  	}
2246  
2247  	ns->opts = opts;
2248  	ns->subsystem = subsystem;
2249  	subsystem->ns[opts.nsid - 1] = ns;
2250  	ns->nsid = opts.nsid;
2251  	ns->anagrpid = opts.anagrpid;
2252  	subsystem->ana_group[ns->anagrpid - 1]++;
2253  	TAILQ_INIT(&ns->registrants);
2254  	if (ptpl_file) {
2255  		ns->ptpl_file = strdup(ptpl_file);
2256  		if (!ns->ptpl_file) {
2257  			SPDK_ERRLOG("Namespace ns->ptpl_file allocation failed\n");
2258  			goto err;
2259  		}
2260  	}
2261  
2262  	if (nvmf_ns_is_ptpl_capable(ns)) {
2263  		rc = nvmf_ns_reservation_load(ns, &info);
2264  		if (rc) {
2265  			SPDK_ERRLOG("Subsystem load reservation failed\n");
2266  			goto err;
2267  		}
2268  
2269  		rc = nvmf_ns_reservation_restore(ns, &info);
2270  		if (rc) {
2271  			SPDK_ERRLOG("Subsystem restore reservation failed\n");
2272  			goto err;
2273  		}
2274  	}
2275  
2276  	for (transport = spdk_nvmf_transport_get_first(subsystem->tgt); transport;
2277  	     transport = spdk_nvmf_transport_get_next(transport)) {
2278  		if (transport->ops->subsystem_add_ns) {
2279  			rc = transport->ops->subsystem_add_ns(transport, subsystem, ns);
2280  			if (rc) {
2281  				SPDK_ERRLOG("Namespace attachment is not allowed by %s transport\n", transport->ops->name);
2282  				nvmf_ns_reservation_clear_all_registrants(ns);
2283  				goto err;
2284  			}
2285  		}
2286  	}
2287  
2288  	/* JSON value obj is freed before sending the response. Set NULL to prevent usage of dangling pointer. */
2289  	ns->opts.transport_specific = NULL;
2290  
2291  	SPDK_DEBUGLOG(nvmf, "Subsystem %s: bdev %s assigned nsid %" PRIu32 "\n",
2292  		      spdk_nvmf_subsystem_get_nqn(subsystem),
2293  		      bdev_name,
2294  		      opts.nsid);
2295  
2296  	nvmf_subsystem_ns_changed(subsystem, opts.nsid);
2297  
2298  	SPDK_DTRACE_PROBE2(nvmf_subsystem_add_ns, subsystem->subnqn, ns->nsid);
2299  
2300  	return opts.nsid;
2301  err:
2302  	subsystem->ns[opts.nsid - 1] = NULL;
2303  	spdk_bdev_module_release_bdev(ns->bdev);
2304  	spdk_bdev_close(ns->desc);
2305  	free(ns->ptpl_file);
2306  	free(ns);
2307  
2308  	return 0;
2309  }
2310  
2311  int
2312  spdk_nvmf_subsystem_set_ns_ana_group(struct spdk_nvmf_subsystem *subsystem,
2313  				     uint32_t nsid, uint32_t anagrpid)
2314  {
2315  	struct spdk_nvmf_ns *ns;
2316  
2317  	if (anagrpid > subsystem->max_nsid) {
2318  		SPDK_ERRLOG("ANAGRPID greater than maximum NSID not allowed\n");
2319  		return -1;
2320  	}
2321  
2322  	if (anagrpid == 0) {
2323  		SPDK_ERRLOG("Zero is not allowed to ANAGRPID\n");
2324  		return -1;
2325  	}
2326  
2327  	if (nsid == 0 || nsid > subsystem->max_nsid) {
2328  		return -1;
2329  	}
2330  
2331  	ns = subsystem->ns[nsid - 1];
2332  	if (!ns) {
2333  		return -1;
2334  	}
2335  
2336  	assert(ns->anagrpid - 1 < subsystem->max_nsid);
2337  
2338  	assert(subsystem->ana_group[ns->anagrpid - 1] > 0);
2339  
2340  	subsystem->ana_group[ns->anagrpid - 1]--;
2341  
2342  	subsystem->ana_group[anagrpid - 1]++;
2343  
2344  	ns->anagrpid = anagrpid;
2345  	ns->opts.anagrpid = anagrpid;
2346  
2347  	nvmf_subsystem_ns_changed(subsystem, nsid);
2348  
2349  	return 0;
2350  }
2351  
2352  static uint32_t
2353  nvmf_subsystem_get_next_allocated_nsid(struct spdk_nvmf_subsystem *subsystem,
2354  				       uint32_t prev_nsid)
2355  {
2356  	uint32_t nsid;
2357  
2358  	if (prev_nsid >= subsystem->max_nsid) {
2359  		return 0;
2360  	}
2361  
2362  	for (nsid = prev_nsid + 1; nsid <= subsystem->max_nsid; nsid++) {
2363  		if (subsystem->ns[nsid - 1]) {
2364  			return nsid;
2365  		}
2366  	}
2367  
2368  	return 0;
2369  }
2370  
2371  struct spdk_nvmf_ns *
2372  spdk_nvmf_subsystem_get_first_ns(struct spdk_nvmf_subsystem *subsystem)
2373  {
2374  	uint32_t first_nsid;
2375  
2376  	first_nsid = nvmf_subsystem_get_next_allocated_nsid(subsystem, 0);
2377  	return _nvmf_subsystem_get_ns(subsystem, first_nsid);
2378  }
2379  
2380  struct spdk_nvmf_ns *
2381  spdk_nvmf_subsystem_get_next_ns(struct spdk_nvmf_subsystem *subsystem,
2382  				struct spdk_nvmf_ns *prev_ns)
2383  {
2384  	uint32_t next_nsid;
2385  
2386  	next_nsid = nvmf_subsystem_get_next_allocated_nsid(subsystem, prev_ns->opts.nsid);
2387  	return _nvmf_subsystem_get_ns(subsystem, next_nsid);
2388  }
2389  
2390  struct spdk_nvmf_ns *
2391  spdk_nvmf_subsystem_get_ns(struct spdk_nvmf_subsystem *subsystem, uint32_t nsid)
2392  {
2393  	return _nvmf_subsystem_get_ns(subsystem, nsid);
2394  }
2395  
2396  uint32_t
2397  spdk_nvmf_ns_get_id(const struct spdk_nvmf_ns *ns)
2398  {
2399  	return ns->opts.nsid;
2400  }
2401  
2402  struct spdk_bdev *
2403  spdk_nvmf_ns_get_bdev(struct spdk_nvmf_ns *ns)
2404  {
2405  	return ns->bdev;
2406  }
2407  
2408  void
2409  spdk_nvmf_ns_get_opts(const struct spdk_nvmf_ns *ns, struct spdk_nvmf_ns_opts *opts,
2410  		      size_t opts_size)
2411  {
2412  	memset(opts, 0, opts_size);
2413  	memcpy(opts, &ns->opts, spdk_min(sizeof(ns->opts), opts_size));
2414  }
2415  
2416  const char *
2417  spdk_nvmf_subsystem_get_sn(const struct spdk_nvmf_subsystem *subsystem)
2418  {
2419  	return subsystem->sn;
2420  }
2421  
2422  int
2423  spdk_nvmf_subsystem_set_sn(struct spdk_nvmf_subsystem *subsystem, const char *sn)
2424  {
2425  	size_t len, max_len;
2426  
2427  	max_len = sizeof(subsystem->sn) - 1;
2428  	len = strlen(sn);
2429  	if (len > max_len) {
2430  		SPDK_DEBUGLOG(nvmf, "Invalid sn \"%s\": length %zu > max %zu\n",
2431  			      sn, len, max_len);
2432  		return -1;
2433  	}
2434  
2435  	if (!nvmf_valid_ascii_string(sn, len)) {
2436  		SPDK_DEBUGLOG(nvmf, "Non-ASCII sn\n");
2437  		SPDK_LOGDUMP(nvmf, "sn", sn, len);
2438  		return -1;
2439  	}
2440  
2441  	snprintf(subsystem->sn, sizeof(subsystem->sn), "%s", sn);
2442  
2443  	return 0;
2444  }
2445  
2446  const char *
2447  spdk_nvmf_subsystem_get_mn(const struct spdk_nvmf_subsystem *subsystem)
2448  {
2449  	return subsystem->mn;
2450  }
2451  
2452  int
2453  spdk_nvmf_subsystem_set_mn(struct spdk_nvmf_subsystem *subsystem, const char *mn)
2454  {
2455  	size_t len, max_len;
2456  
2457  	if (mn == NULL) {
2458  		mn = MODEL_NUMBER_DEFAULT;
2459  	}
2460  	max_len = sizeof(subsystem->mn) - 1;
2461  	len = strlen(mn);
2462  	if (len > max_len) {
2463  		SPDK_DEBUGLOG(nvmf, "Invalid mn \"%s\": length %zu > max %zu\n",
2464  			      mn, len, max_len);
2465  		return -1;
2466  	}
2467  
2468  	if (!nvmf_valid_ascii_string(mn, len)) {
2469  		SPDK_DEBUGLOG(nvmf, "Non-ASCII mn\n");
2470  		SPDK_LOGDUMP(nvmf, "mn", mn, len);
2471  		return -1;
2472  	}
2473  
2474  	snprintf(subsystem->mn, sizeof(subsystem->mn), "%s", mn);
2475  
2476  	return 0;
2477  }
2478  
2479  const char *
2480  spdk_nvmf_subsystem_get_nqn(const struct spdk_nvmf_subsystem *subsystem)
2481  {
2482  	return subsystem->subnqn;
2483  }
2484  
2485  /* We have to use the typedef in the function declaration to appease astyle. */
2486  typedef enum spdk_nvmf_subtype spdk_nvmf_subtype_t;
2487  
2488  spdk_nvmf_subtype_t
2489  spdk_nvmf_subsystem_get_type(struct spdk_nvmf_subsystem *subsystem)
2490  {
2491  	return subsystem->subtype;
2492  }
2493  
2494  uint32_t
2495  spdk_nvmf_subsystem_get_max_nsid(struct spdk_nvmf_subsystem *subsystem)
2496  {
2497  	return subsystem->max_nsid;
2498  }
2499  
2500  int
2501  spdk_nvmf_subsystem_set_cntlid_range(struct spdk_nvmf_subsystem *subsystem,
2502  				     uint16_t min_cntlid, uint16_t max_cntlid)
2503  {
2504  	if (subsystem->state != SPDK_NVMF_SUBSYSTEM_INACTIVE) {
2505  		return -EAGAIN;
2506  	}
2507  
2508  	if (min_cntlid > max_cntlid) {
2509  		return -EINVAL;
2510  	}
2511  	/* The spec reserves cntlid values in the range FFF0h to FFFFh. */
2512  	if (min_cntlid < NVMF_MIN_CNTLID || min_cntlid > NVMF_MAX_CNTLID ||
2513  	    max_cntlid < NVMF_MIN_CNTLID || max_cntlid > NVMF_MAX_CNTLID) {
2514  		return -EINVAL;
2515  	}
2516  	subsystem->min_cntlid = min_cntlid;
2517  	subsystem->max_cntlid = max_cntlid;
2518  	if (subsystem->next_cntlid < min_cntlid || subsystem->next_cntlid > max_cntlid) {
2519  		subsystem->next_cntlid = min_cntlid;
2520  	}
2521  
2522  	return 0;
2523  }
2524  
2525  uint16_t
2526  nvmf_subsystem_gen_cntlid(struct spdk_nvmf_subsystem *subsystem)
2527  {
2528  	int count;
2529  	uint16_t cntlid;
2530  
2531  	/*
2532  	 * In the worst case, we might have to try all CNTLID values between min_cntlid and max_cntlid
2533  	 * before we find one that is unused (or find that all values are in use).
2534  	 */
2535  	for (count = 0; count < subsystem->max_cntlid - subsystem->min_cntlid + 1; count++) {
2536  		cntlid = subsystem->next_cntlid;
2537  		subsystem->next_cntlid++;
2538  
2539  		if (subsystem->next_cntlid > subsystem->max_cntlid) {
2540  			subsystem->next_cntlid = subsystem->min_cntlid;
2541  		}
2542  
2543  		/* Check if a controller with this cntlid currently exists. */
2544  		if (nvmf_subsystem_get_ctrlr(subsystem, cntlid) == NULL) {
2545  			/* Found unused cntlid */
2546  			return cntlid;
2547  		}
2548  	}
2549  
2550  	/* All valid cntlid values are in use. */
2551  	return 0xFFFF;
2552  }
2553  
2554  int
2555  nvmf_subsystem_add_ctrlr(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *ctrlr)
2556  {
2557  
2558  	if (ctrlr->dynamic_ctrlr) {
2559  		ctrlr->cntlid = nvmf_subsystem_gen_cntlid(subsystem);
2560  		if (ctrlr->cntlid == 0xFFFF) {
2561  			/* Unable to get a cntlid */
2562  			SPDK_ERRLOG("Reached max simultaneous ctrlrs\n");
2563  			return -EBUSY;
2564  		}
2565  	} else if (nvmf_subsystem_get_ctrlr(subsystem, ctrlr->cntlid) != NULL) {
2566  		SPDK_ERRLOG("Ctrlr with cntlid %u already exist\n", ctrlr->cntlid);
2567  		return -EEXIST;
2568  	}
2569  
2570  	TAILQ_INSERT_TAIL(&subsystem->ctrlrs, ctrlr, link);
2571  
2572  	SPDK_DTRACE_PROBE3(nvmf_subsystem_add_ctrlr, subsystem->subnqn, ctrlr, ctrlr->hostnqn);
2573  
2574  	return 0;
2575  }
2576  
2577  void
2578  nvmf_subsystem_remove_ctrlr(struct spdk_nvmf_subsystem *subsystem,
2579  			    struct spdk_nvmf_ctrlr *ctrlr)
2580  {
2581  	SPDK_DTRACE_PROBE3(nvmf_subsystem_remove_ctrlr, subsystem->subnqn, ctrlr, ctrlr->hostnqn);
2582  
2583  	assert(spdk_get_thread() == subsystem->thread);
2584  	assert(subsystem == ctrlr->subsys);
2585  	SPDK_DEBUGLOG(nvmf, "remove ctrlr %p id 0x%x from subsys %p %s\n", ctrlr, ctrlr->cntlid, subsystem,
2586  		      subsystem->subnqn);
2587  	TAILQ_REMOVE(&subsystem->ctrlrs, ctrlr, link);
2588  }
2589  
2590  struct spdk_nvmf_ctrlr *
2591  nvmf_subsystem_get_ctrlr(struct spdk_nvmf_subsystem *subsystem, uint16_t cntlid)
2592  {
2593  	struct spdk_nvmf_ctrlr *ctrlr;
2594  
2595  	TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) {
2596  		if (ctrlr->cntlid == cntlid) {
2597  			return ctrlr;
2598  		}
2599  	}
2600  
2601  	return NULL;
2602  }
2603  
2604  uint32_t
2605  spdk_nvmf_subsystem_get_max_namespaces(const struct spdk_nvmf_subsystem *subsystem)
2606  {
2607  	return subsystem->max_nsid;
2608  }
2609  
2610  uint16_t
2611  spdk_nvmf_subsystem_get_min_cntlid(const struct spdk_nvmf_subsystem *subsystem)
2612  {
2613  	return subsystem->min_cntlid;
2614  }
2615  
2616  uint16_t
2617  spdk_nvmf_subsystem_get_max_cntlid(const struct spdk_nvmf_subsystem *subsystem)
2618  {
2619  	return subsystem->max_cntlid;
2620  }
2621  
2622  struct _nvmf_ns_registrant {
2623  	uint64_t		rkey;
2624  	char			*host_uuid;
2625  };
2626  
2627  struct _nvmf_ns_registrants {
2628  	size_t				num_regs;
2629  	struct _nvmf_ns_registrant	reg[SPDK_NVMF_MAX_NUM_REGISTRANTS];
2630  };
2631  
2632  struct _nvmf_ns_reservation {
2633  	bool					ptpl_activated;
2634  	enum spdk_nvme_reservation_type		rtype;
2635  	uint64_t				crkey;
2636  	char					*bdev_uuid;
2637  	char					*holder_uuid;
2638  	struct _nvmf_ns_registrants		regs;
2639  };
2640  
2641  static const struct spdk_json_object_decoder nvmf_ns_pr_reg_decoders[] = {
2642  	{"rkey", offsetof(struct _nvmf_ns_registrant, rkey), spdk_json_decode_uint64},
2643  	{"host_uuid", offsetof(struct _nvmf_ns_registrant, host_uuid), spdk_json_decode_string},
2644  };
2645  
2646  static int
2647  nvmf_decode_ns_pr_reg(const struct spdk_json_val *val, void *out)
2648  {
2649  	struct _nvmf_ns_registrant *reg = out;
2650  
2651  	return spdk_json_decode_object(val, nvmf_ns_pr_reg_decoders,
2652  				       SPDK_COUNTOF(nvmf_ns_pr_reg_decoders), reg);
2653  }
2654  
2655  static int
2656  nvmf_decode_ns_pr_regs(const struct spdk_json_val *val, void *out)
2657  {
2658  	struct _nvmf_ns_registrants *regs = out;
2659  
2660  	return spdk_json_decode_array(val, nvmf_decode_ns_pr_reg, regs->reg,
2661  				      SPDK_NVMF_MAX_NUM_REGISTRANTS, &regs->num_regs,
2662  				      sizeof(struct _nvmf_ns_registrant));
2663  }
2664  
2665  static const struct spdk_json_object_decoder nvmf_ns_pr_decoders[] = {
2666  	{"ptpl", offsetof(struct _nvmf_ns_reservation, ptpl_activated), spdk_json_decode_bool, true},
2667  	{"rtype", offsetof(struct _nvmf_ns_reservation, rtype), spdk_json_decode_uint32, true},
2668  	{"crkey", offsetof(struct _nvmf_ns_reservation, crkey), spdk_json_decode_uint64, true},
2669  	{"bdev_uuid", offsetof(struct _nvmf_ns_reservation, bdev_uuid), spdk_json_decode_string},
2670  	{"holder_uuid", offsetof(struct _nvmf_ns_reservation, holder_uuid), spdk_json_decode_string, true},
2671  	{"registrants", offsetof(struct _nvmf_ns_reservation, regs), nvmf_decode_ns_pr_regs},
2672  };
2673  
2674  static int
2675  nvmf_ns_reservation_load_json(const struct spdk_nvmf_ns *ns,
2676  			      struct spdk_nvmf_reservation_info *info)
2677  {
2678  	size_t json_size;
2679  	ssize_t values_cnt, rc;
2680  	void *json = NULL, *end;
2681  	struct spdk_json_val *values = NULL;
2682  	struct _nvmf_ns_reservation res = {};
2683  	const char *file = ns->ptpl_file;
2684  	uint32_t i;
2685  
2686  	/* It's not an error if the file does not exist */
2687  	if (access(file, F_OK) != 0) {
2688  		SPDK_DEBUGLOG(nvmf, "File %s does not exist\n", file);
2689  		return 0;
2690  	}
2691  
2692  	/* Load all persist file contents into a local buffer */
2693  	json = spdk_posix_file_load_from_name(file, &json_size);
2694  	if (!json) {
2695  		SPDK_ERRLOG("Load persist file %s failed\n", file);
2696  		return -ENOMEM;
2697  	}
2698  
2699  	rc = spdk_json_parse(json, json_size, NULL, 0, &end, 0);
2700  	if (rc < 0) {
2701  		SPDK_NOTICELOG("Parsing JSON configuration failed (%zd)\n", rc);
2702  		goto exit;
2703  	}
2704  
2705  	values_cnt = rc;
2706  	values = calloc(values_cnt, sizeof(struct spdk_json_val));
2707  	if (values == NULL) {
2708  		goto exit;
2709  	}
2710  
2711  	rc = spdk_json_parse(json, json_size, values, values_cnt, &end, 0);
2712  	if (rc != values_cnt) {
2713  		SPDK_ERRLOG("Parsing JSON configuration failed (%zd)\n", rc);
2714  		goto exit;
2715  	}
2716  
2717  	/* Decode json */
2718  	if (spdk_json_decode_object(values, nvmf_ns_pr_decoders,
2719  				    SPDK_COUNTOF(nvmf_ns_pr_decoders),
2720  				    &res)) {
2721  		SPDK_ERRLOG("Invalid objects in the persist file %s\n", file);
2722  		rc = -EINVAL;
2723  		goto exit;
2724  	}
2725  
2726  	if (res.regs.num_regs > SPDK_NVMF_MAX_NUM_REGISTRANTS) {
2727  		SPDK_ERRLOG("Can only support up to %u registrants\n", SPDK_NVMF_MAX_NUM_REGISTRANTS);
2728  		rc = -ERANGE;
2729  		goto exit;
2730  	}
2731  
2732  	rc = 0;
2733  	info->ptpl_activated = res.ptpl_activated;
2734  	info->rtype = res.rtype;
2735  	info->crkey = res.crkey;
2736  	snprintf(info->bdev_uuid, sizeof(info->bdev_uuid), "%s", res.bdev_uuid);
2737  	snprintf(info->holder_uuid, sizeof(info->holder_uuid), "%s", res.holder_uuid);
2738  	info->num_regs = res.regs.num_regs;
2739  	for (i = 0; i < res.regs.num_regs; i++) {
2740  		info->registrants[i].rkey = res.regs.reg[i].rkey;
2741  		snprintf(info->registrants[i].host_uuid, sizeof(info->registrants[i].host_uuid), "%s",
2742  			 res.regs.reg[i].host_uuid);
2743  	}
2744  
2745  exit:
2746  	free(json);
2747  	free(values);
2748  	free(res.bdev_uuid);
2749  	free(res.holder_uuid);
2750  	for (i = 0; i < res.regs.num_regs; i++) {
2751  		free(res.regs.reg[i].host_uuid);
2752  	}
2753  
2754  	return rc;
2755  }
2756  
2757  static bool nvmf_ns_reservation_all_registrants_type(struct spdk_nvmf_ns *ns);
2758  
2759  static int
2760  nvmf_ns_reservation_restore(struct spdk_nvmf_ns *ns, struct spdk_nvmf_reservation_info *info)
2761  {
2762  	uint32_t i;
2763  	struct spdk_nvmf_registrant *reg, *holder = NULL;
2764  	struct spdk_uuid bdev_uuid, holder_uuid;
2765  	bool rkey_flag = false;
2766  
2767  	SPDK_DEBUGLOG(nvmf, "NSID %u, PTPL %u, Number of registrants %u\n",
2768  		      ns->nsid, info->ptpl_activated, info->num_regs);
2769  
2770  	/* it's not an error */
2771  	if (!info->ptpl_activated || !info->num_regs) {
2772  		return 0;
2773  	}
2774  
2775  	/* Check info->crkey exist or not in info->registrants[i].rkey */
2776  	for (i = 0; i < info->num_regs; i++) {
2777  		if (info->crkey == info->registrants[i].rkey) {
2778  			rkey_flag = true;
2779  		}
2780  	}
2781  	if (!rkey_flag && info->crkey != 0) {
2782  		return -EINVAL;
2783  	}
2784  
2785  	spdk_uuid_parse(&bdev_uuid, info->bdev_uuid);
2786  	if (spdk_uuid_compare(&bdev_uuid, spdk_bdev_get_uuid(ns->bdev))) {
2787  		SPDK_ERRLOG("Existing bdev UUID is not same with configuration file\n");
2788  		return -EINVAL;
2789  	}
2790  
2791  	ns->crkey = info->crkey;
2792  	ns->rtype = info->rtype;
2793  	ns->ptpl_activated = info->ptpl_activated;
2794  	spdk_uuid_parse(&holder_uuid, info->holder_uuid);
2795  
2796  	SPDK_DEBUGLOG(nvmf, "Bdev UUID %s\n", info->bdev_uuid);
2797  	if (info->rtype) {
2798  		SPDK_DEBUGLOG(nvmf, "Holder UUID %s, RTYPE %u, RKEY 0x%"PRIx64"\n",
2799  			      info->holder_uuid, info->rtype, info->crkey);
2800  	}
2801  
2802  	for (i = 0; i < info->num_regs; i++) {
2803  		reg = calloc(1, sizeof(*reg));
2804  		if (!reg) {
2805  			return -ENOMEM;
2806  		}
2807  		spdk_uuid_parse(&reg->hostid, info->registrants[i].host_uuid);
2808  		reg->rkey = info->registrants[i].rkey;
2809  		TAILQ_INSERT_TAIL(&ns->registrants, reg, link);
2810  		if (info->crkey != 0 && !spdk_uuid_compare(&holder_uuid, &reg->hostid)) {
2811  			holder = reg;
2812  		}
2813  		SPDK_DEBUGLOG(nvmf, "Registrant RKEY 0x%"PRIx64", Host UUID %s\n",
2814  			      info->registrants[i].rkey, info->registrants[i].host_uuid);
2815  	}
2816  
2817  	if (nvmf_ns_reservation_all_registrants_type(ns)) {
2818  		ns->holder = TAILQ_FIRST(&ns->registrants);
2819  	} else {
2820  		ns->holder = holder;
2821  	}
2822  
2823  	return 0;
2824  }
2825  
2826  static int
2827  nvmf_ns_json_write_cb(void *cb_ctx, const void *data, size_t size)
2828  {
2829  	char *file = cb_ctx;
2830  	size_t rc;
2831  	FILE *fd;
2832  
2833  	fd = fopen(file, "w");
2834  	if (!fd) {
2835  		SPDK_ERRLOG("Can't open file %s for write\n", file);
2836  		return -ENOENT;
2837  	}
2838  	rc = fwrite(data, 1, size, fd);
2839  	fclose(fd);
2840  
2841  	return rc == size ? 0 : -1;
2842  }
2843  
2844  static int
2845  nvmf_ns_reservation_update_json(const struct spdk_nvmf_ns *ns,
2846  				const struct spdk_nvmf_reservation_info *info)
2847  {
2848  	const char *file = ns->ptpl_file;
2849  	struct spdk_json_write_ctx *w;
2850  	uint32_t i;
2851  	int rc = 0;
2852  
2853  	w = spdk_json_write_begin(nvmf_ns_json_write_cb, (void *)file, 0);
2854  	if (w == NULL) {
2855  		return -ENOMEM;
2856  	}
2857  	/* clear the configuration file */
2858  	if (!info->ptpl_activated) {
2859  		goto exit;
2860  	}
2861  
2862  	spdk_json_write_object_begin(w);
2863  	spdk_json_write_named_bool(w, "ptpl", info->ptpl_activated);
2864  	spdk_json_write_named_uint32(w, "rtype", info->rtype);
2865  	spdk_json_write_named_uint64(w, "crkey", info->crkey);
2866  	spdk_json_write_named_string(w, "bdev_uuid", info->bdev_uuid);
2867  	spdk_json_write_named_string(w, "holder_uuid", info->holder_uuid);
2868  
2869  	spdk_json_write_named_array_begin(w, "registrants");
2870  	for (i = 0; i < info->num_regs; i++) {
2871  		spdk_json_write_object_begin(w);
2872  		spdk_json_write_named_uint64(w, "rkey", info->registrants[i].rkey);
2873  		spdk_json_write_named_string(w, "host_uuid", info->registrants[i].host_uuid);
2874  		spdk_json_write_object_end(w);
2875  	}
2876  	spdk_json_write_array_end(w);
2877  	spdk_json_write_object_end(w);
2878  
2879  exit:
2880  	rc = spdk_json_write_end(w);
2881  	return rc;
2882  }
2883  
2884  static int
2885  nvmf_ns_update_reservation_info(struct spdk_nvmf_ns *ns)
2886  {
2887  	struct spdk_nvmf_reservation_info info;
2888  	struct spdk_nvmf_registrant *reg, *tmp;
2889  	uint32_t i = 0;
2890  
2891  	assert(ns != NULL);
2892  
2893  	if (!ns->bdev || !nvmf_ns_is_ptpl_capable(ns)) {
2894  		return 0;
2895  	}
2896  
2897  	memset(&info, 0, sizeof(info));
2898  	spdk_uuid_fmt_lower(info.bdev_uuid, sizeof(info.bdev_uuid), spdk_bdev_get_uuid(ns->bdev));
2899  
2900  	if (ns->rtype) {
2901  		info.rtype = ns->rtype;
2902  		info.crkey = ns->crkey;
2903  		if (!nvmf_ns_reservation_all_registrants_type(ns)) {
2904  			assert(ns->holder != NULL);
2905  			spdk_uuid_fmt_lower(info.holder_uuid, sizeof(info.holder_uuid), &ns->holder->hostid);
2906  		}
2907  	}
2908  
2909  	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) {
2910  		spdk_uuid_fmt_lower(info.registrants[i].host_uuid, sizeof(info.registrants[i].host_uuid),
2911  				    &reg->hostid);
2912  		info.registrants[i++].rkey = reg->rkey;
2913  	}
2914  
2915  	info.num_regs = i;
2916  	info.ptpl_activated = ns->ptpl_activated;
2917  
2918  	return nvmf_ns_reservation_update(ns, &info);
2919  }
2920  
2921  static struct spdk_nvmf_registrant *
2922  nvmf_ns_reservation_get_registrant(struct spdk_nvmf_ns *ns,
2923  				   struct spdk_uuid *uuid)
2924  {
2925  	struct spdk_nvmf_registrant *reg, *tmp;
2926  
2927  	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) {
2928  		if (!spdk_uuid_compare(&reg->hostid, uuid)) {
2929  			return reg;
2930  		}
2931  	}
2932  
2933  	return NULL;
2934  }
2935  
2936  /* Generate reservation notice log to registered HostID controllers */
2937  static void
2938  nvmf_subsystem_gen_ctrlr_notification(struct spdk_nvmf_subsystem *subsystem,
2939  				      struct spdk_nvmf_ns *ns,
2940  				      struct spdk_uuid *hostid_list,
2941  				      uint32_t num_hostid,
2942  				      enum spdk_nvme_reservation_notification_log_page_type type)
2943  {
2944  	struct spdk_nvmf_ctrlr *ctrlr;
2945  	uint32_t i;
2946  
2947  	for (i = 0; i < num_hostid; i++) {
2948  		TAILQ_FOREACH(ctrlr, &subsystem->ctrlrs, link) {
2949  			if (!spdk_uuid_compare(&ctrlr->hostid, &hostid_list[i])) {
2950  				nvmf_ctrlr_reservation_notice_log(ctrlr, ns, type);
2951  			}
2952  		}
2953  	}
2954  }
2955  
2956  /* Get all registrants' hostid other than the controller who issued the command */
2957  static uint32_t
2958  nvmf_ns_reservation_get_all_other_hostid(struct spdk_nvmf_ns *ns,
2959  		struct spdk_uuid *hostid_list,
2960  		uint32_t max_num_hostid,
2961  		struct spdk_uuid *current_hostid)
2962  {
2963  	struct spdk_nvmf_registrant *reg, *tmp;
2964  	uint32_t num_hostid = 0;
2965  
2966  	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) {
2967  		if (spdk_uuid_compare(&reg->hostid, current_hostid)) {
2968  			if (num_hostid == max_num_hostid) {
2969  				assert(false);
2970  				return max_num_hostid;
2971  			}
2972  			hostid_list[num_hostid++] = reg->hostid;
2973  		}
2974  	}
2975  
2976  	return num_hostid;
2977  }
2978  
2979  /* Calculate the unregistered HostID list according to list
2980   * prior to execute preempt command and list after executing
2981   * preempt command.
2982   */
2983  static uint32_t
2984  nvmf_ns_reservation_get_unregistered_hostid(struct spdk_uuid *old_hostid_list,
2985  		uint32_t old_num_hostid,
2986  		struct spdk_uuid *remaining_hostid_list,
2987  		uint32_t remaining_num_hostid)
2988  {
2989  	struct spdk_uuid temp_hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS];
2990  	uint32_t i, j, num_hostid = 0;
2991  	bool found;
2992  
2993  	if (!remaining_num_hostid) {
2994  		return old_num_hostid;
2995  	}
2996  
2997  	for (i = 0; i < old_num_hostid; i++) {
2998  		found = false;
2999  		for (j = 0; j < remaining_num_hostid; j++) {
3000  			if (!spdk_uuid_compare(&old_hostid_list[i], &remaining_hostid_list[j])) {
3001  				found = true;
3002  				break;
3003  			}
3004  		}
3005  		if (!found) {
3006  			spdk_uuid_copy(&temp_hostid_list[num_hostid++], &old_hostid_list[i]);
3007  		}
3008  	}
3009  
3010  	if (num_hostid) {
3011  		memcpy(old_hostid_list, temp_hostid_list, sizeof(struct spdk_uuid) * num_hostid);
3012  	}
3013  
3014  	return num_hostid;
3015  }
3016  
3017  /* current reservation type is all registrants or not */
3018  static bool
3019  nvmf_ns_reservation_all_registrants_type(struct spdk_nvmf_ns *ns)
3020  {
3021  	return (ns->rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS ||
3022  		ns->rtype == SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_ALL_REGS);
3023  }
3024  
3025  /* current registrant is reservation holder or not */
3026  static bool
3027  nvmf_ns_reservation_registrant_is_holder(struct spdk_nvmf_ns *ns,
3028  		struct spdk_nvmf_registrant *reg)
3029  {
3030  	if (!reg) {
3031  		return false;
3032  	}
3033  
3034  	if (nvmf_ns_reservation_all_registrants_type(ns)) {
3035  		return true;
3036  	}
3037  
3038  	return (ns->holder == reg);
3039  }
3040  
3041  static int
3042  nvmf_ns_reservation_add_registrant(struct spdk_nvmf_ns *ns,
3043  				   struct spdk_nvmf_ctrlr *ctrlr,
3044  				   uint64_t nrkey)
3045  {
3046  	struct spdk_nvmf_registrant *reg;
3047  
3048  	reg = calloc(1, sizeof(*reg));
3049  	if (!reg) {
3050  		return -ENOMEM;
3051  	}
3052  
3053  	reg->rkey = nrkey;
3054  	/* set hostid for the registrant */
3055  	spdk_uuid_copy(&reg->hostid, &ctrlr->hostid);
3056  	TAILQ_INSERT_TAIL(&ns->registrants, reg, link);
3057  	ns->gen++;
3058  
3059  	return 0;
3060  }
3061  
3062  static void
3063  nvmf_ns_reservation_release_reservation(struct spdk_nvmf_ns *ns)
3064  {
3065  	ns->rtype = 0;
3066  	ns->crkey = 0;
3067  	ns->holder = NULL;
3068  }
3069  
3070  /* release the reservation if the last registrant was removed */
3071  static void
3072  nvmf_ns_reservation_check_release_on_remove_registrant(struct spdk_nvmf_ns *ns,
3073  		struct spdk_nvmf_registrant *reg)
3074  {
3075  	struct spdk_nvmf_registrant *next_reg;
3076  
3077  	/* no reservation holder */
3078  	if (!ns->holder) {
3079  		assert(ns->rtype == 0);
3080  		return;
3081  	}
3082  
3083  	next_reg = TAILQ_FIRST(&ns->registrants);
3084  	if (next_reg && nvmf_ns_reservation_all_registrants_type(ns)) {
3085  		/* the next valid registrant is the new holder now */
3086  		ns->holder = next_reg;
3087  	} else if (nvmf_ns_reservation_registrant_is_holder(ns, reg)) {
3088  		/* release the reservation */
3089  		nvmf_ns_reservation_release_reservation(ns);
3090  	}
3091  }
3092  
3093  static void
3094  nvmf_ns_reservation_remove_registrant(struct spdk_nvmf_ns *ns,
3095  				      struct spdk_nvmf_registrant *reg)
3096  {
3097  	TAILQ_REMOVE(&ns->registrants, reg, link);
3098  	nvmf_ns_reservation_check_release_on_remove_registrant(ns, reg);
3099  	free(reg);
3100  	ns->gen++;
3101  	return;
3102  }
3103  
3104  static uint32_t
3105  nvmf_ns_reservation_remove_registrants_by_key(struct spdk_nvmf_ns *ns,
3106  		uint64_t rkey)
3107  {
3108  	struct spdk_nvmf_registrant *reg, *tmp;
3109  	uint32_t count = 0;
3110  
3111  	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) {
3112  		if (reg->rkey == rkey) {
3113  			nvmf_ns_reservation_remove_registrant(ns, reg);
3114  			count++;
3115  		}
3116  	}
3117  	return count;
3118  }
3119  
3120  static uint32_t
3121  nvmf_ns_reservation_remove_all_other_registrants(struct spdk_nvmf_ns *ns,
3122  		struct spdk_nvmf_registrant *reg)
3123  {
3124  	struct spdk_nvmf_registrant *reg_tmp, *reg_tmp2;
3125  	uint32_t count = 0;
3126  
3127  	TAILQ_FOREACH_SAFE(reg_tmp, &ns->registrants, link, reg_tmp2) {
3128  		if (reg_tmp != reg) {
3129  			nvmf_ns_reservation_remove_registrant(ns, reg_tmp);
3130  			count++;
3131  		}
3132  	}
3133  	return count;
3134  }
3135  
3136  static uint32_t
3137  nvmf_ns_reservation_clear_all_registrants(struct spdk_nvmf_ns *ns)
3138  {
3139  	struct spdk_nvmf_registrant *reg, *reg_tmp;
3140  	uint32_t count = 0;
3141  
3142  	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, reg_tmp) {
3143  		nvmf_ns_reservation_remove_registrant(ns, reg);
3144  		count++;
3145  	}
3146  	return count;
3147  }
3148  
3149  static void
3150  nvmf_ns_reservation_acquire_reservation(struct spdk_nvmf_ns *ns, uint64_t rkey,
3151  					enum spdk_nvme_reservation_type rtype,
3152  					struct spdk_nvmf_registrant *holder)
3153  {
3154  	ns->rtype = rtype;
3155  	ns->crkey = rkey;
3156  	assert(ns->holder == NULL);
3157  	ns->holder = holder;
3158  }
3159  
3160  static bool
3161  nvmf_ns_reservation_register(struct spdk_nvmf_ns *ns,
3162  			     struct spdk_nvmf_ctrlr *ctrlr,
3163  			     struct spdk_nvmf_request *req)
3164  {
3165  	struct spdk_nvme_reservation_register_data key = { 0 };
3166  	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
3167  	uint8_t rrega, iekey, cptpl, rtype;
3168  	struct spdk_nvmf_registrant *reg;
3169  	uint8_t status = SPDK_NVME_SC_SUCCESS;
3170  	bool update_sgroup = false;
3171  	struct spdk_uuid hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS];
3172  	uint32_t num_hostid = 0;
3173  	int rc;
3174  
3175  	rrega = cmd->cdw10_bits.resv_register.rrega;
3176  	iekey = cmd->cdw10_bits.resv_register.iekey;
3177  	cptpl = cmd->cdw10_bits.resv_register.cptpl;
3178  
3179  	if (req->iovcnt > 0 && req->length >= sizeof(key)) {
3180  		struct spdk_iov_xfer ix;
3181  		spdk_iov_xfer_init(&ix, req->iov, req->iovcnt);
3182  		spdk_iov_xfer_to_buf(&ix, &key, sizeof(key));
3183  	} else {
3184  		SPDK_ERRLOG("No key provided. Failing request.\n");
3185  		status = SPDK_NVME_SC_INVALID_FIELD;
3186  		goto exit;
3187  	}
3188  
3189  	SPDK_DEBUGLOG(nvmf, "REGISTER: RREGA %u, IEKEY %u, CPTPL %u, "
3190  		      "NRKEY 0x%"PRIx64", NRKEY 0x%"PRIx64"\n",
3191  		      rrega, iekey, cptpl, key.crkey, key.nrkey);
3192  
3193  	if (cptpl == SPDK_NVME_RESERVE_PTPL_CLEAR_POWER_ON) {
3194  		/* True to OFF state, and need to be updated in the configuration file */
3195  		if (ns->ptpl_activated) {
3196  			ns->ptpl_activated = 0;
3197  			update_sgroup = true;
3198  		}
3199  	} else if (cptpl == SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS) {
3200  		if (!nvmf_ns_is_ptpl_capable(ns)) {
3201  			status = SPDK_NVME_SC_INVALID_FIELD;
3202  			goto exit;
3203  		} else if (ns->ptpl_activated == 0) {
3204  			ns->ptpl_activated = 1;
3205  			update_sgroup = true;
3206  		}
3207  	}
3208  
3209  	/* current Host Identifier has registrant or not */
3210  	reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid);
3211  
3212  	switch (rrega) {
3213  	case SPDK_NVME_RESERVE_REGISTER_KEY:
3214  		if (!reg) {
3215  			/* register new controller */
3216  			if (key.nrkey == 0) {
3217  				SPDK_ERRLOG("Can't register zeroed new key\n");
3218  				status = SPDK_NVME_SC_INVALID_FIELD;
3219  				goto exit;
3220  			}
3221  			rc = nvmf_ns_reservation_add_registrant(ns, ctrlr, key.nrkey);
3222  			if (rc < 0) {
3223  				status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
3224  				goto exit;
3225  			}
3226  			update_sgroup = true;
3227  		} else {
3228  			/* register with same key is not an error */
3229  			if (reg->rkey != key.nrkey) {
3230  				SPDK_ERRLOG("The same host already register a "
3231  					    "key with 0x%"PRIx64"\n",
3232  					    reg->rkey);
3233  				status = SPDK_NVME_SC_RESERVATION_CONFLICT;
3234  				goto exit;
3235  			}
3236  		}
3237  		break;
3238  	case SPDK_NVME_RESERVE_UNREGISTER_KEY:
3239  		if (!reg || (!iekey && reg->rkey != key.crkey)) {
3240  			SPDK_ERRLOG("No registrant or current key doesn't match "
3241  				    "with existing registrant key\n");
3242  			status = SPDK_NVME_SC_RESERVATION_CONFLICT;
3243  			goto exit;
3244  		}
3245  
3246  		rtype = ns->rtype;
3247  		num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, hostid_list,
3248  				SPDK_NVMF_MAX_NUM_REGISTRANTS,
3249  				&ctrlr->hostid);
3250  
3251  		nvmf_ns_reservation_remove_registrant(ns, reg);
3252  
3253  		if (!ns->rtype && num_hostid && (rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY ||
3254  						 rtype == SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY)) {
3255  			nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns,
3256  							      hostid_list,
3257  							      num_hostid,
3258  							      SPDK_NVME_RESERVATION_RELEASED);
3259  		}
3260  		update_sgroup = true;
3261  		break;
3262  	case SPDK_NVME_RESERVE_REPLACE_KEY:
3263  		if (key.nrkey == 0) {
3264  			SPDK_ERRLOG("Can't register zeroed new key\n");
3265  			status = SPDK_NVME_SC_INVALID_FIELD;
3266  			goto exit;
3267  		}
3268  		/* Registrant exists */
3269  		if (reg) {
3270  			if (!iekey && reg->rkey != key.crkey) {
3271  				SPDK_ERRLOG("Current key doesn't match "
3272  					    "existing registrant key\n");
3273  				status = SPDK_NVME_SC_RESERVATION_CONFLICT;
3274  				goto exit;
3275  			}
3276  			if (reg->rkey == key.nrkey) {
3277  				goto exit;
3278  			}
3279  			reg->rkey = key.nrkey;
3280  		} else if (iekey) { /* No registrant but IEKEY is set */
3281  			/* new registrant */
3282  			rc = nvmf_ns_reservation_add_registrant(ns, ctrlr, key.nrkey);
3283  			if (rc < 0) {
3284  				status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
3285  				goto exit;
3286  			}
3287  		} else { /* No registrant */
3288  			SPDK_ERRLOG("No registrant\n");
3289  			status = SPDK_NVME_SC_RESERVATION_CONFLICT;
3290  			goto exit;
3291  
3292  		}
3293  		update_sgroup = true;
3294  		break;
3295  	default:
3296  		status = SPDK_NVME_SC_INVALID_FIELD;
3297  		goto exit;
3298  	}
3299  
3300  exit:
3301  	req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC;
3302  	req->rsp->nvme_cpl.status.sc = status;
3303  	return update_sgroup;
3304  }
3305  
3306  static bool
3307  nvmf_ns_reservation_acquire(struct spdk_nvmf_ns *ns,
3308  			    struct spdk_nvmf_ctrlr *ctrlr,
3309  			    struct spdk_nvmf_request *req)
3310  {
3311  	struct spdk_nvme_reservation_acquire_data key = { 0 };
3312  	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
3313  	uint8_t racqa, iekey, rtype;
3314  	struct spdk_nvmf_registrant *reg;
3315  	bool all_regs = false;
3316  	uint32_t count = 0;
3317  	bool update_sgroup = true;
3318  	struct spdk_uuid hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS];
3319  	uint32_t num_hostid = 0;
3320  	struct spdk_uuid new_hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS];
3321  	uint32_t new_num_hostid = 0;
3322  	bool reservation_released = false;
3323  	uint8_t status = SPDK_NVME_SC_SUCCESS;
3324  
3325  	racqa = cmd->cdw10_bits.resv_acquire.racqa;
3326  	iekey = cmd->cdw10_bits.resv_acquire.iekey;
3327  	rtype = cmd->cdw10_bits.resv_acquire.rtype;
3328  
3329  	if (req->iovcnt > 0 && req->length >= sizeof(key)) {
3330  		struct spdk_iov_xfer ix;
3331  		spdk_iov_xfer_init(&ix, req->iov, req->iovcnt);
3332  		spdk_iov_xfer_to_buf(&ix, &key, sizeof(key));
3333  	} else {
3334  		SPDK_ERRLOG("No key provided. Failing request.\n");
3335  		status = SPDK_NVME_SC_INVALID_FIELD;
3336  		goto exit;
3337  	}
3338  
3339  	SPDK_DEBUGLOG(nvmf, "ACQUIRE: RACQA %u, IEKEY %u, RTYPE %u, "
3340  		      "NRKEY 0x%"PRIx64", PRKEY 0x%"PRIx64"\n",
3341  		      racqa, iekey, rtype, key.crkey, key.prkey);
3342  
3343  	if (iekey || rtype > SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_ALL_REGS) {
3344  		SPDK_ERRLOG("Ignore existing key field set to 1\n");
3345  		status = SPDK_NVME_SC_INVALID_FIELD;
3346  		update_sgroup = false;
3347  		goto exit;
3348  	}
3349  
3350  	reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid);
3351  	/* must be registrant and CRKEY must match */
3352  	if (!reg || reg->rkey != key.crkey) {
3353  		SPDK_ERRLOG("No registrant or current key doesn't match "
3354  			    "with existing registrant key\n");
3355  		status = SPDK_NVME_SC_RESERVATION_CONFLICT;
3356  		update_sgroup = false;
3357  		goto exit;
3358  	}
3359  
3360  	all_regs = nvmf_ns_reservation_all_registrants_type(ns);
3361  
3362  	switch (racqa) {
3363  	case SPDK_NVME_RESERVE_ACQUIRE:
3364  		/* it's not an error for the holder to acquire same reservation type again */
3365  		if (nvmf_ns_reservation_registrant_is_holder(ns, reg) && ns->rtype == rtype) {
3366  			/* do nothing */
3367  			update_sgroup = false;
3368  		} else if (ns->holder == NULL) {
3369  			/* first time to acquire the reservation */
3370  			nvmf_ns_reservation_acquire_reservation(ns, key.crkey, rtype, reg);
3371  		} else {
3372  			SPDK_ERRLOG("Invalid rtype or current registrant is not holder\n");
3373  			status = SPDK_NVME_SC_RESERVATION_CONFLICT;
3374  			update_sgroup = false;
3375  			goto exit;
3376  		}
3377  		break;
3378  	case SPDK_NVME_RESERVE_PREEMPT:
3379  		/* no reservation holder */
3380  		if (!ns->holder) {
3381  			/* unregister with PRKEY */
3382  			nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey);
3383  			break;
3384  		}
3385  		num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, hostid_list,
3386  				SPDK_NVMF_MAX_NUM_REGISTRANTS,
3387  				&ctrlr->hostid);
3388  
3389  		/* only 1 reservation holder and reservation key is valid */
3390  		if (!all_regs) {
3391  			/* preempt itself */
3392  			if (nvmf_ns_reservation_registrant_is_holder(ns, reg) &&
3393  			    ns->crkey == key.prkey) {
3394  				ns->rtype = rtype;
3395  				reservation_released = true;
3396  				break;
3397  			}
3398  
3399  			if (ns->crkey == key.prkey) {
3400  				nvmf_ns_reservation_remove_registrant(ns, ns->holder);
3401  				nvmf_ns_reservation_acquire_reservation(ns, key.crkey, rtype, reg);
3402  				reservation_released = true;
3403  			} else if (key.prkey != 0) {
3404  				nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey);
3405  			} else {
3406  				/* PRKEY is zero */
3407  				SPDK_ERRLOG("Current PRKEY is zero\n");
3408  				status = SPDK_NVME_SC_RESERVATION_CONFLICT;
3409  				update_sgroup = false;
3410  				goto exit;
3411  			}
3412  		} else {
3413  			/* release all other registrants except for the current one */
3414  			if (key.prkey == 0) {
3415  				nvmf_ns_reservation_remove_all_other_registrants(ns, reg);
3416  				assert(ns->holder == reg);
3417  			} else {
3418  				count = nvmf_ns_reservation_remove_registrants_by_key(ns, key.prkey);
3419  				if (count == 0) {
3420  					SPDK_ERRLOG("PRKEY doesn't match any registrant\n");
3421  					status = SPDK_NVME_SC_RESERVATION_CONFLICT;
3422  					update_sgroup = false;
3423  					goto exit;
3424  				}
3425  			}
3426  		}
3427  		break;
3428  	default:
3429  		status = SPDK_NVME_SC_INVALID_FIELD;
3430  		update_sgroup = false;
3431  		break;
3432  	}
3433  
3434  exit:
3435  	if (update_sgroup && racqa == SPDK_NVME_RESERVE_PREEMPT) {
3436  		new_num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, new_hostid_list,
3437  				 SPDK_NVMF_MAX_NUM_REGISTRANTS,
3438  				 &ctrlr->hostid);
3439  		/* Preempt notification occurs on the unregistered controllers
3440  		 * other than the controller who issued the command.
3441  		 */
3442  		num_hostid = nvmf_ns_reservation_get_unregistered_hostid(hostid_list,
3443  				num_hostid,
3444  				new_hostid_list,
3445  				new_num_hostid);
3446  		if (num_hostid) {
3447  			nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns,
3448  							      hostid_list,
3449  							      num_hostid,
3450  							      SPDK_NVME_REGISTRATION_PREEMPTED);
3451  
3452  		}
3453  		/* Reservation released notification occurs on the
3454  		 * controllers which are the remaining registrants other than
3455  		 * the controller who issued the command.
3456  		 */
3457  		if (reservation_released && new_num_hostid) {
3458  			nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns,
3459  							      new_hostid_list,
3460  							      new_num_hostid,
3461  							      SPDK_NVME_RESERVATION_RELEASED);
3462  
3463  		}
3464  	}
3465  	req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC;
3466  	req->rsp->nvme_cpl.status.sc = status;
3467  	return update_sgroup;
3468  }
3469  
3470  static bool
3471  nvmf_ns_reservation_release(struct spdk_nvmf_ns *ns,
3472  			    struct spdk_nvmf_ctrlr *ctrlr,
3473  			    struct spdk_nvmf_request *req)
3474  {
3475  	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
3476  	uint8_t rrela, iekey, rtype;
3477  	struct spdk_nvmf_registrant *reg;
3478  	uint64_t crkey = 0;
3479  	uint8_t status = SPDK_NVME_SC_SUCCESS;
3480  	bool update_sgroup = true;
3481  	struct spdk_uuid hostid_list[SPDK_NVMF_MAX_NUM_REGISTRANTS];
3482  	uint32_t num_hostid = 0;
3483  
3484  	rrela = cmd->cdw10_bits.resv_release.rrela;
3485  	iekey = cmd->cdw10_bits.resv_release.iekey;
3486  	rtype = cmd->cdw10_bits.resv_release.rtype;
3487  
3488  	if (req->iovcnt > 0 && req->length >= sizeof(crkey)) {
3489  		struct spdk_iov_xfer ix;
3490  		spdk_iov_xfer_init(&ix, req->iov, req->iovcnt);
3491  		spdk_iov_xfer_to_buf(&ix, &crkey, sizeof(crkey));
3492  	} else {
3493  		SPDK_ERRLOG("No key provided. Failing request.\n");
3494  		status = SPDK_NVME_SC_INVALID_FIELD;
3495  		goto exit;
3496  	}
3497  
3498  	SPDK_DEBUGLOG(nvmf, "RELEASE: RRELA %u, IEKEY %u, RTYPE %u, "
3499  		      "CRKEY 0x%"PRIx64"\n",  rrela, iekey, rtype, crkey);
3500  
3501  	if (iekey) {
3502  		SPDK_ERRLOG("Ignore existing key field set to 1\n");
3503  		status = SPDK_NVME_SC_INVALID_FIELD;
3504  		update_sgroup = false;
3505  		goto exit;
3506  	}
3507  
3508  	reg = nvmf_ns_reservation_get_registrant(ns, &ctrlr->hostid);
3509  	if (!reg || reg->rkey != crkey) {
3510  		SPDK_ERRLOG("No registrant or current key doesn't match "
3511  			    "with existing registrant key\n");
3512  		status = SPDK_NVME_SC_RESERVATION_CONFLICT;
3513  		update_sgroup = false;
3514  		goto exit;
3515  	}
3516  
3517  	num_hostid = nvmf_ns_reservation_get_all_other_hostid(ns, hostid_list,
3518  			SPDK_NVMF_MAX_NUM_REGISTRANTS,
3519  			&ctrlr->hostid);
3520  
3521  	switch (rrela) {
3522  	case SPDK_NVME_RESERVE_RELEASE:
3523  		if (!ns->holder) {
3524  			SPDK_DEBUGLOG(nvmf, "RELEASE: no holder\n");
3525  			update_sgroup = false;
3526  			goto exit;
3527  		}
3528  		if (ns->rtype != rtype) {
3529  			SPDK_ERRLOG("Type doesn't match\n");
3530  			status = SPDK_NVME_SC_INVALID_FIELD;
3531  			update_sgroup = false;
3532  			goto exit;
3533  		}
3534  		if (!nvmf_ns_reservation_registrant_is_holder(ns, reg)) {
3535  			/* not the reservation holder, this isn't an error */
3536  			update_sgroup = false;
3537  			goto exit;
3538  		}
3539  
3540  		rtype = ns->rtype;
3541  		nvmf_ns_reservation_release_reservation(ns);
3542  
3543  		if (num_hostid && rtype != SPDK_NVME_RESERVE_WRITE_EXCLUSIVE &&
3544  		    rtype != SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS) {
3545  			nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns,
3546  							      hostid_list,
3547  							      num_hostid,
3548  							      SPDK_NVME_RESERVATION_RELEASED);
3549  		}
3550  		break;
3551  	case SPDK_NVME_RESERVE_CLEAR:
3552  		nvmf_ns_reservation_clear_all_registrants(ns);
3553  		if (num_hostid) {
3554  			nvmf_subsystem_gen_ctrlr_notification(ns->subsystem, ns,
3555  							      hostid_list,
3556  							      num_hostid,
3557  							      SPDK_NVME_RESERVATION_PREEMPTED);
3558  		}
3559  		break;
3560  	default:
3561  		status = SPDK_NVME_SC_INVALID_FIELD;
3562  		update_sgroup = false;
3563  		goto exit;
3564  	}
3565  
3566  exit:
3567  	req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC;
3568  	req->rsp->nvme_cpl.status.sc = status;
3569  	return update_sgroup;
3570  }
3571  
3572  static void
3573  nvmf_ns_reservation_report(struct spdk_nvmf_ns *ns,
3574  			   struct spdk_nvmf_ctrlr *ctrlr,
3575  			   struct spdk_nvmf_request *req)
3576  {
3577  	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
3578  	struct spdk_nvmf_registrant *reg, *tmp;
3579  	struct spdk_nvme_reservation_status_extended_data status_data = { 0 };
3580  	struct spdk_iov_xfer ix;
3581  	uint32_t transfer_len;
3582  	uint32_t regctl = 0;
3583  	uint8_t status = SPDK_NVME_SC_SUCCESS;
3584  
3585  	if (req->iovcnt == 0) {
3586  		SPDK_ERRLOG("No data transfer specified for request. "
3587  			    " Unable to transfer back response.\n");
3588  		status = SPDK_NVME_SC_INVALID_FIELD;
3589  		goto exit;
3590  	}
3591  
3592  	if (!cmd->cdw11_bits.resv_report.eds) {
3593  		SPDK_ERRLOG("NVMeoF uses extended controller data structure, "
3594  			    "please set EDS bit in cdw11 and try again\n");
3595  		status = SPDK_NVME_SC_HOSTID_INCONSISTENT_FORMAT;
3596  		goto exit;
3597  	}
3598  
3599  	/* Number of Dwords of the Reservation Status data structure to transfer */
3600  	transfer_len = (cmd->cdw10 + 1) * sizeof(uint32_t);
3601  
3602  	if (transfer_len < sizeof(struct spdk_nvme_reservation_status_extended_data)) {
3603  		status = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
3604  		goto exit;
3605  	}
3606  
3607  	spdk_iov_xfer_init(&ix, req->iov, req->iovcnt);
3608  
3609  	status_data.data.gen = ns->gen;
3610  	status_data.data.rtype = ns->rtype;
3611  	status_data.data.ptpls = ns->ptpl_activated;
3612  
3613  	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) {
3614  		regctl++;
3615  	}
3616  
3617  	/*
3618  	 * We report the number of registrants as per the spec here, even if
3619  	 * the iov isn't big enough to contain them all. In that case, the
3620  	 * spdk_iov_xfer_from_buf() won't actually copy any of the remaining
3621  	 * data; as it keeps track of the iov cursor itself, it's simplest to
3622  	 * just walk the entire list anyway.
3623  	 */
3624  	status_data.data.regctl = regctl;
3625  
3626  	spdk_iov_xfer_from_buf(&ix, &status_data, sizeof(status_data));
3627  
3628  	TAILQ_FOREACH_SAFE(reg, &ns->registrants, link, tmp) {
3629  		struct spdk_nvme_registered_ctrlr_extended_data ctrlr_data = { 0 };
3630  
3631  		/* Set to 0xffffh for dynamic controller */
3632  		ctrlr_data.cntlid = 0xffff;
3633  		ctrlr_data.rcsts.status = (ns->holder == reg) ? true : false;
3634  		ctrlr_data.rkey = reg->rkey;
3635  		spdk_uuid_copy((struct spdk_uuid *)ctrlr_data.hostid, &reg->hostid);
3636  
3637  		spdk_iov_xfer_from_buf(&ix, &ctrlr_data, sizeof(ctrlr_data));
3638  	}
3639  
3640  exit:
3641  	req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC;
3642  	req->rsp->nvme_cpl.status.sc = status;
3643  	return;
3644  }
3645  
3646  static void
3647  nvmf_ns_reservation_complete(void *ctx)
3648  {
3649  	struct spdk_nvmf_request *req = ctx;
3650  
3651  	spdk_nvmf_request_complete(req);
3652  }
3653  
3654  static void
3655  _nvmf_ns_reservation_update_done(struct spdk_nvmf_subsystem *subsystem,
3656  				 void *cb_arg, int status)
3657  {
3658  	struct spdk_nvmf_request *req = (struct spdk_nvmf_request *)cb_arg;
3659  	struct spdk_nvmf_poll_group *group = req->qpair->group;
3660  
3661  	spdk_thread_send_msg(group->thread, nvmf_ns_reservation_complete, req);
3662  }
3663  
3664  void
3665  nvmf_ns_reservation_request(void *ctx)
3666  {
3667  	struct spdk_nvmf_request *req = (struct spdk_nvmf_request *)ctx;
3668  	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
3669  	struct spdk_nvmf_ctrlr *ctrlr = req->qpair->ctrlr;
3670  	uint32_t nsid;
3671  	struct spdk_nvmf_ns *ns;
3672  	bool update_sgroup = false;
3673  	int status = 0;
3674  
3675  	nsid = cmd->nsid;
3676  	ns = _nvmf_subsystem_get_ns(ctrlr->subsys, nsid);
3677  	assert(ns != NULL);
3678  
3679  	switch (cmd->opc) {
3680  	case SPDK_NVME_OPC_RESERVATION_REGISTER:
3681  		update_sgroup = nvmf_ns_reservation_register(ns, ctrlr, req);
3682  		break;
3683  	case SPDK_NVME_OPC_RESERVATION_ACQUIRE:
3684  		update_sgroup = nvmf_ns_reservation_acquire(ns, ctrlr, req);
3685  		break;
3686  	case SPDK_NVME_OPC_RESERVATION_RELEASE:
3687  		update_sgroup = nvmf_ns_reservation_release(ns, ctrlr, req);
3688  		break;
3689  	case SPDK_NVME_OPC_RESERVATION_REPORT:
3690  		nvmf_ns_reservation_report(ns, ctrlr, req);
3691  		break;
3692  	default:
3693  		break;
3694  	}
3695  
3696  	/* update reservation information to subsystem's poll group */
3697  	if (update_sgroup) {
3698  		if (ns->ptpl_activated || cmd->opc == SPDK_NVME_OPC_RESERVATION_REGISTER) {
3699  			if (nvmf_ns_update_reservation_info(ns) != 0) {
3700  				req->rsp->nvme_cpl.status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
3701  			}
3702  		}
3703  		status = nvmf_subsystem_update_ns(ctrlr->subsys, _nvmf_ns_reservation_update_done, req);
3704  		if (status == 0) {
3705  			return;
3706  		}
3707  	}
3708  
3709  	_nvmf_ns_reservation_update_done(ctrlr->subsys, req, status);
3710  }
3711  
3712  static bool
3713  nvmf_ns_is_ptpl_capable_json(const struct spdk_nvmf_ns *ns)
3714  {
3715  	return ns->ptpl_file != NULL;
3716  }
3717  
3718  static struct spdk_nvmf_ns_reservation_ops g_reservation_ops = {
3719  	.is_ptpl_capable = nvmf_ns_is_ptpl_capable_json,
3720  	.update = nvmf_ns_reservation_update_json,
3721  	.load = nvmf_ns_reservation_load_json,
3722  };
3723  
3724  bool
3725  nvmf_ns_is_ptpl_capable(const struct spdk_nvmf_ns *ns)
3726  {
3727  	return g_reservation_ops.is_ptpl_capable(ns);
3728  }
3729  
3730  static int
3731  nvmf_ns_reservation_update(const struct spdk_nvmf_ns *ns,
3732  			   const struct spdk_nvmf_reservation_info *info)
3733  {
3734  	return g_reservation_ops.update(ns, info);
3735  }
3736  
3737  static int
3738  nvmf_ns_reservation_load(const struct spdk_nvmf_ns *ns, struct spdk_nvmf_reservation_info *info)
3739  {
3740  	return g_reservation_ops.load(ns, info);
3741  }
3742  
3743  void
3744  spdk_nvmf_set_custom_ns_reservation_ops(const struct spdk_nvmf_ns_reservation_ops *ops)
3745  {
3746  	g_reservation_ops = *ops;
3747  }
3748  
3749  int
3750  spdk_nvmf_subsystem_set_ana_reporting(struct spdk_nvmf_subsystem *subsystem,
3751  				      bool ana_reporting)
3752  {
3753  	if (subsystem->state != SPDK_NVMF_SUBSYSTEM_INACTIVE) {
3754  		return -EAGAIN;
3755  	}
3756  
3757  	subsystem->flags.ana_reporting = ana_reporting;
3758  
3759  	return 0;
3760  }
3761  
3762  bool
3763  spdk_nvmf_subsystem_get_ana_reporting(struct spdk_nvmf_subsystem *subsystem)
3764  {
3765  	return subsystem->flags.ana_reporting;
3766  }
3767  
3768  struct subsystem_listener_update_ctx {
3769  	struct spdk_nvmf_subsystem_listener *listener;
3770  
3771  	spdk_nvmf_tgt_subsystem_listen_done_fn cb_fn;
3772  	void *cb_arg;
3773  };
3774  
3775  static void
3776  subsystem_listener_update_done(struct spdk_io_channel_iter *i, int status)
3777  {
3778  	struct subsystem_listener_update_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
3779  
3780  	if (ctx->cb_fn) {
3781  		ctx->cb_fn(ctx->cb_arg, status);
3782  	}
3783  	free(ctx);
3784  }
3785  
3786  static void
3787  subsystem_listener_update_on_pg(struct spdk_io_channel_iter *i)
3788  {
3789  	struct subsystem_listener_update_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
3790  	struct spdk_nvmf_subsystem_listener *listener;
3791  	struct spdk_nvmf_poll_group *group;
3792  	struct spdk_nvmf_ctrlr *ctrlr;
3793  
3794  	listener = ctx->listener;
3795  	group = spdk_io_channel_get_ctx(spdk_io_channel_iter_get_channel(i));
3796  
3797  	TAILQ_FOREACH(ctrlr, &listener->subsystem->ctrlrs, link) {
3798  		if (ctrlr->thread != spdk_get_thread()) {
3799  			continue;
3800  		}
3801  
3802  		if (ctrlr->admin_qpair && ctrlr->admin_qpair->group == group && ctrlr->listener == listener) {
3803  			nvmf_ctrlr_async_event_ana_change_notice(ctrlr);
3804  		}
3805  	}
3806  
3807  	spdk_for_each_channel_continue(i, 0);
3808  }
3809  
3810  void
3811  spdk_nvmf_subsystem_set_ana_state(struct spdk_nvmf_subsystem *subsystem,
3812  				  const struct spdk_nvme_transport_id *trid,
3813  				  enum spdk_nvme_ana_state ana_state, uint32_t anagrpid,
3814  				  spdk_nvmf_tgt_subsystem_listen_done_fn cb_fn, void *cb_arg)
3815  {
3816  	struct spdk_nvmf_subsystem_listener *listener;
3817  	struct subsystem_listener_update_ctx *ctx;
3818  	uint32_t i;
3819  
3820  	assert(cb_fn != NULL);
3821  	assert(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
3822  	       subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED);
3823  
3824  	if (!subsystem->flags.ana_reporting) {
3825  		SPDK_ERRLOG("ANA reporting is disabled\n");
3826  		cb_fn(cb_arg, -EINVAL);
3827  		return;
3828  	}
3829  
3830  	/* ANA Change state is not used, ANA Persistent Loss state
3831  	 * is not supported yet.
3832  	 */
3833  	if (!(ana_state == SPDK_NVME_ANA_OPTIMIZED_STATE ||
3834  	      ana_state == SPDK_NVME_ANA_NON_OPTIMIZED_STATE ||
3835  	      ana_state == SPDK_NVME_ANA_INACCESSIBLE_STATE)) {
3836  		SPDK_ERRLOG("ANA state %d is not supported\n", ana_state);
3837  		cb_fn(cb_arg, -ENOTSUP);
3838  		return;
3839  	}
3840  
3841  	if (anagrpid > subsystem->max_nsid) {
3842  		SPDK_ERRLOG("ANA group ID %" PRIu32 " is more than maximum\n", anagrpid);
3843  		cb_fn(cb_arg, -EINVAL);
3844  		return;
3845  	}
3846  
3847  	listener = nvmf_subsystem_find_listener(subsystem, trid);
3848  	if (!listener) {
3849  		SPDK_ERRLOG("Unable to find listener.\n");
3850  		cb_fn(cb_arg, -EINVAL);
3851  		return;
3852  	}
3853  
3854  	if (anagrpid != 0 && listener->ana_state[anagrpid - 1] == ana_state) {
3855  		cb_fn(cb_arg, 0);
3856  		return;
3857  	}
3858  
3859  	ctx = calloc(1, sizeof(*ctx));
3860  	if (!ctx) {
3861  		SPDK_ERRLOG("Unable to allocate context\n");
3862  		cb_fn(cb_arg, -ENOMEM);
3863  		return;
3864  	}
3865  
3866  	for (i = 1; i <= subsystem->max_nsid; i++) {
3867  		if (anagrpid == 0 || i == anagrpid) {
3868  			listener->ana_state[i - 1] = ana_state;
3869  		}
3870  	}
3871  	listener->ana_state_change_count++;
3872  
3873  	ctx->listener = listener;
3874  	ctx->cb_fn = cb_fn;
3875  	ctx->cb_arg = cb_arg;
3876  
3877  	spdk_for_each_channel(subsystem->tgt,
3878  			      subsystem_listener_update_on_pg,
3879  			      ctx,
3880  			      subsystem_listener_update_done);
3881  }
3882  
3883  int
3884  spdk_nvmf_subsystem_get_ana_state(struct spdk_nvmf_subsystem *subsystem,
3885  				  const struct spdk_nvme_transport_id *trid,
3886  				  uint32_t anagrpid,
3887  				  enum spdk_nvme_ana_state *ana_state)
3888  {
3889  	assert(ana_state != NULL);
3890  
3891  	struct spdk_nvmf_subsystem_listener *listener;
3892  
3893  	if (!subsystem->flags.ana_reporting) {
3894  		SPDK_ERRLOG("ANA reporting is disabled\n");
3895  		return -EINVAL;
3896  	}
3897  
3898  	if (anagrpid <= 0 || anagrpid > subsystem->max_nsid) {
3899  		SPDK_ERRLOG("ANA group ID %" PRIu32 " is invalid\n", anagrpid);
3900  		return -EINVAL;
3901  	}
3902  
3903  	listener = nvmf_subsystem_find_listener(subsystem, trid);
3904  	if (!listener) {
3905  		SPDK_ERRLOG("Unable to find listener.\n");
3906  		return -EINVAL;
3907  	}
3908  
3909  	*ana_state = listener->ana_state[anagrpid - 1];
3910  	return 0;
3911  }
3912  
3913  bool
3914  spdk_nvmf_subsystem_is_discovery(struct spdk_nvmf_subsystem *subsystem)
3915  {
3916  	return subsystem->subtype == SPDK_NVMF_SUBTYPE_DISCOVERY_CURRENT ||
3917  	       subsystem->subtype == SPDK_NVMF_SUBTYPE_DISCOVERY;
3918  }
3919  
3920  bool
3921  nvmf_nqn_is_discovery(const char *nqn)
3922  {
3923  	return strcmp(nqn, SPDK_NVMF_DISCOVERY_NQN) == 0;
3924  }
3925