xref: /spdk/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c (revision 588dfe314bb83d86effdf67ec42837b11c2620bf)
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   */
5  
6  #include "spdk/stdinc.h"
7  
8  #include "common/lib/ut_multithread.c"
9  #include "spdk_cunit.h"
10  #include "spdk_internal/mock.h"
11  
12  #include "spdk/bdev_module.h"
13  #include "nvmf/subsystem.c"
14  #include <uuid/uuid.h>
15  
16  SPDK_LOG_REGISTER_COMPONENT(nvmf)
17  
18  DEFINE_STUB(spdk_bdev_module_claim_bdev,
19  	    int,
20  	    (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
21  	     struct spdk_bdev_module *module), 0);
22  
23  DEFINE_STUB_V(spdk_bdev_module_release_bdev,
24  	      (struct spdk_bdev *bdev));
25  
26  DEFINE_STUB(spdk_bdev_get_block_size, uint32_t,
27  	    (const struct spdk_bdev *bdev), 512);
28  
29  DEFINE_STUB(spdk_bdev_get_md_size, uint32_t,
30  	    (const struct spdk_bdev *bdev), 0);
31  
32  DEFINE_STUB(spdk_bdev_is_md_interleaved, bool,
33  	    (const struct spdk_bdev *bdev), false);
34  
35  DEFINE_STUB(spdk_bdev_io_type_supported, bool,
36  	    (struct spdk_bdev *bdev,
37  	     enum spdk_bdev_io_type io_type), false);
38  
39  DEFINE_STUB(spdk_nvmf_transport_stop_listen,
40  	    int,
41  	    (struct spdk_nvmf_transport *transport,
42  	     const struct spdk_nvme_transport_id *trid), 0);
43  
44  DEFINE_STUB_V(nvmf_update_discovery_log,
45  	      (struct spdk_nvmf_tgt *tgt, const char *hostnqn));
46  
47  DEFINE_STUB(spdk_nvmf_qpair_disconnect,
48  	    int,
49  	    (struct spdk_nvmf_qpair *qpair,
50  	     nvmf_qpair_disconnect_cb cb_fn, void *ctx), 0);
51  
52  DEFINE_STUB(nvmf_transport_find_listener,
53  	    struct spdk_nvmf_listener *,
54  	    (struct spdk_nvmf_transport *transport,
55  	     const struct spdk_nvme_transport_id *trid), NULL);
56  
57  DEFINE_STUB(spdk_nvmf_transport_get_first,
58  	    struct spdk_nvmf_transport *,
59  	    (struct spdk_nvmf_tgt *tgt), NULL);
60  
61  DEFINE_STUB(spdk_nvmf_transport_get_next,
62  	    struct spdk_nvmf_transport *,
63  	    (struct spdk_nvmf_transport *transport), NULL);
64  
65  DEFINE_STUB(spdk_nvmf_request_complete,
66  	    int,
67  	    (struct spdk_nvmf_request *req), 0);
68  
69  DEFINE_STUB(nvmf_ctrlr_async_event_ana_change_notice,
70  	    int,
71  	    (struct spdk_nvmf_ctrlr *ctrlr), 0);
72  
73  DEFINE_STUB(spdk_nvme_transport_id_trtype_str,
74  	    const char *,
75  	    (enum spdk_nvme_transport_type trtype), NULL);
76  
77  int
78  spdk_nvmf_transport_listen(struct spdk_nvmf_transport *transport,
79  			   const struct spdk_nvme_transport_id *trid, struct spdk_nvmf_listen_opts *opts)
80  {
81  	return 0;
82  }
83  
84  void
85  nvmf_transport_listener_discover(struct spdk_nvmf_transport *transport,
86  				 struct spdk_nvme_transport_id *trid,
87  				 struct spdk_nvmf_discovery_log_page_entry *entry)
88  {
89  	entry->trtype = 42;
90  }
91  
92  static struct spdk_nvmf_transport g_transport = {};
93  
94  struct spdk_nvmf_transport *
95  spdk_nvmf_transport_create(const char *transport_name,
96  			   struct spdk_nvmf_transport_opts *tprt_opts)
97  {
98  	if (strcasecmp(transport_name, spdk_nvme_transport_id_trtype_str(SPDK_NVME_TRANSPORT_RDMA))) {
99  		return &g_transport;
100  	}
101  
102  	return NULL;
103  }
104  
105  struct spdk_nvmf_subsystem *
106  spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt *tgt, const char *subnqn)
107  {
108  	return NULL;
109  }
110  
111  struct spdk_nvmf_transport *
112  spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, const char *transport_name)
113  {
114  	if (strncmp(transport_name, SPDK_NVME_TRANSPORT_NAME_RDMA, SPDK_NVMF_TRSTRING_MAX_LEN)) {
115  		return &g_transport;
116  	}
117  
118  	return NULL;
119  }
120  
121  int
122  nvmf_poll_group_update_subsystem(struct spdk_nvmf_poll_group *group,
123  				 struct spdk_nvmf_subsystem *subsystem)
124  {
125  	return 0;
126  }
127  
128  int
129  nvmf_poll_group_add_subsystem(struct spdk_nvmf_poll_group *group,
130  			      struct spdk_nvmf_subsystem *subsystem,
131  			      spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
132  {
133  	return 0;
134  }
135  
136  void
137  nvmf_poll_group_remove_subsystem(struct spdk_nvmf_poll_group *group,
138  				 struct spdk_nvmf_subsystem *subsystem,
139  				 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
140  {
141  }
142  
143  void
144  nvmf_poll_group_pause_subsystem(struct spdk_nvmf_poll_group *group,
145  				struct spdk_nvmf_subsystem *subsystem,
146  				uint32_t nsid,
147  				spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
148  {
149  }
150  
151  void
152  nvmf_poll_group_resume_subsystem(struct spdk_nvmf_poll_group *group,
153  				 struct spdk_nvmf_subsystem *subsystem,
154  				 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
155  {
156  }
157  
158  int
159  spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type *trtype, const char *str)
160  {
161  	if (trtype == NULL || str == NULL) {
162  		return -EINVAL;
163  	}
164  
165  	if (strcasecmp(str, "PCIe") == 0) {
166  		*trtype = SPDK_NVME_TRANSPORT_PCIE;
167  	} else if (strcasecmp(str, "RDMA") == 0) {
168  		*trtype = SPDK_NVME_TRANSPORT_RDMA;
169  	} else {
170  		return -ENOENT;
171  	}
172  	return 0;
173  }
174  
175  int
176  spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id *trid1,
177  			       const struct spdk_nvme_transport_id *trid2)
178  {
179  	return 0;
180  }
181  
182  int32_t
183  spdk_nvme_ctrlr_process_admin_completions(struct spdk_nvme_ctrlr *ctrlr)
184  {
185  	return -1;
186  }
187  
188  int32_t
189  spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_completions)
190  {
191  	return -1;
192  }
193  
194  int
195  spdk_nvme_detach(struct spdk_nvme_ctrlr *ctrlr)
196  {
197  	return -1;
198  }
199  
200  void
201  nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr)
202  {
203  }
204  
205  static struct spdk_nvmf_ctrlr *g_ns_changed_ctrlr = NULL;
206  static uint32_t g_ns_changed_nsid = 0;
207  void
208  nvmf_ctrlr_ns_changed(struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid)
209  {
210  	g_ns_changed_ctrlr = ctrlr;
211  	g_ns_changed_nsid = nsid;
212  }
213  
214  static struct spdk_bdev g_bdevs[] = {
215  	{ .name = "bdev1" },
216  	{ .name = "bdev2" },
217  };
218  
219  struct spdk_bdev_desc {
220  	struct spdk_bdev	*bdev;
221  };
222  
223  int
224  spdk_bdev_open_ext(const char *bdev_name, bool write, spdk_bdev_event_cb_t event_cb,
225  		   void *event_ctx, struct spdk_bdev_desc **_desc)
226  {
227  	struct spdk_bdev_desc *desc;
228  	size_t i;
229  
230  	for (i = 0; i < sizeof(g_bdevs); i++) {
231  		if (strcmp(bdev_name, g_bdevs[i].name) == 0) {
232  
233  			desc = calloc(1, sizeof(*desc));
234  			SPDK_CU_ASSERT_FATAL(desc != NULL);
235  
236  			desc->bdev = &g_bdevs[i];
237  			*_desc = desc;
238  			return 0;
239  		}
240  	}
241  
242  	return -EINVAL;
243  }
244  
245  void
246  spdk_bdev_close(struct spdk_bdev_desc *desc)
247  {
248  	free(desc);
249  }
250  
251  struct spdk_bdev *
252  spdk_bdev_desc_get_bdev(struct spdk_bdev_desc *desc)
253  {
254  	return desc->bdev;
255  }
256  
257  const char *
258  spdk_bdev_get_name(const struct spdk_bdev *bdev)
259  {
260  	return "test";
261  }
262  
263  const struct spdk_uuid *
264  spdk_bdev_get_uuid(const struct spdk_bdev *bdev)
265  {
266  	return &bdev->uuid;
267  }
268  
269  static void
270  test_spdk_nvmf_subsystem_add_ns(void)
271  {
272  	struct spdk_nvmf_tgt tgt = {};
273  	struct spdk_nvmf_subsystem subsystem = {
274  		.max_nsid = 1024,
275  		.ns = NULL,
276  		.tgt = &tgt,
277  	};
278  	struct spdk_nvmf_ns_opts ns_opts;
279  	uint32_t nsid;
280  	int rc;
281  
282  	subsystem.ns = calloc(subsystem.max_nsid, sizeof(struct spdk_nvmf_subsystem_ns *));
283  	SPDK_CU_ASSERT_FATAL(subsystem.ns != NULL);
284  	subsystem.ana_group = calloc(subsystem.max_nsid, sizeof(uint32_t));
285  	SPDK_CU_ASSERT_FATAL(subsystem.ana_group != NULL);
286  
287  	tgt.max_subsystems = 1024;
288  	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
289  	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
290  
291  	/* Request a specific NSID */
292  	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
293  	ns_opts.nsid = 5;
294  	nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL);
295  	CU_ASSERT(nsid == 5);
296  	CU_ASSERT(subsystem.max_nsid == 1024);
297  	SPDK_CU_ASSERT_FATAL(subsystem.ns[nsid - 1] != NULL);
298  	CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &g_bdevs[1]);
299  
300  	/* Request an NSID that is already in use */
301  	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
302  	ns_opts.nsid = 5;
303  	nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL);
304  	CU_ASSERT(nsid == 0);
305  	CU_ASSERT(subsystem.max_nsid == 1024);
306  
307  	/* Request 0xFFFFFFFF (invalid NSID, reserved for broadcast) */
308  	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
309  	ns_opts.nsid = 0xFFFFFFFF;
310  	nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL);
311  	CU_ASSERT(nsid == 0);
312  	CU_ASSERT(subsystem.max_nsid == 1024);
313  
314  	rc = spdk_nvmf_subsystem_remove_ns(&subsystem, 5);
315  	CU_ASSERT(rc == 0);
316  
317  	free(subsystem.ns);
318  	free(subsystem.ana_group);
319  	free(tgt.subsystems);
320  }
321  
322  static void
323  nvmf_test_create_subsystem(void)
324  {
325  	struct spdk_nvmf_tgt tgt = {};
326  	char nqn[256];
327  	struct spdk_nvmf_subsystem *subsystem;
328  	int rc;
329  
330  	tgt.max_subsystems = 1024;
331  	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
332  	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
333  
334  	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
335  	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
336  	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
337  	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
338  	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
339  	CU_ASSERT(rc == 0);
340  
341  	/* valid name with complex reverse domain */
342  	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-full--rev-domain.name:subsystem1");
343  	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
344  	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
345  	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
346  	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
347  	CU_ASSERT(rc == 0);
348  
349  	/* Valid name discovery controller */
350  	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
351  	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
352  	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
353  	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
354  	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
355  	CU_ASSERT(rc == 0);
356  
357  	/* Invalid name, no user supplied string */
358  	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:");
359  	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
360  	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
361  
362  	/* Valid name, only contains top-level domain name */
363  	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
364  	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
365  	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
366  	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
367  	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
368  	CU_ASSERT(rc == 0);
369  
370  	/* Invalid name, domain label > 63 characters */
371  	snprintf(nqn, sizeof(nqn),
372  		 "nqn.2016-06.io.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz:sub");
373  	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
374  	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
375  
376  	/* Invalid name, domain label starts with digit */
377  	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.3spdk:sub");
378  	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
379  	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
380  
381  	/* Invalid name, domain label starts with - */
382  	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.-spdk:subsystem1");
383  	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
384  	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
385  
386  	/* Invalid name, domain label ends with - */
387  	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-:subsystem1");
388  	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
389  	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
390  
391  	/* Invalid name, domain label with multiple consecutive periods */
392  	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io..spdk:subsystem1");
393  	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
394  	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
395  
396  	/* Longest valid name */
397  	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:");
398  	memset(nqn + strlen(nqn), 'a', 223 - strlen(nqn));
399  	nqn[223] = '\0';
400  	CU_ASSERT(strlen(nqn) == 223);
401  	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
402  	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
403  	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
404  	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
405  	CU_ASSERT(rc == 0);
406  
407  	/* Invalid name, too long */
408  	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:");
409  	memset(nqn + strlen(nqn), 'a', 224 - strlen(nqn));
410  	nqn[224] = '\0';
411  	CU_ASSERT(strlen(nqn) == 224);
412  	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
413  	CU_ASSERT(subsystem == NULL);
414  
415  	/* Valid name using uuid format */
416  	snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:11111111-aaaa-bbdd-FFEE-123456789abc");
417  	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
418  	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
419  	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
420  	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
421  	CU_ASSERT(rc == 0);
422  
423  	/* Invalid name user string contains an invalid utf-8 character */
424  	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xFFsubsystem1");
425  	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
426  	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
427  
428  	/* Valid name with non-ascii but valid utf-8 characters */
429  	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xe1\x8a\x88subsystem1\xca\x80");
430  	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
431  	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
432  	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
433  	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
434  	CU_ASSERT(rc == 0);
435  
436  	/* Invalid uuid (too long) */
437  	snprintf(nqn, sizeof(nqn),
438  		 "nqn.2014-08.org.nvmexpress:uuid:11111111-aaaa-bbdd-FFEE-123456789abcdef");
439  	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
440  	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
441  
442  	/* Invalid uuid (dashes placed incorrectly) */
443  	snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:111111-11aaaa-bbdd-FFEE-123456789abc");
444  	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
445  	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
446  
447  	/* Invalid uuid (invalid characters in uuid) */
448  	snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:111hg111-aaaa-bbdd-FFEE-123456789abc");
449  	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
450  	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
451  
452  	free(tgt.subsystems);
453  }
454  
455  static void
456  test_spdk_nvmf_subsystem_set_sn(void)
457  {
458  	struct spdk_nvmf_subsystem subsystem = {};
459  
460  	/* Basic valid serial number */
461  	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd xyz") == 0);
462  	CU_ASSERT(strcmp(subsystem.sn, "abcd xyz") == 0);
463  
464  	/* Exactly 20 characters (valid) */
465  	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "12345678901234567890") == 0);
466  	CU_ASSERT(strcmp(subsystem.sn, "12345678901234567890") == 0);
467  
468  	/* 21 characters (too long, invalid) */
469  	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "123456789012345678901") < 0);
470  
471  	/* Non-ASCII characters (invalid) */
472  	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd\txyz") < 0);
473  }
474  
475  /*
476   * Reservation Unit Test Configuration
477   *       --------             --------    --------
478   *      | Host A |           | Host B |  | Host C |
479   *       --------             --------    --------
480   *      /        \               |           |
481   *  --------   --------       -------     -------
482   * |Ctrlr1_A| |Ctrlr2_A|     |Ctrlr_B|   |Ctrlr_C|
483   *  --------   --------       -------     -------
484   *    \           \              /           /
485   *     \           \            /           /
486   *      \           \          /           /
487   *      --------------------------------------
488   *     |            NAMESPACE 1               |
489   *      --------------------------------------
490   */
491  static struct spdk_nvmf_subsystem g_subsystem;
492  static struct spdk_nvmf_ctrlr g_ctrlr1_A, g_ctrlr2_A, g_ctrlr_B, g_ctrlr_C;
493  static struct spdk_nvmf_ns g_ns;
494  static struct spdk_bdev g_bdev;
495  struct spdk_nvmf_subsystem_pg_ns_info g_ns_info;
496  
497  void
498  nvmf_ctrlr_async_event_reservation_notification(struct spdk_nvmf_ctrlr *ctrlr)
499  {
500  }
501  
502  static void
503  ut_reservation_init(void)
504  {
505  
506  	TAILQ_INIT(&g_subsystem.ctrlrs);
507  
508  	memset(&g_ns, 0, sizeof(g_ns));
509  	TAILQ_INIT(&g_ns.registrants);
510  	g_ns.subsystem = &g_subsystem;
511  	g_ns.ptpl_file = NULL;
512  	g_ns.ptpl_activated = false;
513  	spdk_uuid_generate(&g_bdev.uuid);
514  	g_ns.bdev = &g_bdev;
515  
516  	/* Host A has two controllers */
517  	spdk_uuid_generate(&g_ctrlr1_A.hostid);
518  	TAILQ_INIT(&g_ctrlr1_A.log_head);
519  	g_ctrlr1_A.subsys = &g_subsystem;
520  	g_ctrlr1_A.num_avail_log_pages = 0;
521  	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr1_A, link);
522  	spdk_uuid_copy(&g_ctrlr2_A.hostid, &g_ctrlr1_A.hostid);
523  	TAILQ_INIT(&g_ctrlr2_A.log_head);
524  	g_ctrlr2_A.subsys = &g_subsystem;
525  	g_ctrlr2_A.num_avail_log_pages = 0;
526  	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr2_A, link);
527  
528  	/* Host B has 1 controller */
529  	spdk_uuid_generate(&g_ctrlr_B.hostid);
530  	TAILQ_INIT(&g_ctrlr_B.log_head);
531  	g_ctrlr_B.subsys = &g_subsystem;
532  	g_ctrlr_B.num_avail_log_pages = 0;
533  	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_B, link);
534  
535  	/* Host C has 1 controller */
536  	spdk_uuid_generate(&g_ctrlr_C.hostid);
537  	TAILQ_INIT(&g_ctrlr_C.log_head);
538  	g_ctrlr_C.subsys = &g_subsystem;
539  	g_ctrlr_C.num_avail_log_pages = 0;
540  	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_C, link);
541  }
542  
543  static void
544  ut_reservation_deinit(void)
545  {
546  	struct spdk_nvmf_registrant *reg, *tmp;
547  	struct spdk_nvmf_reservation_log *log, *log_tmp;
548  	struct spdk_nvmf_ctrlr *ctrlr, *ctrlr_tmp;
549  
550  	TAILQ_FOREACH_SAFE(reg, &g_ns.registrants, link, tmp) {
551  		TAILQ_REMOVE(&g_ns.registrants, reg, link);
552  		free(reg);
553  	}
554  	TAILQ_FOREACH_SAFE(log, &g_ctrlr1_A.log_head, link, log_tmp) {
555  		TAILQ_REMOVE(&g_ctrlr1_A.log_head, log, link);
556  		free(log);
557  	}
558  	g_ctrlr1_A.num_avail_log_pages = 0;
559  	TAILQ_FOREACH_SAFE(log, &g_ctrlr2_A.log_head, link, log_tmp) {
560  		TAILQ_REMOVE(&g_ctrlr2_A.log_head, log, link);
561  		free(log);
562  	}
563  	g_ctrlr2_A.num_avail_log_pages = 0;
564  	TAILQ_FOREACH_SAFE(log, &g_ctrlr_B.log_head, link, log_tmp) {
565  		TAILQ_REMOVE(&g_ctrlr_B.log_head, log, link);
566  		free(log);
567  	}
568  	g_ctrlr_B.num_avail_log_pages = 0;
569  	TAILQ_FOREACH_SAFE(log, &g_ctrlr_C.log_head, link, log_tmp) {
570  		TAILQ_REMOVE(&g_ctrlr_C.log_head, log, link);
571  		free(log);
572  	}
573  	g_ctrlr_C.num_avail_log_pages = 0;
574  
575  	TAILQ_FOREACH_SAFE(ctrlr, &g_subsystem.ctrlrs, link, ctrlr_tmp) {
576  		TAILQ_REMOVE(&g_subsystem.ctrlrs, ctrlr, link);
577  	}
578  }
579  
580  static struct spdk_nvmf_request *
581  ut_reservation_build_req(uint32_t length)
582  {
583  	struct spdk_nvmf_request *req;
584  
585  	req = calloc(1, sizeof(*req));
586  	assert(req != NULL);
587  
588  	req->data = calloc(1, length);
589  	assert(req->data != NULL);
590  	req->length = length;
591  
592  	req->cmd = (union nvmf_h2c_msg *)calloc(1, sizeof(union nvmf_h2c_msg));
593  	assert(req->cmd != NULL);
594  
595  	req->rsp = (union nvmf_c2h_msg *)calloc(1, sizeof(union nvmf_c2h_msg));
596  	assert(req->rsp != NULL);
597  
598  	return req;
599  }
600  
601  static void
602  ut_reservation_free_req(struct spdk_nvmf_request *req)
603  {
604  	free(req->cmd);
605  	free(req->rsp);
606  	free(req->data);
607  	free(req);
608  }
609  
610  static void
611  ut_reservation_build_register_request(struct spdk_nvmf_request *req,
612  				      uint8_t rrega, uint8_t iekey,
613  				      uint8_t cptpl, uint64_t crkey,
614  				      uint64_t nrkey)
615  {
616  	struct spdk_nvme_reservation_register_data key;
617  	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
618  
619  	key.crkey = crkey;
620  	key.nrkey = nrkey;
621  	cmd->cdw10 = 0;
622  	cmd->cdw10_bits.resv_register.rrega = rrega;
623  	cmd->cdw10_bits.resv_register.iekey = iekey;
624  	cmd->cdw10_bits.resv_register.cptpl = cptpl;
625  	memcpy(req->data, &key, sizeof(key));
626  }
627  
628  static void
629  ut_reservation_build_acquire_request(struct spdk_nvmf_request *req,
630  				     uint8_t racqa, uint8_t iekey,
631  				     uint8_t rtype, uint64_t crkey,
632  				     uint64_t prkey)
633  {
634  	struct spdk_nvme_reservation_acquire_data key;
635  	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
636  
637  	key.crkey = crkey;
638  	key.prkey = prkey;
639  	cmd->cdw10 = 0;
640  	cmd->cdw10_bits.resv_acquire.racqa = racqa;
641  	cmd->cdw10_bits.resv_acquire.iekey = iekey;
642  	cmd->cdw10_bits.resv_acquire.rtype = rtype;
643  	memcpy(req->data, &key, sizeof(key));
644  }
645  
646  static void
647  ut_reservation_build_release_request(struct spdk_nvmf_request *req,
648  				     uint8_t rrela, uint8_t iekey,
649  				     uint8_t rtype, uint64_t crkey)
650  {
651  	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
652  
653  	cmd->cdw10 = 0;
654  	cmd->cdw10_bits.resv_release.rrela = rrela;
655  	cmd->cdw10_bits.resv_release.iekey = iekey;
656  	cmd->cdw10_bits.resv_release.rtype = rtype;
657  	memcpy(req->data, &crkey, sizeof(crkey));
658  }
659  
660  /*
661   * Construct four registrants for other test cases.
662   *
663   * g_ctrlr1_A register with key 0xa1.
664   * g_ctrlr2_A register with key 0xa1.
665   * g_ctrlr_B register with key 0xb1.
666   * g_ctrlr_C register with key 0xc1.
667   * */
668  static void
669  ut_reservation_build_registrants(void)
670  {
671  	struct spdk_nvmf_request *req;
672  	struct spdk_nvme_cpl *rsp;
673  	struct spdk_nvmf_registrant *reg;
674  	uint32_t gen;
675  
676  	req = ut_reservation_build_req(16);
677  	rsp = &req->rsp->nvme_cpl;
678  	SPDK_CU_ASSERT_FATAL(req != NULL);
679  	gen = g_ns.gen;
680  
681  	/* TEST CASE: g_ctrlr1_A register with a new key */
682  	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
683  					      0, 0, 0, 0xa1);
684  	nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
685  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
686  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
687  	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa1);
688  	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 1);
689  
690  	/* TEST CASE: g_ctrlr2_A register with a new key, because it has same
691  	 * Host Identifier with g_ctrlr1_A, so the register key should same.
692  	 */
693  	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
694  					      0, 0, 0, 0xa2);
695  	nvmf_ns_reservation_register(&g_ns, &g_ctrlr2_A, req);
696  	/* Reservation conflict for other key than 0xa1 */
697  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT);
698  
699  	/* g_ctrlr_B register with a new key */
700  	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
701  					      0, 0, 0, 0xb1);
702  	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
703  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
704  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
705  	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb1);
706  	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 2);
707  
708  	/* g_ctrlr_C register with a new key */
709  	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
710  					      0, 0, 0, 0xc1);
711  	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req);
712  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
713  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
714  	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xc1);
715  	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 3);
716  
717  	ut_reservation_free_req(req);
718  }
719  
720  static void
721  test_reservation_register(void)
722  {
723  	struct spdk_nvmf_request *req;
724  	struct spdk_nvme_cpl *rsp;
725  	struct spdk_nvmf_registrant *reg;
726  	uint32_t gen;
727  
728  	ut_reservation_init();
729  
730  	req = ut_reservation_build_req(16);
731  	rsp = &req->rsp->nvme_cpl;
732  	SPDK_CU_ASSERT_FATAL(req != NULL);
733  
734  	ut_reservation_build_registrants();
735  
736  	/* TEST CASE: Replace g_ctrlr1_A with a new key */
737  	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
738  					      0, 0, 0xa1, 0xa11);
739  	nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
740  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
741  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
742  	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa11);
743  
744  	/* TEST CASE: Host A with g_ctrlr1_A get reservation with
745  	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
746  	 */
747  	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
748  					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xa11, 0x0);
749  	gen = g_ns.gen;
750  	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
751  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
752  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
753  	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
754  	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa11);
755  	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
756  	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen);
757  
758  	/* TEST CASE: g_ctrlr_C unregister with IEKEY enabled */
759  	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
760  					      1, 0, 0, 0);
761  	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req);
762  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
763  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
764  	SPDK_CU_ASSERT_FATAL(reg == NULL);
765  
766  	/* TEST CASE: g_ctrlr_B unregister with correct key */
767  	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
768  					      0, 0, 0xb1, 0);
769  	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
770  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
771  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
772  	SPDK_CU_ASSERT_FATAL(reg == NULL);
773  
774  	/* TEST CASE: No registrant now, g_ctrlr_B replace new key with IEKEY disabled */
775  	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
776  					      0, 0, 0, 0xb1);
777  	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
778  	SPDK_CU_ASSERT_FATAL(rsp->status.sc != SPDK_NVME_SC_SUCCESS);
779  
780  	/* TEST CASE: No registrant now, g_ctrlr_B replace new key with IEKEY enabled */
781  	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
782  					      1, 0, 0, 0xb1);
783  	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
784  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
785  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
786  	SPDK_CU_ASSERT_FATAL(reg != NULL);
787  
788  	/* TEST CASE: g_ctrlr_B replace new key with IEKEY enabled and wrong crkey  */
789  	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
790  					      1, 0, 0xff, 0xb2);
791  	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
792  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
793  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
794  	SPDK_CU_ASSERT_FATAL(reg != NULL);
795  	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb2);
796  
797  	/* TEST CASE: g_ctrlr1_A unregister with correct key,
798  	 * reservation should be removed as well.
799  	 */
800  	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
801  					      0, 0, 0xa11, 0);
802  	nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
803  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
804  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
805  	SPDK_CU_ASSERT_FATAL(reg == NULL);
806  	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
807  	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0);
808  	SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL);
809  
810  	ut_reservation_free_req(req);
811  	ut_reservation_deinit();
812  }
813  
814  static void
815  test_reservation_register_with_ptpl(void)
816  {
817  	struct spdk_nvmf_request *req;
818  	struct spdk_nvme_cpl *rsp;
819  	struct spdk_nvmf_registrant *reg;
820  	bool update_sgroup = false;
821  	int rc;
822  	struct spdk_nvmf_reservation_info info;
823  
824  	ut_reservation_init();
825  
826  	req = ut_reservation_build_req(16);
827  	rsp = &req->rsp->nvme_cpl;
828  	SPDK_CU_ASSERT_FATAL(req != NULL);
829  
830  	/* TEST CASE: No persistent file, register with PTPL enabled will fail */
831  	g_ns.ptpl_file = NULL;
832  	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
833  					      SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
834  	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
835  	SPDK_CU_ASSERT_FATAL(update_sgroup == false);
836  	SPDK_CU_ASSERT_FATAL(rsp->status.sc != SPDK_NVME_SC_SUCCESS);
837  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
838  	SPDK_CU_ASSERT_FATAL(reg == NULL);
839  
840  	/* TEST CASE: Enable PTPL */
841  	g_ns.ptpl_file = "/tmp/Ns1PR.cfg";
842  	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
843  					      SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
844  	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
845  	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
846  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
847  	SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true);
848  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
849  	SPDK_CU_ASSERT_FATAL(reg != NULL);
850  	SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &reg->hostid));
851  	/* Load reservation information from configuration file */
852  	memset(&info, 0, sizeof(info));
853  	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
854  	SPDK_CU_ASSERT_FATAL(rc == 0);
855  	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
856  
857  	/* TEST CASE: Disable PTPL */
858  	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
859  	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
860  					      SPDK_NVME_RESERVE_PTPL_CLEAR_POWER_ON, 0, 0xa1);
861  	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
862  	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
863  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
864  	SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == false);
865  	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
866  	SPDK_CU_ASSERT_FATAL(rc < 0);
867  	unlink(g_ns.ptpl_file);
868  
869  	ut_reservation_free_req(req);
870  	ut_reservation_deinit();
871  }
872  
873  static void
874  test_reservation_acquire_preempt_1(void)
875  {
876  	struct spdk_nvmf_request *req;
877  	struct spdk_nvme_cpl *rsp;
878  	struct spdk_nvmf_registrant *reg;
879  	uint32_t gen;
880  
881  	ut_reservation_init();
882  
883  	req = ut_reservation_build_req(16);
884  	rsp = &req->rsp->nvme_cpl;
885  	SPDK_CU_ASSERT_FATAL(req != NULL);
886  
887  	ut_reservation_build_registrants();
888  
889  	gen = g_ns.gen;
890  	/* ACQUIRE: Host A with g_ctrlr1_A acquire reservation with
891  	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE.
892  	 */
893  	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
894  					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0);
895  	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
896  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
897  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
898  	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
899  	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa1);
900  	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
901  	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen);
902  
903  	/* TEST CASE: g_ctrlr1_A holds the reservation, g_ctrlr_B preempt g_ctrl1_A,
904  	 * g_ctrl1_A registrant is unregistered.
905  	 */
906  	gen = g_ns.gen;
907  	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
908  					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1, 0xa1);
909  	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
910  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
911  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
912  	SPDK_CU_ASSERT_FATAL(reg == NULL);
913  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
914  	SPDK_CU_ASSERT_FATAL(reg != NULL);
915  	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
916  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
917  	SPDK_CU_ASSERT_FATAL(reg != NULL);
918  	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
919  	SPDK_CU_ASSERT_FATAL(g_ns.gen > gen);
920  
921  	/* TEST CASE: g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B
922  	 * with valid key and PRKEY set to 0, all registrants other the host that issued
923  	 * the command are unregistered.
924  	 */
925  	gen = g_ns.gen;
926  	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
927  					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0x0);
928  	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req);
929  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
930  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid);
931  	SPDK_CU_ASSERT_FATAL(reg == NULL);
932  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
933  	SPDK_CU_ASSERT_FATAL(reg == NULL);
934  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
935  	SPDK_CU_ASSERT_FATAL(reg != NULL);
936  	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
937  	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
938  	SPDK_CU_ASSERT_FATAL(g_ns.gen > gen);
939  
940  	ut_reservation_free_req(req);
941  	ut_reservation_deinit();
942  }
943  
944  static void
945  test_reservation_acquire_release_with_ptpl(void)
946  {
947  	struct spdk_nvmf_request *req;
948  	struct spdk_nvme_cpl *rsp;
949  	struct spdk_nvmf_registrant *reg;
950  	bool update_sgroup = false;
951  	struct spdk_uuid holder_uuid;
952  	int rc;
953  	struct spdk_nvmf_reservation_info info;
954  
955  	ut_reservation_init();
956  
957  	req = ut_reservation_build_req(16);
958  	rsp = &req->rsp->nvme_cpl;
959  	SPDK_CU_ASSERT_FATAL(req != NULL);
960  
961  	/* TEST CASE: Enable PTPL */
962  	g_ns.ptpl_file = "/tmp/Ns1PR.cfg";
963  	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
964  					      SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
965  	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
966  	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
967  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
968  	SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true);
969  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
970  	SPDK_CU_ASSERT_FATAL(reg != NULL);
971  	SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &reg->hostid));
972  	/* Load reservation information from configuration file */
973  	memset(&info, 0, sizeof(info));
974  	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
975  	SPDK_CU_ASSERT_FATAL(rc == 0);
976  	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
977  
978  	/* TEST CASE: Acquire the reservation */
979  	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
980  	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
981  					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0);
982  	update_sgroup = nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
983  	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
984  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
985  	memset(&info, 0, sizeof(info));
986  	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
987  	SPDK_CU_ASSERT_FATAL(rc == 0);
988  	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
989  	SPDK_CU_ASSERT_FATAL(info.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
990  	SPDK_CU_ASSERT_FATAL(info.crkey == 0xa1);
991  	spdk_uuid_parse(&holder_uuid, info.holder_uuid);
992  	SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &holder_uuid));
993  
994  	/* TEST CASE: Release the reservation */
995  	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
996  	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
997  					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1);
998  	update_sgroup = nvmf_ns_reservation_release(&g_ns, &g_ctrlr1_A, req);
999  	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
1000  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1001  	memset(&info, 0, sizeof(info));
1002  	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
1003  	SPDK_CU_ASSERT_FATAL(rc == 0);
1004  	SPDK_CU_ASSERT_FATAL(info.rtype == 0);
1005  	SPDK_CU_ASSERT_FATAL(info.crkey == 0);
1006  	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
1007  	unlink(g_ns.ptpl_file);
1008  
1009  	ut_reservation_free_req(req);
1010  	ut_reservation_deinit();
1011  }
1012  
1013  static void
1014  test_reservation_release(void)
1015  {
1016  	struct spdk_nvmf_request *req;
1017  	struct spdk_nvme_cpl *rsp;
1018  	struct spdk_nvmf_registrant *reg;
1019  
1020  	ut_reservation_init();
1021  
1022  	req = ut_reservation_build_req(16);
1023  	rsp = &req->rsp->nvme_cpl;
1024  	SPDK_CU_ASSERT_FATAL(req != NULL);
1025  
1026  	ut_reservation_build_registrants();
1027  
1028  	/* ACQUIRE: Host A with g_ctrlr1_A get reservation with
1029  	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS
1030  	 */
1031  	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1032  					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xa1, 0x0);
1033  	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
1034  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1035  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
1036  	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
1037  	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
1038  
1039  	/* Test Case: Host B release the reservation */
1040  	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1041  					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1);
1042  	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1043  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1044  	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1045  	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0);
1046  	SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL);
1047  
1048  	/* Test Case: Host C clear the registrants */
1049  	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0,
1050  					     0, 0xc1);
1051  	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_C, req);
1052  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1053  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
1054  	SPDK_CU_ASSERT_FATAL(reg == NULL);
1055  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid);
1056  	SPDK_CU_ASSERT_FATAL(reg == NULL);
1057  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
1058  	SPDK_CU_ASSERT_FATAL(reg == NULL);
1059  	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
1060  	SPDK_CU_ASSERT_FATAL(reg == NULL);
1061  
1062  	ut_reservation_free_req(req);
1063  	ut_reservation_deinit();
1064  }
1065  
1066  void
1067  nvmf_ctrlr_reservation_notice_log(struct spdk_nvmf_ctrlr *ctrlr,
1068  				  struct spdk_nvmf_ns *ns,
1069  				  enum spdk_nvme_reservation_notification_log_page_type type)
1070  {
1071  	ctrlr->num_avail_log_pages++;
1072  }
1073  
1074  static void
1075  test_reservation_unregister_notification(void)
1076  {
1077  	struct spdk_nvmf_request *req;
1078  	struct spdk_nvme_cpl *rsp;
1079  
1080  	ut_reservation_init();
1081  
1082  	req = ut_reservation_build_req(16);
1083  	SPDK_CU_ASSERT_FATAL(req != NULL);
1084  	rsp = &req->rsp->nvme_cpl;
1085  
1086  	ut_reservation_build_registrants();
1087  
1088  	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1089  	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1090  	 */
1091  	rsp->status.sc = 0xff;
1092  	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1093  					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1094  	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1095  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1096  	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1097  
1098  	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B unregister the registration.
1099  	 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C only for
1100  	 * SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY or SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY
1101  	 * type.
1102  	 */
1103  	rsp->status.sc = 0xff;
1104  	g_ctrlr1_A.num_avail_log_pages = 0;
1105  	g_ctrlr2_A.num_avail_log_pages = 0;
1106  	g_ctrlr_B.num_avail_log_pages = 5;
1107  	g_ctrlr_C.num_avail_log_pages = 0;
1108  	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
1109  					      0, 0, 0xb1, 0);
1110  	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
1111  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1112  	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1113  	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1114  	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1115  	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1116  	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1117  
1118  	ut_reservation_free_req(req);
1119  	ut_reservation_deinit();
1120  }
1121  
1122  static void
1123  test_reservation_release_notification(void)
1124  {
1125  	struct spdk_nvmf_request *req;
1126  	struct spdk_nvme_cpl *rsp;
1127  
1128  	ut_reservation_init();
1129  
1130  	req = ut_reservation_build_req(16);
1131  	SPDK_CU_ASSERT_FATAL(req != NULL);
1132  	rsp = &req->rsp->nvme_cpl;
1133  
1134  	ut_reservation_build_registrants();
1135  
1136  	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1137  	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1138  	 */
1139  	rsp->status.sc = 0xff;
1140  	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1141  					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1142  	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1143  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1144  	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1145  
1146  	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation.
1147  	 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C.
1148  	 */
1149  	rsp->status.sc = 0xff;
1150  	g_ctrlr1_A.num_avail_log_pages = 0;
1151  	g_ctrlr2_A.num_avail_log_pages = 0;
1152  	g_ctrlr_B.num_avail_log_pages = 5;
1153  	g_ctrlr_C.num_avail_log_pages = 0;
1154  	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1155  					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1);
1156  	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1157  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1158  	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1159  	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1160  	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1161  	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1162  	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1163  
1164  	ut_reservation_free_req(req);
1165  	ut_reservation_deinit();
1166  }
1167  
1168  static void
1169  test_reservation_release_notification_write_exclusive(void)
1170  {
1171  	struct spdk_nvmf_request *req;
1172  	struct spdk_nvme_cpl *rsp;
1173  
1174  	ut_reservation_init();
1175  
1176  	req = ut_reservation_build_req(16);
1177  	SPDK_CU_ASSERT_FATAL(req != NULL);
1178  	rsp = &req->rsp->nvme_cpl;
1179  
1180  	ut_reservation_build_registrants();
1181  
1182  	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1183  	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
1184  	 */
1185  	rsp->status.sc = 0xff;
1186  	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1187  					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1, 0x0);
1188  	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1189  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1190  	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
1191  
1192  	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation.
1193  	 * Because the reservation type is SPDK_NVME_RESERVE_WRITE_EXCLUSIVE,
1194  	 * no reservation notification occurs.
1195  	 */
1196  	rsp->status.sc = 0xff;
1197  	g_ctrlr1_A.num_avail_log_pages = 5;
1198  	g_ctrlr2_A.num_avail_log_pages = 5;
1199  	g_ctrlr_B.num_avail_log_pages = 5;
1200  	g_ctrlr_C.num_avail_log_pages = 5;
1201  	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1202  					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1);
1203  	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1204  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1205  	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1206  	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr1_A.num_avail_log_pages);
1207  	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr2_A.num_avail_log_pages);
1208  	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1209  	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages);
1210  
1211  	ut_reservation_free_req(req);
1212  	ut_reservation_deinit();
1213  }
1214  
1215  static void
1216  test_reservation_clear_notification(void)
1217  {
1218  	struct spdk_nvmf_request *req;
1219  	struct spdk_nvme_cpl *rsp;
1220  
1221  	ut_reservation_init();
1222  
1223  	req = ut_reservation_build_req(16);
1224  	SPDK_CU_ASSERT_FATAL(req != NULL);
1225  	rsp = &req->rsp->nvme_cpl;
1226  
1227  	ut_reservation_build_registrants();
1228  
1229  	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1230  	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1231  	 */
1232  	rsp->status.sc = 0xff;
1233  	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1234  					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1235  	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1236  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1237  	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1238  
1239  	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B clear the reservation.
1240  	 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C.
1241  	 */
1242  	rsp->status.sc = 0xff;
1243  	g_ctrlr1_A.num_avail_log_pages = 0;
1244  	g_ctrlr2_A.num_avail_log_pages = 0;
1245  	g_ctrlr_B.num_avail_log_pages = 5;
1246  	g_ctrlr_C.num_avail_log_pages = 0;
1247  	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0,
1248  					     0, 0xb1);
1249  	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1250  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1251  	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1252  	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1253  	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1254  	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1255  	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1256  
1257  	ut_reservation_free_req(req);
1258  	ut_reservation_deinit();
1259  }
1260  
1261  static void
1262  test_reservation_preempt_notification(void)
1263  {
1264  	struct spdk_nvmf_request *req;
1265  	struct spdk_nvme_cpl *rsp;
1266  
1267  	ut_reservation_init();
1268  
1269  	req = ut_reservation_build_req(16);
1270  	SPDK_CU_ASSERT_FATAL(req != NULL);
1271  	rsp = &req->rsp->nvme_cpl;
1272  
1273  	ut_reservation_build_registrants();
1274  
1275  	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1276  	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1277  	 */
1278  	rsp->status.sc = 0xff;
1279  	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1280  					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1281  	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1282  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1283  	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1284  
1285  	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B,
1286  	 * g_ctrlr_B registrant is unregistered, and reservation is preempted.
1287  	 * Registration Preempted notification sends to g_ctrlr_B.
1288  	 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A.
1289  	 */
1290  	rsp->status.sc = 0xff;
1291  	g_ctrlr1_A.num_avail_log_pages = 0;
1292  	g_ctrlr2_A.num_avail_log_pages = 0;
1293  	g_ctrlr_B.num_avail_log_pages = 0;
1294  	g_ctrlr_C.num_avail_log_pages = 5;
1295  	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
1296  					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0xb1);
1297  	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req);
1298  	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1299  	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
1300  	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1301  	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1302  	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_B.num_avail_log_pages);
1303  	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages);
1304  
1305  	ut_reservation_free_req(req);
1306  	ut_reservation_deinit();
1307  }
1308  
1309  static int
1310  nvmf_tgt_create_poll_group(void *io_device, void *ctx_buf)
1311  {
1312  	return 0;
1313  }
1314  
1315  static void
1316  nvmf_tgt_destroy_poll_group(void *io_device, void *ctx_buf)
1317  {
1318  }
1319  
1320  static void
1321  test_spdk_nvmf_ns_event(void)
1322  {
1323  	struct spdk_nvmf_tgt tgt = {};
1324  	struct spdk_nvmf_subsystem subsystem = {
1325  		.max_nsid = 1024,
1326  		.ns = NULL,
1327  		.tgt = &tgt,
1328  	};
1329  	struct spdk_nvmf_ctrlr ctrlr = {
1330  		.subsys = &subsystem
1331  	};
1332  	struct spdk_nvmf_ns_opts ns_opts;
1333  	uint32_t nsid;
1334  	struct spdk_bdev *bdev;
1335  
1336  	subsystem.ns = calloc(subsystem.max_nsid, sizeof(struct spdk_nvmf_subsystem_ns *));
1337  	SPDK_CU_ASSERT_FATAL(subsystem.ns != NULL);
1338  	subsystem.ana_group = calloc(subsystem.max_nsid, sizeof(uint32_t));
1339  	SPDK_CU_ASSERT_FATAL(subsystem.ana_group != NULL);
1340  
1341  	tgt.max_subsystems = 1024;
1342  	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
1343  	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
1344  
1345  	spdk_io_device_register(&tgt,
1346  				nvmf_tgt_create_poll_group,
1347  				nvmf_tgt_destroy_poll_group,
1348  				sizeof(struct spdk_nvmf_poll_group),
1349  				NULL);
1350  
1351  	/* Add one namespace */
1352  	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
1353  	nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev1", &ns_opts, sizeof(ns_opts), NULL);
1354  	CU_ASSERT(nsid == 1);
1355  	CU_ASSERT(NULL != subsystem.ns[0]);
1356  	CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &g_bdevs[nsid - 1]);
1357  
1358  	bdev = subsystem.ns[nsid - 1]->bdev;
1359  
1360  	/* Add one controller */
1361  	TAILQ_INIT(&subsystem.ctrlrs);
1362  	TAILQ_INSERT_TAIL(&subsystem.ctrlrs, &ctrlr, link);
1363  
1364  	/* Namespace resize event */
1365  	subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
1366  	g_ns_changed_nsid = 0xFFFFFFFF;
1367  	g_ns_changed_ctrlr = NULL;
1368  	nvmf_ns_event(SPDK_BDEV_EVENT_RESIZE, bdev, subsystem.ns[0]);
1369  	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state);
1370  
1371  	poll_threads();
1372  	CU_ASSERT(1 == g_ns_changed_nsid);
1373  	CU_ASSERT(&ctrlr == g_ns_changed_ctrlr);
1374  	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state);
1375  
1376  	/* Namespace remove event */
1377  	subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
1378  	g_ns_changed_nsid = 0xFFFFFFFF;
1379  	g_ns_changed_ctrlr = NULL;
1380  	nvmf_ns_event(SPDK_BDEV_EVENT_REMOVE, bdev, subsystem.ns[0]);
1381  	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state);
1382  	CU_ASSERT(0xFFFFFFFF == g_ns_changed_nsid);
1383  	CU_ASSERT(NULL == g_ns_changed_ctrlr);
1384  
1385  	poll_threads();
1386  	CU_ASSERT(1 == g_ns_changed_nsid);
1387  	CU_ASSERT(&ctrlr == g_ns_changed_ctrlr);
1388  	CU_ASSERT(NULL == subsystem.ns[0]);
1389  	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state);
1390  
1391  	spdk_io_device_unregister(&tgt, NULL);
1392  
1393  	poll_threads();
1394  
1395  	free(subsystem.ns);
1396  	free(subsystem.ana_group);
1397  	free(tgt.subsystems);
1398  }
1399  
1400  static void
1401  test_nvmf_ns_reservation_add_remove_registrant(void)
1402  {
1403  	struct spdk_nvmf_ns ns = {};
1404  	struct spdk_nvmf_ctrlr ctrlr = {};
1405  	struct spdk_nvmf_registrant *reg = NULL;
1406  	int rc;
1407  
1408  	TAILQ_INIT(&ns.registrants);
1409  	spdk_uuid_generate(&ctrlr.hostid);
1410  
1411  	rc = nvmf_ns_reservation_add_registrant(&ns, &ctrlr, 0xa11);
1412  	CU_ASSERT(rc == 0);
1413  	reg = TAILQ_FIRST(&ns.registrants);
1414  	SPDK_CU_ASSERT_FATAL(reg != NULL);
1415  	CU_ASSERT(ns.gen == 1);
1416  	CU_ASSERT(reg->rkey == 0xa11);
1417  	CU_ASSERT(!strncmp((uint8_t *)&reg->hostid, (uint8_t *)&ctrlr.hostid, sizeof(ctrlr.hostid)));
1418  
1419  	nvmf_ns_reservation_remove_registrant(&ns, reg);
1420  	CU_ASSERT(TAILQ_EMPTY(&ns.registrants));
1421  	CU_ASSERT(ns.gen == 2);
1422  }
1423  
1424  static void
1425  test_nvmf_subsystem_destroy_cb(void *cb_arg)
1426  {
1427  }
1428  
1429  static void
1430  test_nvmf_subsystem_add_ctrlr(void)
1431  {
1432  	int rc;
1433  	struct spdk_nvmf_ctrlr ctrlr = {};
1434  	struct spdk_nvmf_tgt tgt = {};
1435  	char nqn[256] = "nqn.2016-06.io.spdk:subsystem1";
1436  	struct spdk_nvmf_subsystem *subsystem = NULL;
1437  
1438  	tgt.max_subsystems = 1024;
1439  	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
1440  	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
1441  
1442  	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
1443  	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
1444  	ctrlr.subsys = subsystem;
1445  
1446  	ctrlr.dynamic_ctrlr = true;
1447  	rc = nvmf_subsystem_add_ctrlr(subsystem, &ctrlr);
1448  	CU_ASSERT(rc == 0);
1449  	CU_ASSERT(!TAILQ_EMPTY(&subsystem->ctrlrs));
1450  	CU_ASSERT(ctrlr.cntlid == 1);
1451  	CU_ASSERT(nvmf_subsystem_get_ctrlr(subsystem, 1) == &ctrlr);
1452  
1453  	nvmf_subsystem_remove_ctrlr(subsystem, &ctrlr);
1454  	CU_ASSERT(TAILQ_EMPTY(&subsystem->ctrlrs));
1455  	rc = spdk_nvmf_subsystem_destroy(subsystem, test_nvmf_subsystem_destroy_cb, NULL);
1456  	CU_ASSERT(rc == 0);
1457  	free(tgt.subsystems);
1458  }
1459  
1460  static void
1461  test_spdk_nvmf_subsystem_add_host(void)
1462  {
1463  	struct spdk_nvmf_tgt tgt = {};
1464  	struct spdk_nvmf_subsystem *subsystem = NULL;
1465  	int rc;
1466  	const char hostnqn[] = "nqn.2016-06.io.spdk:host1";
1467  	const char subsystemnqn[] = "nqn.2016-06.io.spdk:subsystem1";
1468  
1469  	tgt.max_subsystems = 1024;
1470  	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
1471  	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
1472  
1473  	subsystem = spdk_nvmf_subsystem_create(&tgt, subsystemnqn, SPDK_NVMF_SUBTYPE_NVME, 0);
1474  	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
1475  	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, subsystemnqn);
1476  
1477  	rc = spdk_nvmf_subsystem_add_host(subsystem, hostnqn);
1478  	CU_ASSERT(rc == 0);
1479  	CU_ASSERT(!TAILQ_EMPTY(&subsystem->hosts));
1480  
1481  	/* Add existing nqn, this function is allowed to be called if the nqn was previously added. */
1482  	rc = spdk_nvmf_subsystem_add_host(subsystem, hostnqn);
1483  	CU_ASSERT(rc == 0);
1484  
1485  	rc = spdk_nvmf_subsystem_remove_host(subsystem, hostnqn);
1486  	CU_ASSERT(rc == 0);
1487  	CU_ASSERT(TAILQ_EMPTY(&subsystem->hosts));
1488  
1489  	/* No available nqn */
1490  	rc = spdk_nvmf_subsystem_remove_host(subsystem, hostnqn);
1491  	CU_ASSERT(rc == -ENOENT);
1492  
1493  	spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
1494  	free(tgt.subsystems);
1495  }
1496  
1497  static void
1498  test_nvmf_ns_reservation_report(void)
1499  {
1500  	struct spdk_nvmf_ns ns = {};
1501  	struct spdk_nvmf_ctrlr ctrlr = {};
1502  	struct spdk_nvmf_request req = {};
1503  	union nvmf_h2c_msg cmd = {};
1504  	union nvmf_c2h_msg rsp = {};
1505  	struct spdk_nvme_registered_ctrlr_extended_data *ctrlr_data;
1506  	struct spdk_nvme_reservation_status_extended_data *status_data;
1507  	struct spdk_nvmf_registrant *reg;
1508  
1509  	req.data = calloc(1, sizeof(*status_data) + sizeof(*ctrlr_data) * 2);
1510  	reg = calloc(2, sizeof(struct spdk_nvmf_registrant));
1511  	SPDK_CU_ASSERT_FATAL(req.data != NULL && reg != NULL);
1512  
1513  	req.cmd = &cmd;
1514  	req.rsp = &rsp;
1515  	ns.gen = 1;
1516  	ns.rtype = SPDK_NVME_RESERVE_WRITE_EXCLUSIVE;
1517  	ns.ptpl_activated = true;
1518  	cmd.nvme_cmd.cdw11_bits.resv_report.eds = true;
1519  	cmd.nvme_cmd.cdw10 = 100;
1520  	reg[0].rkey = 0xa;
1521  	reg[1].rkey = 0xb;
1522  	spdk_uuid_generate(&reg[0].hostid);
1523  	spdk_uuid_generate(&reg[1].hostid);
1524  	TAILQ_INIT(&ns.registrants);
1525  	TAILQ_INSERT_TAIL(&ns.registrants, &reg[0], link);
1526  	TAILQ_INSERT_TAIL(&ns.registrants, &reg[1], link);
1527  
1528  	nvmf_ns_reservation_report(&ns, &ctrlr, &req);
1529  	CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC);
1530  	CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS);
1531  	/* Get ctrlr data and status data pointers */
1532  	ctrlr_data = (void *)((uint64_t)req.data + sizeof(*status_data));
1533  	status_data = (void *)req.data;
1534  	SPDK_CU_ASSERT_FATAL(status_data != NULL && ctrlr_data != NULL);
1535  	CU_ASSERT(status_data->data.gen == 1);
1536  	CU_ASSERT(status_data->data.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
1537  	CU_ASSERT(status_data->data.ptpls == true);
1538  	CU_ASSERT(status_data->data.regctl == 2);
1539  	CU_ASSERT(ctrlr_data->cntlid == 0xffff);
1540  	CU_ASSERT(ctrlr_data->rcsts.status == false);
1541  	CU_ASSERT(ctrlr_data->rkey ==  0xa);
1542  	CU_ASSERT(!spdk_uuid_compare((struct spdk_uuid *)ctrlr_data->hostid, &reg[0].hostid));
1543  	/* Check second ctrlr data */
1544  	ctrlr_data++;
1545  	CU_ASSERT(ctrlr_data->cntlid == 0xffff);
1546  	CU_ASSERT(ctrlr_data->rcsts.status == false);
1547  	CU_ASSERT(ctrlr_data->rkey ==  0xb);
1548  	CU_ASSERT(!spdk_uuid_compare((struct spdk_uuid *)ctrlr_data->hostid, &reg[1].hostid));
1549  
1550  	/* extended controller data structure */
1551  	memset(req.data, 0, sizeof(*status_data) + sizeof(*ctrlr_data) * 2);
1552  	memset(req.rsp, 0, sizeof(*req.rsp));
1553  	cmd.nvme_cmd.cdw11_bits.resv_report.eds = false;
1554  
1555  	nvmf_ns_reservation_report(&ns, &ctrlr, &req);
1556  	CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_HOSTID_INCONSISTENT_FORMAT);
1557  	CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC);
1558  
1559  	/* Transfer length invalid */
1560  	memset(req.data, 0, sizeof(*status_data) + sizeof(*ctrlr_data) * 2);
1561  	memset(req.rsp, 0, sizeof(*req.rsp));
1562  	cmd.nvme_cmd.cdw11_bits.resv_report.eds = true;
1563  	cmd.nvme_cmd.cdw10 = 0;
1564  
1565  	nvmf_ns_reservation_report(&ns, &ctrlr, &req);
1566  	CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_INTERNAL_DEVICE_ERROR);
1567  	CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC);
1568  
1569  	free(req.data);
1570  	free(reg);
1571  }
1572  
1573  static void
1574  test_nvmf_valid_nqn(void)
1575  {
1576  	bool rc;
1577  	char uuid[SPDK_NVMF_UUID_STRING_LEN + 1] = {};
1578  	char nqn[SPDK_NVMF_NQN_MAX_LEN + 1] = {};
1579  	struct spdk_uuid s_uuid = {};
1580  
1581  	spdk_uuid_generate(&s_uuid);
1582  	uuid_unparse((void *)&s_uuid, uuid);
1583  
1584  	/* discovery nqn */
1585  	snprintf(nqn, sizeof(nqn), "%s", SPDK_NVMF_DISCOVERY_NQN);
1586  
1587  	rc = nvmf_valid_nqn(nqn);
1588  	CU_ASSERT(rc == true);
1589  
1590  	/* nqn with uuid */
1591  	memset(nqn, 0xff, sizeof(nqn));
1592  	snprintf(nqn, sizeof(nqn), "%s%s", SPDK_NVMF_NQN_UUID_PRE, uuid);
1593  
1594  	rc = nvmf_valid_nqn(nqn);
1595  	CU_ASSERT(rc == true);
1596  
1597  	/* Check nqn valid reverse domain */
1598  	memset(nqn, 0xff, sizeof(nqn));
1599  	snprintf(nqn, sizeof(nqn), "%s", "nqn.2016-06.io.spdk:cnode1");
1600  
1601  	rc = nvmf_valid_nqn(nqn);
1602  	CU_ASSERT(rc == true);
1603  
1604  	/* Invalid nqn length */
1605  	memset(nqn, 0xff, sizeof(nqn));
1606  	snprintf(nqn, sizeof(nqn), "%s", "nqn.");
1607  
1608  	rc = nvmf_valid_nqn(nqn);
1609  	CU_ASSERT(rc == false);
1610  
1611  	/* Copy uuid to the nqn string, but omit the last character to make it invalid */
1612  	memset(nqn, 0, SPDK_NVMF_NQN_MAX_LEN + 1);
1613  	snprintf(nqn, sizeof(nqn), "%s", SPDK_NVMF_NQN_UUID_PRE);
1614  	memcpy(&nqn[SPDK_NVMF_NQN_UUID_PRE_LEN], uuid, SPDK_NVMF_UUID_STRING_LEN - 1);
1615  
1616  	rc = nvmf_valid_nqn(nqn);
1617  	CU_ASSERT(rc == false);
1618  
1619  	/* Invalid domain */
1620  	memset(nqn, 0xff, SPDK_NVMF_NQN_MAX_LEN + 1);
1621  	snprintf(nqn, sizeof(nqn), "%s", "nqn.2016-06.io...spdk:cnode1");
1622  
1623  	rc = nvmf_valid_nqn(nqn);
1624  	CU_ASSERT(rc == false);
1625  }
1626  
1627  static void
1628  test_nvmf_ns_reservation_restore(void)
1629  {
1630  	struct spdk_nvmf_ns ns = {};
1631  	struct spdk_nvmf_reservation_info info = {};
1632  	struct spdk_bdev bdev = {};
1633  	struct spdk_uuid s_uuid = {};
1634  	struct spdk_nvmf_registrant *reg0, *reg1;
1635  	char uuid[SPDK_UUID_STRING_LEN] = {};
1636  	int rc;
1637  
1638  	ns.bdev = &bdev;
1639  	TAILQ_INIT(&ns.registrants);
1640  	info.ptpl_activated = true;
1641  	info.num_regs = 2;
1642  	info.rtype = SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS;
1643  	info.registrants[0].rkey = 0xb;
1644  	info.registrants[1].rkey = 0xc;
1645  
1646  	/* Generate and prepare uuids, make sure bdev and info uuid are the same */
1647  	spdk_uuid_generate(&s_uuid);
1648  	uuid_unparse((void *)&s_uuid, uuid);
1649  	snprintf(info.holder_uuid, SPDK_UUID_STRING_LEN, "%s", uuid);
1650  	snprintf(info.bdev_uuid, SPDK_UUID_STRING_LEN, "%s", uuid);
1651  	snprintf(info.registrants[0].host_uuid, SPDK_UUID_STRING_LEN, "%s", uuid);
1652  	spdk_uuid_copy(&bdev.uuid, &s_uuid);
1653  	spdk_uuid_generate(&s_uuid);
1654  	uuid_unparse((void *)&s_uuid, uuid);
1655  	snprintf(info.registrants[1].host_uuid, SPDK_UUID_STRING_LEN, "%s", uuid);
1656  
1657  	/* info->rkey not exist in registrants */
1658  	info.crkey = 0xa;
1659  
1660  	rc = nvmf_ns_reservation_restore(&ns, &info);
1661  	CU_ASSERT(rc == -EINVAL);
1662  
1663  	/* info->rkey exists in registrants */
1664  	info.crkey = 0xb;
1665  
1666  	rc = nvmf_ns_reservation_restore(&ns, &info);
1667  	CU_ASSERT(rc == 0);
1668  	CU_ASSERT(ns.crkey == 0xb);
1669  	CU_ASSERT(ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
1670  	CU_ASSERT(ns.ptpl_activated == true);
1671  	/* Check two registrant`s rkey */
1672  	reg0 = TAILQ_FIRST(&ns.registrants);
1673  	reg1 = TAILQ_NEXT(reg0, link);
1674  	CU_ASSERT(ns.holder == reg0);
1675  	CU_ASSERT(reg0->rkey = 0xb);
1676  	CU_ASSERT(reg1->rkey = 0xc);
1677  
1678  	rc = nvmf_ns_reservation_clear_all_registrants(&ns);
1679  	CU_ASSERT(rc == 2);
1680  	CU_ASSERT(TAILQ_EMPTY(&ns.registrants));
1681  
1682  	/* Existing bdev UUID is different with configuration */
1683  	spdk_uuid_generate(&s_uuid);
1684  	uuid_unparse((void *)&s_uuid, uuid);
1685  	snprintf(info.bdev_uuid, SPDK_UUID_STRING_LEN, "%s", uuid);
1686  	spdk_uuid_generate(&s_uuid);
1687  	spdk_uuid_copy(&bdev.uuid, &s_uuid);
1688  
1689  	rc = nvmf_ns_reservation_restore(&ns, &info);
1690  	CU_ASSERT(rc == -EINVAL);
1691  }
1692  
1693  static void
1694  test_nvmf_subsystem_state_change(void)
1695  {
1696  	struct spdk_nvmf_tgt tgt = {};
1697  	struct spdk_nvmf_subsystem *subsystem, *discovery_subsystem;
1698  	int rc;
1699  
1700  	tgt.max_subsystems = 1024;
1701  	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
1702  	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
1703  
1704  	discovery_subsystem = spdk_nvmf_subsystem_create(&tgt, SPDK_NVMF_DISCOVERY_NQN,
1705  			      SPDK_NVMF_SUBTYPE_DISCOVERY, 0);
1706  	SPDK_CU_ASSERT_FATAL(discovery_subsystem != NULL);
1707  	subsystem = spdk_nvmf_subsystem_create(&tgt, "nqn.2016-06.io.spdk:subsystem1",
1708  					       SPDK_NVMF_SUBTYPE_NVME, 0);
1709  	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
1710  
1711  	spdk_io_device_register(&tgt,
1712  				nvmf_tgt_create_poll_group,
1713  				nvmf_tgt_destroy_poll_group,
1714  				sizeof(struct spdk_nvmf_poll_group),
1715  				NULL);
1716  
1717  	rc = spdk_nvmf_subsystem_start(discovery_subsystem, NULL, NULL);
1718  	CU_ASSERT(rc == 0);
1719  	poll_threads();
1720  	CU_ASSERT(discovery_subsystem->state == SPDK_NVMF_SUBSYSTEM_ACTIVE);
1721  	rc = spdk_nvmf_subsystem_start(subsystem, NULL, NULL);
1722  	CU_ASSERT(rc == 0);
1723  	poll_threads();
1724  	CU_ASSERT(subsystem->state == SPDK_NVMF_SUBSYSTEM_ACTIVE);
1725  
1726  	rc = spdk_nvmf_subsystem_pause(subsystem, SPDK_NVME_GLOBAL_NS_TAG, NULL, NULL);
1727  	CU_ASSERT(rc == 0);
1728  	rc = spdk_nvmf_subsystem_stop(subsystem, NULL, NULL);
1729  	CU_ASSERT(rc == -EBUSY);
1730  	poll_threads();
1731  	CU_ASSERT(subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED);
1732  
1733  	rc = spdk_nvmf_subsystem_stop(discovery_subsystem, NULL, NULL);
1734  	CU_ASSERT(rc == 0);
1735  	poll_threads();
1736  	CU_ASSERT(discovery_subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE);
1737  	rc = spdk_nvmf_subsystem_stop(subsystem, NULL, NULL);
1738  	CU_ASSERT(rc == 0);
1739  	poll_threads();
1740  	CU_ASSERT(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE);
1741  
1742  	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
1743  	CU_ASSERT(rc == 0);
1744  	rc = spdk_nvmf_subsystem_destroy(discovery_subsystem, NULL, NULL);
1745  	CU_ASSERT(rc == 0);
1746  
1747  	spdk_io_device_unregister(&tgt, NULL);
1748  	poll_threads();
1749  
1750  	free(tgt.subsystems);
1751  }
1752  
1753  int
1754  main(int argc, char **argv)
1755  {
1756  	CU_pSuite	suite = NULL;
1757  	unsigned int	num_failures;
1758  
1759  	CU_set_error_action(CUEA_ABORT);
1760  	CU_initialize_registry();
1761  
1762  	suite = CU_add_suite("nvmf", NULL, NULL);
1763  
1764  	CU_ADD_TEST(suite, nvmf_test_create_subsystem);
1765  	CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_add_ns);
1766  	CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_set_sn);
1767  	CU_ADD_TEST(suite, test_reservation_register);
1768  	CU_ADD_TEST(suite, test_reservation_register_with_ptpl);
1769  	CU_ADD_TEST(suite, test_reservation_acquire_preempt_1);
1770  	CU_ADD_TEST(suite, test_reservation_acquire_release_with_ptpl);
1771  	CU_ADD_TEST(suite, test_reservation_release);
1772  	CU_ADD_TEST(suite, test_reservation_unregister_notification);
1773  	CU_ADD_TEST(suite, test_reservation_release_notification);
1774  	CU_ADD_TEST(suite, test_reservation_release_notification_write_exclusive);
1775  	CU_ADD_TEST(suite, test_reservation_clear_notification);
1776  	CU_ADD_TEST(suite, test_reservation_preempt_notification);
1777  	CU_ADD_TEST(suite, test_spdk_nvmf_ns_event);
1778  	CU_ADD_TEST(suite, test_nvmf_ns_reservation_add_remove_registrant);
1779  	CU_ADD_TEST(suite, test_nvmf_subsystem_add_ctrlr);
1780  	CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_add_host);
1781  	CU_ADD_TEST(suite, test_nvmf_ns_reservation_report);
1782  	CU_ADD_TEST(suite, test_nvmf_valid_nqn);
1783  	CU_ADD_TEST(suite, test_nvmf_ns_reservation_restore);
1784  	CU_ADD_TEST(suite, test_nvmf_subsystem_state_change);
1785  
1786  	allocate_threads(1);
1787  	set_thread(0);
1788  
1789  	CU_basic_set_mode(CU_BRM_VERBOSE);
1790  	CU_basic_run_tests();
1791  	num_failures = CU_get_number_of_failures();
1792  	CU_cleanup_registry();
1793  
1794  	free_threads();
1795  
1796  	return num_failures;
1797  }
1798