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