xref: /spdk/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c (revision 0ed85362c8132a2d1927757fbcade66b6660d26a)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation. All rights reserved.
5  *   Copyright (c) 2019 Mellanox Technologies LTD. All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/stdinc.h"
35 
36 #include "common/lib/ut_multithread.c"
37 #include "spdk_cunit.h"
38 #include "spdk_internal/mock.h"
39 #include "spdk_internal/thread.h"
40 
41 #include "nvmf/subsystem.c"
42 
43 SPDK_LOG_REGISTER_COMPONENT("nvmf", SPDK_LOG_NVMF)
44 
45 DEFINE_STUB(spdk_bdev_module_claim_bdev,
46 	    int,
47 	    (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
48 	     struct spdk_bdev_module *module), 0);
49 
50 DEFINE_STUB_V(spdk_bdev_module_release_bdev,
51 	      (struct spdk_bdev *bdev));
52 
53 DEFINE_STUB(spdk_bdev_get_block_size, uint32_t,
54 	    (const struct spdk_bdev *bdev), 512);
55 
56 DEFINE_STUB(spdk_bdev_get_md_size, uint32_t,
57 	    (const struct spdk_bdev *bdev), 0);
58 
59 DEFINE_STUB(spdk_bdev_is_md_interleaved, bool,
60 	    (const struct spdk_bdev *bdev), false);
61 
62 DEFINE_STUB(spdk_nvmf_transport_stop_listen,
63 	    int,
64 	    (struct spdk_nvmf_transport *transport,
65 	     const struct spdk_nvme_transport_id *trid), 0);
66 
67 int
68 spdk_nvmf_transport_listen(struct spdk_nvmf_transport *transport,
69 			   const struct spdk_nvme_transport_id *trid)
70 {
71 	return 0;
72 }
73 
74 void
75 nvmf_transport_listener_discover(struct spdk_nvmf_transport *transport,
76 				 struct spdk_nvme_transport_id *trid,
77 				 struct spdk_nvmf_discovery_log_page_entry *entry)
78 {
79 	entry->trtype = 42;
80 }
81 
82 static struct spdk_nvmf_transport g_transport = {};
83 
84 struct spdk_nvmf_transport *
85 spdk_nvmf_transport_create(const char *transport_name,
86 			   struct spdk_nvmf_transport_opts *tprt_opts)
87 {
88 	if (strcasecmp(transport_name, spdk_nvme_transport_id_trtype_str(SPDK_NVME_TRANSPORT_RDMA))) {
89 		return &g_transport;
90 	}
91 
92 	return NULL;
93 }
94 
95 struct spdk_nvmf_subsystem *
96 spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt *tgt, const char *subnqn)
97 {
98 	return NULL;
99 }
100 
101 struct spdk_nvmf_transport *
102 spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, const char *transport_name)
103 {
104 	if (strncmp(transport_name, SPDK_NVME_TRANSPORT_NAME_RDMA, SPDK_NVMF_TRSTRING_MAX_LEN)) {
105 		return &g_transport;
106 	}
107 
108 	return NULL;
109 }
110 
111 int
112 nvmf_poll_group_update_subsystem(struct spdk_nvmf_poll_group *group,
113 				 struct spdk_nvmf_subsystem *subsystem)
114 {
115 	return 0;
116 }
117 
118 int
119 nvmf_poll_group_add_subsystem(struct spdk_nvmf_poll_group *group,
120 			      struct spdk_nvmf_subsystem *subsystem,
121 			      spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
122 {
123 	return 0;
124 }
125 
126 void
127 nvmf_poll_group_remove_subsystem(struct spdk_nvmf_poll_group *group,
128 				 struct spdk_nvmf_subsystem *subsystem,
129 				 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
130 {
131 }
132 
133 void
134 nvmf_poll_group_pause_subsystem(struct spdk_nvmf_poll_group *group,
135 				struct spdk_nvmf_subsystem *subsystem,
136 				spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
137 {
138 }
139 
140 void
141 nvmf_poll_group_resume_subsystem(struct spdk_nvmf_poll_group *group,
142 				 struct spdk_nvmf_subsystem *subsystem,
143 				 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
144 {
145 }
146 
147 int
148 spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type *trtype, const char *str)
149 {
150 	if (trtype == NULL || str == NULL) {
151 		return -EINVAL;
152 	}
153 
154 	if (strcasecmp(str, "PCIe") == 0) {
155 		*trtype = SPDK_NVME_TRANSPORT_PCIE;
156 	} else if (strcasecmp(str, "RDMA") == 0) {
157 		*trtype = SPDK_NVME_TRANSPORT_RDMA;
158 	} else {
159 		return -ENOENT;
160 	}
161 	return 0;
162 }
163 
164 int
165 spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id *trid1,
166 			       const struct spdk_nvme_transport_id *trid2)
167 {
168 	return 0;
169 }
170 
171 int32_t
172 spdk_nvme_ctrlr_process_admin_completions(struct spdk_nvme_ctrlr *ctrlr)
173 {
174 	return -1;
175 }
176 
177 int32_t
178 spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_completions)
179 {
180 	return -1;
181 }
182 
183 int
184 spdk_nvme_detach(struct spdk_nvme_ctrlr *ctrlr)
185 {
186 	return -1;
187 }
188 
189 void
190 nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr)
191 {
192 }
193 
194 static struct spdk_nvmf_ctrlr *g_ns_changed_ctrlr = NULL;
195 static uint32_t g_ns_changed_nsid = 0;
196 void
197 nvmf_ctrlr_ns_changed(struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid)
198 {
199 	g_ns_changed_ctrlr = ctrlr;
200 	g_ns_changed_nsid = nsid;
201 }
202 
203 int
204 spdk_bdev_open_ext(const char *bdev_name, bool write, spdk_bdev_event_cb_t event_cb,
205 		   void *event_ctx, struct spdk_bdev_desc **_desc)
206 {
207 	return 0;
208 }
209 
210 void
211 spdk_bdev_close(struct spdk_bdev_desc *desc)
212 {
213 }
214 
215 const char *
216 spdk_bdev_get_name(const struct spdk_bdev *bdev)
217 {
218 	return "test";
219 }
220 
221 const struct spdk_uuid *
222 spdk_bdev_get_uuid(const struct spdk_bdev *bdev)
223 {
224 	return &bdev->uuid;
225 }
226 
227 static void
228 test_spdk_nvmf_subsystem_add_ns(void)
229 {
230 	struct spdk_nvmf_tgt tgt = {};
231 	struct spdk_nvmf_subsystem subsystem = {
232 		.max_nsid = 0,
233 		.ns = NULL,
234 		.tgt = &tgt
235 	};
236 	struct spdk_bdev bdev1 = {}, bdev2 = {};
237 	struct spdk_nvmf_ns_opts ns_opts;
238 	uint32_t nsid;
239 	int rc;
240 
241 	tgt.max_subsystems = 1024;
242 	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
243 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
244 
245 	/* Allow NSID to be assigned automatically */
246 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
247 	nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev1, &ns_opts, sizeof(ns_opts), NULL);
248 	/* NSID 1 is the first unused ID */
249 	CU_ASSERT(nsid == 1);
250 	CU_ASSERT(subsystem.max_nsid == 1);
251 	SPDK_CU_ASSERT_FATAL(subsystem.ns != NULL);
252 	SPDK_CU_ASSERT_FATAL(subsystem.ns[nsid - 1] != NULL);
253 	CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &bdev1);
254 
255 	/* Request a specific NSID */
256 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
257 	ns_opts.nsid = 5;
258 	nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev2, &ns_opts, sizeof(ns_opts), NULL);
259 	CU_ASSERT(nsid == 5);
260 	CU_ASSERT(subsystem.max_nsid == 5);
261 	SPDK_CU_ASSERT_FATAL(subsystem.ns[nsid - 1] != NULL);
262 	CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &bdev2);
263 
264 	/* Request an NSID that is already in use */
265 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
266 	ns_opts.nsid = 5;
267 	nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev2, &ns_opts, sizeof(ns_opts), NULL);
268 	CU_ASSERT(nsid == 0);
269 	CU_ASSERT(subsystem.max_nsid == 5);
270 
271 	/* Request 0xFFFFFFFF (invalid NSID, reserved for broadcast) */
272 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
273 	ns_opts.nsid = 0xFFFFFFFF;
274 	nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev2, &ns_opts, sizeof(ns_opts), NULL);
275 	CU_ASSERT(nsid == 0);
276 	CU_ASSERT(subsystem.max_nsid == 5);
277 
278 	rc = spdk_nvmf_subsystem_remove_ns(&subsystem, 1);
279 	CU_ASSERT(rc == 0);
280 	rc = spdk_nvmf_subsystem_remove_ns(&subsystem, 5);
281 	CU_ASSERT(rc == 0);
282 
283 	free(subsystem.ns);
284 	free(tgt.subsystems);
285 }
286 
287 static void
288 nvmf_test_create_subsystem(void)
289 {
290 	struct spdk_nvmf_tgt tgt = {};
291 	char nqn[256];
292 	struct spdk_nvmf_subsystem *subsystem;
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 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
299 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
300 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
301 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
302 	spdk_nvmf_subsystem_destroy(subsystem);
303 
304 	/* valid name with complex reverse domain */
305 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-full--rev-domain.name:subsystem1");
306 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
307 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
308 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
309 	spdk_nvmf_subsystem_destroy(subsystem);
310 
311 	/* Valid name discovery controller */
312 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
313 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
314 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
315 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
316 	spdk_nvmf_subsystem_destroy(subsystem);
317 
318 
319 	/* Invalid name, no user supplied string */
320 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:");
321 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
322 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
323 
324 	/* Valid name, only contains top-level domain name */
325 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
326 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
327 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
328 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
329 	spdk_nvmf_subsystem_destroy(subsystem);
330 
331 	/* Invalid name, domain label > 63 characters */
332 	snprintf(nqn, sizeof(nqn),
333 		 "nqn.2016-06.io.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz:sub");
334 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
335 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
336 
337 	/* Invalid name, domain label starts with digit */
338 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.3spdk:sub");
339 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
340 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
341 
342 	/* Invalid name, domain label starts with - */
343 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.-spdk:subsystem1");
344 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
345 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
346 
347 	/* Invalid name, domain label ends with - */
348 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-:subsystem1");
349 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
350 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
351 
352 	/* Invalid name, domain label with multiple consecutive periods */
353 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io..spdk:subsystem1");
354 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
355 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
356 
357 	/* Longest valid name */
358 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:");
359 	memset(nqn + strlen(nqn), 'a', 223 - strlen(nqn));
360 	nqn[223] = '\0';
361 	CU_ASSERT(strlen(nqn) == 223);
362 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
363 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
364 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
365 	spdk_nvmf_subsystem_destroy(subsystem);
366 
367 	/* Invalid name, too long */
368 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:");
369 	memset(nqn + strlen(nqn), 'a', 224 - strlen(nqn));
370 	nqn[224] = '\0';
371 	CU_ASSERT(strlen(nqn) == 224);
372 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
373 	CU_ASSERT(subsystem == NULL);
374 
375 	/* Valid name using uuid format */
376 	snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:11111111-aaaa-bbdd-FFEE-123456789abc");
377 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
378 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
379 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
380 	spdk_nvmf_subsystem_destroy(subsystem);
381 
382 	/* Invalid name user string contains an invalid utf-8 character */
383 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xFFsubsystem1");
384 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
385 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
386 
387 	/* Valid name with non-ascii but valid utf-8 characters */
388 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xe1\x8a\x88subsystem1\xca\x80");
389 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
390 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
391 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
392 	spdk_nvmf_subsystem_destroy(subsystem);
393 
394 	/* Invalid uuid (too long) */
395 	snprintf(nqn, sizeof(nqn),
396 		 "nqn.2014-08.org.nvmexpress:uuid:11111111-aaaa-bbdd-FFEE-123456789abcdef");
397 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
398 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
399 
400 	/* Invalid uuid (dashes placed incorrectly) */
401 	snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:111111-11aaaa-bbdd-FFEE-123456789abc");
402 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
403 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
404 
405 	/* Invalid uuid (invalid characters in uuid) */
406 	snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:111hg111-aaaa-bbdd-FFEE-123456789abc");
407 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
408 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
409 
410 	free(tgt.subsystems);
411 }
412 
413 static void
414 test_spdk_nvmf_subsystem_set_sn(void)
415 {
416 	struct spdk_nvmf_subsystem subsystem = {};
417 
418 	/* Basic valid serial number */
419 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd xyz") == 0);
420 	CU_ASSERT(strcmp(subsystem.sn, "abcd xyz") == 0);
421 
422 	/* Exactly 20 characters (valid) */
423 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "12345678901234567890") == 0);
424 	CU_ASSERT(strcmp(subsystem.sn, "12345678901234567890") == 0);
425 
426 	/* 21 characters (too long, invalid) */
427 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "123456789012345678901") < 0);
428 
429 	/* Non-ASCII characters (invalid) */
430 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd\txyz") < 0);
431 }
432 
433 /*
434  * Reservation Unit Test Configuration
435  *       --------             --------    --------
436  *      | Host A |           | Host B |  | Host C |
437  *       --------             --------    --------
438  *      /        \               |           |
439  *  --------   --------       -------     -------
440  * |Ctrlr1_A| |Ctrlr2_A|     |Ctrlr_B|   |Ctrlr_C|
441  *  --------   --------       -------     -------
442  *    \           \              /           /
443  *     \           \            /           /
444  *      \           \          /           /
445  *      --------------------------------------
446  *     |            NAMESPACE 1               |
447  *      --------------------------------------
448  */
449 static struct spdk_nvmf_subsystem g_subsystem;
450 static struct spdk_nvmf_ctrlr g_ctrlr1_A, g_ctrlr2_A, g_ctrlr_B, g_ctrlr_C;
451 static struct spdk_nvmf_ns g_ns;
452 static struct spdk_bdev g_bdev;
453 struct spdk_nvmf_subsystem_pg_ns_info g_ns_info;
454 
455 void
456 nvmf_ctrlr_async_event_reservation_notification(struct spdk_nvmf_ctrlr *ctrlr)
457 {
458 }
459 
460 static void
461 ut_reservation_init(void)
462 {
463 
464 	TAILQ_INIT(&g_subsystem.ctrlrs);
465 
466 	memset(&g_ns, 0, sizeof(g_ns));
467 	TAILQ_INIT(&g_ns.registrants);
468 	g_ns.subsystem = &g_subsystem;
469 	g_ns.ptpl_file = NULL;
470 	g_ns.ptpl_activated = false;
471 	spdk_uuid_generate(&g_bdev.uuid);
472 	g_ns.bdev = &g_bdev;
473 
474 	/* Host A has two controllers */
475 	spdk_uuid_generate(&g_ctrlr1_A.hostid);
476 	TAILQ_INIT(&g_ctrlr1_A.log_head);
477 	g_ctrlr1_A.subsys = &g_subsystem;
478 	g_ctrlr1_A.num_avail_log_pages = 0;
479 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr1_A, link);
480 	spdk_uuid_copy(&g_ctrlr2_A.hostid, &g_ctrlr1_A.hostid);
481 	TAILQ_INIT(&g_ctrlr2_A.log_head);
482 	g_ctrlr2_A.subsys = &g_subsystem;
483 	g_ctrlr2_A.num_avail_log_pages = 0;
484 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr2_A, link);
485 
486 	/* Host B has 1 controller */
487 	spdk_uuid_generate(&g_ctrlr_B.hostid);
488 	TAILQ_INIT(&g_ctrlr_B.log_head);
489 	g_ctrlr_B.subsys = &g_subsystem;
490 	g_ctrlr_B.num_avail_log_pages = 0;
491 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_B, link);
492 
493 	/* Host C has 1 controller */
494 	spdk_uuid_generate(&g_ctrlr_C.hostid);
495 	TAILQ_INIT(&g_ctrlr_C.log_head);
496 	g_ctrlr_C.subsys = &g_subsystem;
497 	g_ctrlr_C.num_avail_log_pages = 0;
498 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_C, link);
499 }
500 
501 static void
502 ut_reservation_deinit(void)
503 {
504 	struct spdk_nvmf_registrant *reg, *tmp;
505 	struct spdk_nvmf_reservation_log *log, *log_tmp;
506 	struct spdk_nvmf_ctrlr *ctrlr, *ctrlr_tmp;
507 
508 	TAILQ_FOREACH_SAFE(reg, &g_ns.registrants, link, tmp) {
509 		TAILQ_REMOVE(&g_ns.registrants, reg, link);
510 		free(reg);
511 	}
512 	TAILQ_FOREACH_SAFE(log, &g_ctrlr1_A.log_head, link, log_tmp) {
513 		TAILQ_REMOVE(&g_ctrlr1_A.log_head, log, link);
514 		free(log);
515 	}
516 	g_ctrlr1_A.num_avail_log_pages = 0;
517 	TAILQ_FOREACH_SAFE(log, &g_ctrlr2_A.log_head, link, log_tmp) {
518 		TAILQ_REMOVE(&g_ctrlr2_A.log_head, log, link);
519 		free(log);
520 	}
521 	g_ctrlr2_A.num_avail_log_pages = 0;
522 	TAILQ_FOREACH_SAFE(log, &g_ctrlr_B.log_head, link, log_tmp) {
523 		TAILQ_REMOVE(&g_ctrlr_B.log_head, log, link);
524 		free(log);
525 	}
526 	g_ctrlr_B.num_avail_log_pages = 0;
527 	TAILQ_FOREACH_SAFE(log, &g_ctrlr_C.log_head, link, log_tmp) {
528 		TAILQ_REMOVE(&g_ctrlr_C.log_head, log, link);
529 		free(log);
530 	}
531 	g_ctrlr_C.num_avail_log_pages = 0;
532 
533 	TAILQ_FOREACH_SAFE(ctrlr, &g_subsystem.ctrlrs, link, ctrlr_tmp) {
534 		TAILQ_REMOVE(&g_subsystem.ctrlrs, ctrlr, link);
535 	}
536 }
537 
538 static struct spdk_nvmf_request *
539 ut_reservation_build_req(uint32_t length)
540 {
541 	struct spdk_nvmf_request *req;
542 
543 	req = calloc(1, sizeof(*req));
544 	assert(req != NULL);
545 
546 	req->data = calloc(1, length);
547 	assert(req->data != NULL);
548 	req->length = length;
549 
550 	req->cmd = (union nvmf_h2c_msg *)calloc(1, sizeof(union nvmf_h2c_msg));
551 	assert(req->cmd != NULL);
552 
553 	req->rsp = (union nvmf_c2h_msg *)calloc(1, sizeof(union nvmf_c2h_msg));
554 	assert(req->rsp != NULL);
555 
556 	return req;
557 }
558 
559 static void
560 ut_reservation_free_req(struct spdk_nvmf_request *req)
561 {
562 	free(req->cmd);
563 	free(req->rsp);
564 	free(req->data);
565 	free(req);
566 }
567 
568 static void
569 ut_reservation_build_register_request(struct spdk_nvmf_request *req,
570 				      uint8_t rrega, uint8_t iekey,
571 				      uint8_t cptpl, uint64_t crkey,
572 				      uint64_t nrkey)
573 {
574 	struct spdk_nvme_reservation_register_data key;
575 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
576 
577 	key.crkey = crkey;
578 	key.nrkey = nrkey;
579 	cmd->cdw10 = 0;
580 	cmd->cdw10_bits.resv_register.rrega = rrega;
581 	cmd->cdw10_bits.resv_register.iekey = iekey;
582 	cmd->cdw10_bits.resv_register.cptpl = cptpl;
583 	memcpy(req->data, &key, sizeof(key));
584 }
585 
586 static void
587 ut_reservation_build_acquire_request(struct spdk_nvmf_request *req,
588 				     uint8_t racqa, uint8_t iekey,
589 				     uint8_t rtype, uint64_t crkey,
590 				     uint64_t prkey)
591 {
592 	struct spdk_nvme_reservation_acquire_data key;
593 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
594 
595 	key.crkey = crkey;
596 	key.prkey = prkey;
597 	cmd->cdw10 = 0;
598 	cmd->cdw10_bits.resv_acquire.racqa = racqa;
599 	cmd->cdw10_bits.resv_acquire.iekey = iekey;
600 	cmd->cdw10_bits.resv_acquire.rtype = rtype;
601 	memcpy(req->data, &key, sizeof(key));
602 }
603 
604 static void
605 ut_reservation_build_release_request(struct spdk_nvmf_request *req,
606 				     uint8_t rrela, uint8_t iekey,
607 				     uint8_t rtype, uint64_t crkey)
608 {
609 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
610 
611 	cmd->cdw10 = 0;
612 	cmd->cdw10_bits.resv_release.rrela = rrela;
613 	cmd->cdw10_bits.resv_release.iekey = iekey;
614 	cmd->cdw10_bits.resv_release.rtype = rtype;
615 	memcpy(req->data, &crkey, sizeof(crkey));
616 }
617 
618 /*
619  * Construct four registrants for other test cases.
620  *
621  * g_ctrlr1_A register with key 0xa1.
622  * g_ctrlr2_A register with key 0xa1.
623  * g_ctrlr_B register with key 0xb1.
624  * g_ctrlr_C register with key 0xc1.
625  * */
626 static void
627 ut_reservation_build_registrants(void)
628 {
629 	struct spdk_nvmf_request *req;
630 	struct spdk_nvme_cpl *rsp;
631 	struct spdk_nvmf_registrant *reg;
632 	uint32_t gen;
633 
634 	req = ut_reservation_build_req(16);
635 	rsp = &req->rsp->nvme_cpl;
636 	SPDK_CU_ASSERT_FATAL(req != NULL);
637 	gen = g_ns.gen;
638 
639 	/* TEST CASE: g_ctrlr1_A register with a new key */
640 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
641 					      0, 0, 0, 0xa1);
642 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
643 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
644 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
645 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa1);
646 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 1);
647 
648 	/* TEST CASE: g_ctrlr2_A register with a new key, because it has same
649 	 * Host Identifier with g_ctrlr1_A, so the register key should same.
650 	 */
651 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
652 					      0, 0, 0, 0xa2);
653 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr2_A, req);
654 	/* Reservation conflict for other key than 0xa1 */
655 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT);
656 
657 	/* g_ctrlr_B register with a new key */
658 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
659 					      0, 0, 0, 0xb1);
660 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
661 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
662 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
663 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb1);
664 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 2);
665 
666 	/* g_ctrlr_C register with a new key */
667 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
668 					      0, 0, 0, 0xc1);
669 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req);
670 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
671 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
672 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xc1);
673 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 3);
674 
675 	ut_reservation_free_req(req);
676 }
677 
678 static void
679 test_reservation_register(void)
680 {
681 	struct spdk_nvmf_request *req;
682 	struct spdk_nvme_cpl *rsp;
683 	struct spdk_nvmf_registrant *reg;
684 	uint32_t gen;
685 
686 	ut_reservation_init();
687 
688 	req = ut_reservation_build_req(16);
689 	rsp = &req->rsp->nvme_cpl;
690 	SPDK_CU_ASSERT_FATAL(req != NULL);
691 
692 	ut_reservation_build_registrants();
693 
694 	/* TEST CASE: Replace g_ctrlr1_A with a new key */
695 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
696 					      0, 0, 0xa1, 0xa11);
697 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
698 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
699 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
700 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa11);
701 
702 	/* TEST CASE: Host A with g_ctrlr1_A get reservation with
703 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
704 	 */
705 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
706 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xa11, 0x0);
707 	gen = g_ns.gen;
708 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
709 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
710 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
711 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
712 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa11);
713 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
714 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen);
715 
716 	/* TEST CASE: g_ctrlr_C unregister with IEKEY enabled */
717 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
718 					      1, 0, 0, 0);
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 == NULL);
723 
724 	/* TEST CASE: g_ctrlr_B unregister with correct key */
725 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
726 					      0, 0, 0xb1, 0);
727 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
728 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
729 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
730 	SPDK_CU_ASSERT_FATAL(reg == NULL);
731 
732 	/* TEST CASE: g_ctrlr1_A unregister with correct key,
733 	 * reservation should be removed as well.
734 	 */
735 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
736 					      0, 0, 0xa11, 0);
737 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
738 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
739 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
740 	SPDK_CU_ASSERT_FATAL(reg == NULL);
741 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
742 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0);
743 	SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL);
744 
745 	ut_reservation_free_req(req);
746 	ut_reservation_deinit();
747 }
748 
749 static void
750 test_reservation_register_with_ptpl(void)
751 {
752 	struct spdk_nvmf_request *req;
753 	struct spdk_nvme_cpl *rsp;
754 	struct spdk_nvmf_registrant *reg;
755 	bool update_sgroup = false;
756 	int rc;
757 	struct spdk_nvmf_reservation_info info;
758 
759 	ut_reservation_init();
760 
761 	req = ut_reservation_build_req(16);
762 	rsp = &req->rsp->nvme_cpl;
763 	SPDK_CU_ASSERT_FATAL(req != NULL);
764 
765 	/* TEST CASE: No persistent file, register with PTPL enabled will fail */
766 	g_ns.ptpl_file = NULL;
767 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
768 					      SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
769 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
770 	SPDK_CU_ASSERT_FATAL(update_sgroup == false);
771 	SPDK_CU_ASSERT_FATAL(rsp->status.sc != SPDK_NVME_SC_SUCCESS);
772 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
773 	SPDK_CU_ASSERT_FATAL(reg == NULL);
774 
775 	/* TEST CASE: Enable PTPL */
776 	g_ns.ptpl_file = "/tmp/Ns1PR.cfg";
777 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
778 					      SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
779 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
780 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
781 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
782 	SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true);
783 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
784 	SPDK_CU_ASSERT_FATAL(reg != NULL);
785 	SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &reg->hostid));
786 	/* Load reservation information from configuration file */
787 	memset(&info, 0, sizeof(info));
788 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
789 	SPDK_CU_ASSERT_FATAL(rc == 0);
790 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
791 
792 	/* TEST CASE: Disable PTPL */
793 	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
794 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
795 					      SPDK_NVME_RESERVE_PTPL_CLEAR_POWER_ON, 0, 0xa1);
796 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
797 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
798 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
799 	SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == false);
800 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
801 	SPDK_CU_ASSERT_FATAL(rc < 0);
802 	unlink(g_ns.ptpl_file);
803 
804 	ut_reservation_free_req(req);
805 	ut_reservation_deinit();
806 }
807 
808 static void
809 test_reservation_acquire_preempt_1(void)
810 {
811 	struct spdk_nvmf_request *req;
812 	struct spdk_nvme_cpl *rsp;
813 	struct spdk_nvmf_registrant *reg;
814 	uint32_t gen;
815 
816 	ut_reservation_init();
817 
818 	req = ut_reservation_build_req(16);
819 	rsp = &req->rsp->nvme_cpl;
820 	SPDK_CU_ASSERT_FATAL(req != NULL);
821 
822 	ut_reservation_build_registrants();
823 
824 	gen = g_ns.gen;
825 	/* ACQUIRE: Host A with g_ctrlr1_A acquire reservation with
826 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE.
827 	 */
828 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
829 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0);
830 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
831 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
832 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
833 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
834 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa1);
835 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
836 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen);
837 
838 	/* TEST CASE: g_ctrlr1_A holds the reservation, g_ctrlr_B preempt g_ctrl1_A,
839 	 * g_ctrl1_A registrant is unregistred.
840 	 */
841 	gen = g_ns.gen;
842 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
843 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1, 0xa1);
844 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
845 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
846 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
847 	SPDK_CU_ASSERT_FATAL(reg == NULL);
848 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
849 	SPDK_CU_ASSERT_FATAL(reg != NULL);
850 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
851 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
852 	SPDK_CU_ASSERT_FATAL(reg != NULL);
853 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
854 	SPDK_CU_ASSERT_FATAL(g_ns.gen > gen);
855 
856 	/* TEST CASE: g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B
857 	 * with valid key and PRKEY set to 0, all registrants other the host that issued
858 	 * the command are unregistered.
859 	 */
860 	gen = g_ns.gen;
861 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
862 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0x0);
863 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req);
864 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
865 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid);
866 	SPDK_CU_ASSERT_FATAL(reg == NULL);
867 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
868 	SPDK_CU_ASSERT_FATAL(reg == NULL);
869 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
870 	SPDK_CU_ASSERT_FATAL(reg != NULL);
871 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
872 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
873 	SPDK_CU_ASSERT_FATAL(g_ns.gen > gen);
874 
875 	ut_reservation_free_req(req);
876 	ut_reservation_deinit();
877 }
878 
879 static void
880 test_reservation_acquire_release_with_ptpl(void)
881 {
882 	struct spdk_nvmf_request *req;
883 	struct spdk_nvme_cpl *rsp;
884 	struct spdk_nvmf_registrant *reg;
885 	bool update_sgroup = false;
886 	struct spdk_uuid holder_uuid;
887 	int rc;
888 	struct spdk_nvmf_reservation_info info;
889 
890 	ut_reservation_init();
891 
892 	req = ut_reservation_build_req(16);
893 	rsp = &req->rsp->nvme_cpl;
894 	SPDK_CU_ASSERT_FATAL(req != NULL);
895 
896 	/* TEST CASE: Enable PTPL */
897 	g_ns.ptpl_file = "/tmp/Ns1PR.cfg";
898 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
899 					      SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
900 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
901 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
902 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
903 	SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true);
904 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
905 	SPDK_CU_ASSERT_FATAL(reg != NULL);
906 	SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &reg->hostid));
907 	/* Load reservation information from configuration file */
908 	memset(&info, 0, sizeof(info));
909 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
910 	SPDK_CU_ASSERT_FATAL(rc == 0);
911 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
912 
913 	/* TEST CASE: Acquire the reservation */
914 	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
915 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
916 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0);
917 	update_sgroup = nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
918 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
919 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
920 	memset(&info, 0, sizeof(info));
921 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
922 	SPDK_CU_ASSERT_FATAL(rc == 0);
923 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
924 	SPDK_CU_ASSERT_FATAL(info.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
925 	SPDK_CU_ASSERT_FATAL(info.crkey == 0xa1);
926 	spdk_uuid_parse(&holder_uuid, info.holder_uuid);
927 	SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &holder_uuid));
928 
929 	/* TEST CASE: Release the reservation */
930 	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
931 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
932 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1);
933 	update_sgroup = nvmf_ns_reservation_release(&g_ns, &g_ctrlr1_A, req);
934 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
935 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
936 	memset(&info, 0, sizeof(info));
937 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
938 	SPDK_CU_ASSERT_FATAL(rc == 0);
939 	SPDK_CU_ASSERT_FATAL(info.rtype == 0);
940 	SPDK_CU_ASSERT_FATAL(info.crkey == 0);
941 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
942 	unlink(g_ns.ptpl_file);
943 
944 	ut_reservation_free_req(req);
945 	ut_reservation_deinit();
946 }
947 
948 static void
949 test_reservation_release(void)
950 {
951 	struct spdk_nvmf_request *req;
952 	struct spdk_nvme_cpl *rsp;
953 	struct spdk_nvmf_registrant *reg;
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 	ut_reservation_build_registrants();
962 
963 	/* ACQUIRE: Host A with g_ctrlr1_A get reservation with
964 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS
965 	 */
966 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
967 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xa1, 0x0);
968 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
969 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
970 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
971 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
972 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
973 
974 	/* Test Case: Host B release the reservation */
975 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
976 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1);
977 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
978 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
979 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
980 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0);
981 	SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL);
982 
983 	/* Test Case: Host C clear the registrants */
984 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0,
985 					     0, 0xc1);
986 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_C, req);
987 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
988 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
989 	SPDK_CU_ASSERT_FATAL(reg == NULL);
990 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid);
991 	SPDK_CU_ASSERT_FATAL(reg == NULL);
992 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
993 	SPDK_CU_ASSERT_FATAL(reg == NULL);
994 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
995 	SPDK_CU_ASSERT_FATAL(reg == NULL);
996 
997 	ut_reservation_free_req(req);
998 	ut_reservation_deinit();
999 }
1000 
1001 void
1002 nvmf_ctrlr_reservation_notice_log(struct spdk_nvmf_ctrlr *ctrlr,
1003 				  struct spdk_nvmf_ns *ns,
1004 				  enum spdk_nvme_reservation_notification_log_page_type type)
1005 {
1006 	ctrlr->num_avail_log_pages++;
1007 }
1008 
1009 static void
1010 test_reservation_unregister_notification(void)
1011 {
1012 	struct spdk_nvmf_request *req;
1013 	struct spdk_nvme_cpl *rsp;
1014 
1015 	ut_reservation_init();
1016 
1017 	req = ut_reservation_build_req(16);
1018 	SPDK_CU_ASSERT_FATAL(req != NULL);
1019 	rsp = &req->rsp->nvme_cpl;
1020 
1021 	ut_reservation_build_registrants();
1022 
1023 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1024 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1025 	 */
1026 	rsp->status.sc = 0xff;
1027 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1028 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1029 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1030 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1031 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1032 
1033 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B unregister the registration.
1034 	 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C only for
1035 	 * SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY or SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY
1036 	 * type.
1037 	 */
1038 	rsp->status.sc = 0xff;
1039 	g_ctrlr1_A.num_avail_log_pages = 0;
1040 	g_ctrlr2_A.num_avail_log_pages = 0;
1041 	g_ctrlr_B.num_avail_log_pages = 5;
1042 	g_ctrlr_C.num_avail_log_pages = 0;
1043 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
1044 					      0, 0, 0xb1, 0);
1045 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
1046 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1047 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1048 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1049 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1050 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1051 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1052 
1053 	ut_reservation_free_req(req);
1054 	ut_reservation_deinit();
1055 }
1056 
1057 static void
1058 test_reservation_release_notification(void)
1059 {
1060 	struct spdk_nvmf_request *req;
1061 	struct spdk_nvme_cpl *rsp;
1062 
1063 	ut_reservation_init();
1064 
1065 	req = ut_reservation_build_req(16);
1066 	SPDK_CU_ASSERT_FATAL(req != NULL);
1067 	rsp = &req->rsp->nvme_cpl;
1068 
1069 	ut_reservation_build_registrants();
1070 
1071 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1072 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1073 	 */
1074 	rsp->status.sc = 0xff;
1075 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1076 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1077 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1078 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1079 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1080 
1081 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation.
1082 	 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C.
1083 	 */
1084 	rsp->status.sc = 0xff;
1085 	g_ctrlr1_A.num_avail_log_pages = 0;
1086 	g_ctrlr2_A.num_avail_log_pages = 0;
1087 	g_ctrlr_B.num_avail_log_pages = 5;
1088 	g_ctrlr_C.num_avail_log_pages = 0;
1089 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1090 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1);
1091 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1092 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1093 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1094 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1095 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1096 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1097 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1098 
1099 	ut_reservation_free_req(req);
1100 	ut_reservation_deinit();
1101 }
1102 
1103 static void
1104 test_reservation_release_notification_write_exclusive(void)
1105 {
1106 	struct spdk_nvmf_request *req;
1107 	struct spdk_nvme_cpl *rsp;
1108 
1109 	ut_reservation_init();
1110 
1111 	req = ut_reservation_build_req(16);
1112 	SPDK_CU_ASSERT_FATAL(req != NULL);
1113 	rsp = &req->rsp->nvme_cpl;
1114 
1115 	ut_reservation_build_registrants();
1116 
1117 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1118 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
1119 	 */
1120 	rsp->status.sc = 0xff;
1121 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1122 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1, 0x0);
1123 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1124 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1125 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
1126 
1127 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation.
1128 	 * Because the reservation type is SPDK_NVME_RESERVE_WRITE_EXCLUSIVE,
1129 	 * no reservation notification occurs.
1130 	 */
1131 	rsp->status.sc = 0xff;
1132 	g_ctrlr1_A.num_avail_log_pages = 5;
1133 	g_ctrlr2_A.num_avail_log_pages = 5;
1134 	g_ctrlr_B.num_avail_log_pages = 5;
1135 	g_ctrlr_C.num_avail_log_pages = 5;
1136 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1137 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1);
1138 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1139 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1140 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1141 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr1_A.num_avail_log_pages);
1142 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr2_A.num_avail_log_pages);
1143 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1144 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages);
1145 
1146 	ut_reservation_free_req(req);
1147 	ut_reservation_deinit();
1148 }
1149 
1150 static void
1151 test_reservation_clear_notification(void)
1152 {
1153 	struct spdk_nvmf_request *req;
1154 	struct spdk_nvme_cpl *rsp;
1155 
1156 	ut_reservation_init();
1157 
1158 	req = ut_reservation_build_req(16);
1159 	SPDK_CU_ASSERT_FATAL(req != NULL);
1160 	rsp = &req->rsp->nvme_cpl;
1161 
1162 	ut_reservation_build_registrants();
1163 
1164 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1165 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1166 	 */
1167 	rsp->status.sc = 0xff;
1168 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1169 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1170 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1171 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1172 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1173 
1174 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B clear the reservation.
1175 	 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C.
1176 	 */
1177 	rsp->status.sc = 0xff;
1178 	g_ctrlr1_A.num_avail_log_pages = 0;
1179 	g_ctrlr2_A.num_avail_log_pages = 0;
1180 	g_ctrlr_B.num_avail_log_pages = 5;
1181 	g_ctrlr_C.num_avail_log_pages = 0;
1182 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0,
1183 					     0, 0xb1);
1184 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1185 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1186 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1187 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1188 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1189 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1190 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1191 
1192 	ut_reservation_free_req(req);
1193 	ut_reservation_deinit();
1194 }
1195 
1196 static void
1197 test_reservation_preempt_notification(void)
1198 {
1199 	struct spdk_nvmf_request *req;
1200 	struct spdk_nvme_cpl *rsp;
1201 
1202 	ut_reservation_init();
1203 
1204 	req = ut_reservation_build_req(16);
1205 	SPDK_CU_ASSERT_FATAL(req != NULL);
1206 	rsp = &req->rsp->nvme_cpl;
1207 
1208 	ut_reservation_build_registrants();
1209 
1210 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1211 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1212 	 */
1213 	rsp->status.sc = 0xff;
1214 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1215 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1216 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1217 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1218 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1219 
1220 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B,
1221 	 * g_ctrlr_B registrant is unregistred, and reservation is preempted.
1222 	 * Registration Preempted notification sends to g_ctrlr_B.
1223 	 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A.
1224 	 */
1225 	rsp->status.sc = 0xff;
1226 	g_ctrlr1_A.num_avail_log_pages = 0;
1227 	g_ctrlr2_A.num_avail_log_pages = 0;
1228 	g_ctrlr_B.num_avail_log_pages = 0;
1229 	g_ctrlr_C.num_avail_log_pages = 5;
1230 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
1231 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0xb1);
1232 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req);
1233 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1234 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
1235 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1236 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1237 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_B.num_avail_log_pages);
1238 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages);
1239 
1240 	ut_reservation_free_req(req);
1241 	ut_reservation_deinit();
1242 }
1243 
1244 static void
1245 test_spdk_nvmf_ns_event(void)
1246 {
1247 	struct spdk_nvmf_tgt tgt = {};
1248 	struct spdk_nvmf_subsystem subsystem = {
1249 		.max_nsid = 0,
1250 		.ns = NULL,
1251 		.tgt = &tgt
1252 	};
1253 	struct spdk_nvmf_ctrlr ctrlr = {
1254 		.subsys = &subsystem
1255 	};
1256 	struct spdk_bdev bdev1 = {};
1257 	struct spdk_nvmf_ns_opts ns_opts;
1258 	uint32_t nsid;
1259 
1260 	tgt.max_subsystems = 1024;
1261 	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
1262 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
1263 
1264 	/* Add one namespace */
1265 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
1266 	nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev1, &ns_opts, sizeof(ns_opts), NULL);
1267 	CU_ASSERT(nsid == 1);
1268 	CU_ASSERT(NULL != subsystem.ns[0]);
1269 
1270 	/* Add one controller */
1271 	TAILQ_INIT(&subsystem.ctrlrs);
1272 	TAILQ_INSERT_TAIL(&subsystem.ctrlrs, &ctrlr, link);
1273 
1274 	/* Namespace resize event */
1275 	subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
1276 	g_ns_changed_nsid = 0xFFFFFFFF;
1277 	g_ns_changed_ctrlr = NULL;
1278 	nvmf_ns_event(SPDK_BDEV_EVENT_RESIZE, &bdev1, subsystem.ns[0]);
1279 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state);
1280 
1281 	poll_threads();
1282 	CU_ASSERT(1 == g_ns_changed_nsid);
1283 	CU_ASSERT(&ctrlr == g_ns_changed_ctrlr);
1284 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state);
1285 
1286 	/* Namespace remove event */
1287 	subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
1288 	g_ns_changed_nsid = 0xFFFFFFFF;
1289 	g_ns_changed_ctrlr = NULL;
1290 	nvmf_ns_event(SPDK_BDEV_EVENT_REMOVE, &bdev1, subsystem.ns[0]);
1291 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state);
1292 	CU_ASSERT(0xFFFFFFFF == g_ns_changed_nsid);
1293 	CU_ASSERT(NULL == g_ns_changed_ctrlr);
1294 
1295 	poll_threads();
1296 	CU_ASSERT(1 == g_ns_changed_nsid);
1297 	CU_ASSERT(&ctrlr == g_ns_changed_ctrlr);
1298 	CU_ASSERT(NULL == subsystem.ns[0]);
1299 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state);
1300 
1301 	free(subsystem.ns);
1302 	free(tgt.subsystems);
1303 }
1304 
1305 
1306 int main(int argc, char **argv)
1307 {
1308 	CU_pSuite	suite = NULL;
1309 	unsigned int	num_failures;
1310 
1311 	CU_set_error_action(CUEA_ABORT);
1312 	CU_initialize_registry();
1313 
1314 	suite = CU_add_suite("nvmf", NULL, NULL);
1315 
1316 	CU_ADD_TEST(suite, nvmf_test_create_subsystem);
1317 	CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_add_ns);
1318 	CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_set_sn);
1319 	CU_ADD_TEST(suite, test_reservation_register);
1320 	CU_ADD_TEST(suite, test_reservation_register_with_ptpl);
1321 	CU_ADD_TEST(suite, test_reservation_acquire_preempt_1);
1322 	CU_ADD_TEST(suite, test_reservation_acquire_release_with_ptpl);
1323 	CU_ADD_TEST(suite, test_reservation_release);
1324 	CU_ADD_TEST(suite, test_reservation_unregister_notification);
1325 	CU_ADD_TEST(suite, test_reservation_release_notification);
1326 	CU_ADD_TEST(suite, test_reservation_release_notification_write_exclusive);
1327 	CU_ADD_TEST(suite, test_reservation_clear_notification);
1328 	CU_ADD_TEST(suite, test_reservation_preempt_notification);
1329 	CU_ADD_TEST(suite, test_spdk_nvmf_ns_event);
1330 
1331 	allocate_threads(1);
1332 	set_thread(0);
1333 
1334 	CU_basic_set_mode(CU_BRM_VERBOSE);
1335 	CU_basic_run_tests();
1336 	num_failures = CU_get_number_of_failures();
1337 	CU_cleanup_registry();
1338 
1339 	free_threads();
1340 
1341 	return num_failures;
1342 }
1343