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