xref: /spdk/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c (revision 9889ab2dc80e40dae92dcef361d53dcba722043d)
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 spdk_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(enum spdk_nvme_transport_type type,
86 			   struct spdk_nvmf_transport_opts *tprt_opts)
87 {
88 	if (type == 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, enum spdk_nvme_transport_type trtype)
103 {
104 	if (trtype == SPDK_NVME_TRANSPORT_RDMA) {
105 		return &g_transport;
106 	}
107 
108 	return NULL;
109 }
110 
111 int
112 spdk_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 spdk_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 spdk_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 spdk_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 spdk_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 spdk_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 spdk_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 spdk_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 	uint32_t cdw10;
575 	struct spdk_nvme_reservation_register_data key;
576 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
577 
578 	cdw10 = (((uint32_t)cptpl << 30) | ((uint32_t)iekey << 3) | rrega);
579 	key.crkey = crkey;
580 	key.nrkey = nrkey;
581 	cmd->cdw10 = cdw10;
582 	memcpy(req->data, &key, sizeof(key));
583 }
584 
585 static void
586 ut_reservation_build_acquire_request(struct spdk_nvmf_request *req,
587 				     uint8_t racqa, uint8_t iekey,
588 				     uint8_t rtype, uint64_t crkey,
589 				     uint64_t prkey)
590 {
591 	uint32_t cdw10;
592 	struct spdk_nvme_reservation_acquire_data key;
593 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
594 
595 	cdw10 = ((rtype << 8) | (iekey << 3) | racqa);
596 	key.crkey = crkey;
597 	key.prkey = prkey;
598 	cmd->cdw10 = cdw10;
599 	memcpy(req->data, &key, sizeof(key));
600 }
601 
602 static void
603 ut_reservation_build_release_request(struct spdk_nvmf_request *req,
604 				     uint8_t rrela, uint8_t iekey,
605 				     uint8_t rtype, uint64_t crkey)
606 {
607 	uint32_t cdw10;
608 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
609 
610 	cdw10 = ((rtype << 8) | (iekey << 3) | rrela);
611 	cmd->cdw10 = cdw10;
612 	memcpy(req->data, &crkey, sizeof(crkey));
613 }
614 
615 /*
616  * Construct four registrants for other test cases.
617  *
618  * g_ctrlr1_A register with key 0xa1.
619  * g_ctrlr2_A register with key 0xa1.
620  * g_ctrlr_B register with key 0xb1.
621  * g_ctrlr_C register with key 0xc1.
622  * */
623 static void
624 ut_reservation_build_registrants(void)
625 {
626 	struct spdk_nvmf_request *req;
627 	struct spdk_nvme_cpl *rsp;
628 	struct spdk_nvmf_registrant *reg;
629 	uint32_t gen;
630 
631 	req = ut_reservation_build_req(16);
632 	rsp = &req->rsp->nvme_cpl;
633 	SPDK_CU_ASSERT_FATAL(req != NULL);
634 	gen = g_ns.gen;
635 
636 	/* TEST CASE: g_ctrlr1_A register with a new key */
637 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
638 					      0, 0, 0, 0xa1);
639 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
640 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
641 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
642 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa1);
643 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 1);
644 
645 	/* TEST CASE: g_ctrlr2_A register with a new key, because it has same
646 	 * Host Identifier with g_ctrlr1_A, so the register key should same.
647 	 */
648 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
649 					      0, 0, 0, 0xa2);
650 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr2_A, req);
651 	/* Reservation conflict for other key than 0xa1 */
652 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT);
653 
654 	/* g_ctrlr_B register with a new key */
655 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
656 					      0, 0, 0, 0xb1);
657 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
658 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
659 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
660 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb1);
661 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 2);
662 
663 	/* g_ctrlr_C register with a new key */
664 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
665 					      0, 0, 0, 0xc1);
666 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req);
667 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
668 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
669 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xc1);
670 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 3);
671 
672 	ut_reservation_free_req(req);
673 }
674 
675 static void
676 test_reservation_register(void)
677 {
678 	struct spdk_nvmf_request *req;
679 	struct spdk_nvme_cpl *rsp;
680 	struct spdk_nvmf_registrant *reg;
681 	uint32_t gen;
682 
683 	ut_reservation_init();
684 
685 	req = ut_reservation_build_req(16);
686 	rsp = &req->rsp->nvme_cpl;
687 	SPDK_CU_ASSERT_FATAL(req != NULL);
688 
689 	ut_reservation_build_registrants();
690 
691 	/* TEST CASE: Replace g_ctrlr1_A with a new key */
692 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
693 					      0, 0, 0xa1, 0xa11);
694 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
695 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
696 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
697 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa11);
698 
699 	/* TEST CASE: Host A with g_ctrlr1_A get reservation with
700 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
701 	 */
702 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
703 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xa11, 0x0);
704 	gen = g_ns.gen;
705 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
706 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
707 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
708 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
709 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa11);
710 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
711 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen);
712 
713 	/* TEST CASE: g_ctrlr_C unregister with IEKEY enabled */
714 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
715 					      1, 0, 0, 0);
716 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req);
717 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
718 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
719 	SPDK_CU_ASSERT_FATAL(reg == NULL);
720 
721 	/* TEST CASE: g_ctrlr_B unregister with correct key */
722 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
723 					      0, 0, 0xb1, 0);
724 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
725 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
726 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
727 	SPDK_CU_ASSERT_FATAL(reg == NULL);
728 
729 	/* TEST CASE: g_ctrlr1_A unregister with correct key,
730 	 * reservation should be removed as well.
731 	 */
732 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
733 					      0, 0, 0xa11, 0);
734 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
735 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
736 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
737 	SPDK_CU_ASSERT_FATAL(reg == NULL);
738 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
739 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0);
740 	SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL);
741 
742 	ut_reservation_free_req(req);
743 	ut_reservation_deinit();
744 }
745 
746 static void
747 test_reservation_register_with_ptpl(void)
748 {
749 	struct spdk_nvmf_request *req;
750 	struct spdk_nvme_cpl *rsp;
751 	struct spdk_nvmf_registrant *reg;
752 	bool update_sgroup = false;
753 	int rc;
754 	struct spdk_nvmf_reservation_info info;
755 
756 	ut_reservation_init();
757 
758 	req = ut_reservation_build_req(16);
759 	rsp = &req->rsp->nvme_cpl;
760 	SPDK_CU_ASSERT_FATAL(req != NULL);
761 
762 	/* TEST CASE: No persistent file, register with PTPL enabled will fail */
763 	g_ns.ptpl_file = NULL;
764 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
765 					      SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
766 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
767 	SPDK_CU_ASSERT_FATAL(update_sgroup == false);
768 	SPDK_CU_ASSERT_FATAL(rsp->status.sc != SPDK_NVME_SC_SUCCESS);
769 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
770 	SPDK_CU_ASSERT_FATAL(reg == NULL);
771 
772 	/* TEST CASE: Enable PTPL */
773 	g_ns.ptpl_file = "/tmp/Ns1PR.cfg";
774 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
775 					      SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
776 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
777 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
778 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
779 	SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true);
780 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
781 	SPDK_CU_ASSERT_FATAL(reg != NULL);
782 	SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &reg->hostid));
783 	/* Load reservation information from configuration file */
784 	memset(&info, 0, sizeof(info));
785 	rc = spdk_nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
786 	SPDK_CU_ASSERT_FATAL(rc == 0);
787 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
788 
789 	/* TEST CASE: Disable PTPL */
790 	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
791 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
792 					      SPDK_NVME_RESERVE_PTPL_CLEAR_POWER_ON, 0, 0xa1);
793 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
794 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
795 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
796 	SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == false);
797 	rc = spdk_nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
798 	SPDK_CU_ASSERT_FATAL(rc < 0);
799 	unlink(g_ns.ptpl_file);
800 
801 	ut_reservation_free_req(req);
802 	ut_reservation_deinit();
803 }
804 
805 static void
806 test_reservation_acquire_preempt_1(void)
807 {
808 	struct spdk_nvmf_request *req;
809 	struct spdk_nvme_cpl *rsp;
810 	struct spdk_nvmf_registrant *reg;
811 	uint32_t gen;
812 
813 	ut_reservation_init();
814 
815 	req = ut_reservation_build_req(16);
816 	rsp = &req->rsp->nvme_cpl;
817 	SPDK_CU_ASSERT_FATAL(req != NULL);
818 
819 	ut_reservation_build_registrants();
820 
821 	gen = g_ns.gen;
822 	/* ACQUIRE: Host A with g_ctrlr1_A acquire reservation with
823 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE.
824 	 */
825 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
826 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0);
827 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
828 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
829 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
830 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
831 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa1);
832 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
833 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen);
834 
835 	/* TEST CASE: g_ctrlr1_A holds the reservation, g_ctrlr_B preempt g_ctrl1_A,
836 	 * g_ctrl1_A registrant is unregistred.
837 	 */
838 	gen = g_ns.gen;
839 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
840 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1, 0xa1);
841 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
842 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
843 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
844 	SPDK_CU_ASSERT_FATAL(reg == NULL);
845 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
846 	SPDK_CU_ASSERT_FATAL(reg != NULL);
847 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
848 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
849 	SPDK_CU_ASSERT_FATAL(reg != NULL);
850 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
851 	SPDK_CU_ASSERT_FATAL(g_ns.gen > gen);
852 
853 	/* TEST CASE: g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B
854 	 * with valid key and PRKEY set to 0, all registrants other the host that issued
855 	 * the command are unregistered.
856 	 */
857 	gen = g_ns.gen;
858 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
859 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0x0);
860 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req);
861 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
862 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid);
863 	SPDK_CU_ASSERT_FATAL(reg == NULL);
864 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
865 	SPDK_CU_ASSERT_FATAL(reg == NULL);
866 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
867 	SPDK_CU_ASSERT_FATAL(reg != NULL);
868 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
869 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
870 	SPDK_CU_ASSERT_FATAL(g_ns.gen > gen);
871 
872 	ut_reservation_free_req(req);
873 	ut_reservation_deinit();
874 }
875 
876 static void
877 test_reservation_acquire_release_with_ptpl(void)
878 {
879 	struct spdk_nvmf_request *req;
880 	struct spdk_nvme_cpl *rsp;
881 	struct spdk_nvmf_registrant *reg;
882 	bool update_sgroup = false;
883 	struct spdk_uuid holder_uuid;
884 	int rc;
885 	struct spdk_nvmf_reservation_info info;
886 
887 	ut_reservation_init();
888 
889 	req = ut_reservation_build_req(16);
890 	rsp = &req->rsp->nvme_cpl;
891 	SPDK_CU_ASSERT_FATAL(req != NULL);
892 
893 	/* TEST CASE: Enable PTPL */
894 	g_ns.ptpl_file = "/tmp/Ns1PR.cfg";
895 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
896 					      SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
897 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
898 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
899 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
900 	SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true);
901 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
902 	SPDK_CU_ASSERT_FATAL(reg != NULL);
903 	SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &reg->hostid));
904 	/* Load reservation information from configuration file */
905 	memset(&info, 0, sizeof(info));
906 	rc = spdk_nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
907 	SPDK_CU_ASSERT_FATAL(rc == 0);
908 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
909 
910 	/* TEST CASE: Acquire the reservation */
911 	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
912 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
913 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0);
914 	update_sgroup = nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
915 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
916 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
917 	memset(&info, 0, sizeof(info));
918 	rc = spdk_nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
919 	SPDK_CU_ASSERT_FATAL(rc == 0);
920 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
921 	SPDK_CU_ASSERT_FATAL(info.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
922 	SPDK_CU_ASSERT_FATAL(info.crkey == 0xa1);
923 	spdk_uuid_parse(&holder_uuid, info.holder_uuid);
924 	SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &holder_uuid));
925 
926 	/* TEST CASE: Release the reservation */
927 	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
928 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
929 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1);
930 	update_sgroup = nvmf_ns_reservation_release(&g_ns, &g_ctrlr1_A, req);
931 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
932 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
933 	memset(&info, 0, sizeof(info));
934 	rc = spdk_nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
935 	SPDK_CU_ASSERT_FATAL(rc == 0);
936 	SPDK_CU_ASSERT_FATAL(info.rtype == 0);
937 	SPDK_CU_ASSERT_FATAL(info.crkey == 0);
938 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
939 	unlink(g_ns.ptpl_file);
940 
941 	ut_reservation_free_req(req);
942 	ut_reservation_deinit();
943 }
944 
945 static void
946 test_reservation_release(void)
947 {
948 	struct spdk_nvmf_request *req;
949 	struct spdk_nvme_cpl *rsp;
950 	struct spdk_nvmf_registrant *reg;
951 
952 	ut_reservation_init();
953 
954 	req = ut_reservation_build_req(16);
955 	rsp = &req->rsp->nvme_cpl;
956 	SPDK_CU_ASSERT_FATAL(req != NULL);
957 
958 	ut_reservation_build_registrants();
959 
960 	/* ACQUIRE: Host A with g_ctrlr1_A get reservation with
961 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS
962 	 */
963 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
964 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xa1, 0x0);
965 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
966 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
967 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
968 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
969 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
970 
971 	/* Test Case: Host B release the reservation */
972 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
973 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1);
974 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
975 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
976 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
977 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0);
978 	SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL);
979 
980 	/* Test Case: Host C clear the registrants */
981 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0,
982 					     0, 0xc1);
983 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_C, req);
984 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
985 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
986 	SPDK_CU_ASSERT_FATAL(reg == NULL);
987 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid);
988 	SPDK_CU_ASSERT_FATAL(reg == NULL);
989 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
990 	SPDK_CU_ASSERT_FATAL(reg == NULL);
991 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
992 	SPDK_CU_ASSERT_FATAL(reg == NULL);
993 
994 	ut_reservation_free_req(req);
995 	ut_reservation_deinit();
996 }
997 
998 void
999 spdk_nvmf_ctrlr_reservation_notice_log(struct spdk_nvmf_ctrlr *ctrlr,
1000 				       struct spdk_nvmf_ns *ns,
1001 				       enum spdk_nvme_reservation_notification_log_page_type type)
1002 {
1003 	ctrlr->num_avail_log_pages++;
1004 }
1005 
1006 static void
1007 test_reservation_unregister_notification(void)
1008 {
1009 	struct spdk_nvmf_request *req;
1010 	struct spdk_nvme_cpl *rsp;
1011 
1012 	ut_reservation_init();
1013 
1014 	req = ut_reservation_build_req(16);
1015 	SPDK_CU_ASSERT_FATAL(req != NULL);
1016 	rsp = &req->rsp->nvme_cpl;
1017 
1018 	ut_reservation_build_registrants();
1019 
1020 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1021 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1022 	 */
1023 	rsp->status.sc = 0xff;
1024 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1025 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1026 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1027 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1028 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1029 
1030 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B unregister the registration.
1031 	 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C only for
1032 	 * SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY or SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY
1033 	 * type.
1034 	 */
1035 	rsp->status.sc = 0xff;
1036 	g_ctrlr1_A.num_avail_log_pages = 0;
1037 	g_ctrlr2_A.num_avail_log_pages = 0;
1038 	g_ctrlr_B.num_avail_log_pages = 5;
1039 	g_ctrlr_C.num_avail_log_pages = 0;
1040 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
1041 					      0, 0, 0xb1, 0);
1042 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
1043 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1044 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1045 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1046 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1047 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1048 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1049 
1050 	ut_reservation_free_req(req);
1051 	ut_reservation_deinit();
1052 }
1053 
1054 static void
1055 test_reservation_release_notification(void)
1056 {
1057 	struct spdk_nvmf_request *req;
1058 	struct spdk_nvme_cpl *rsp;
1059 
1060 	ut_reservation_init();
1061 
1062 	req = ut_reservation_build_req(16);
1063 	SPDK_CU_ASSERT_FATAL(req != NULL);
1064 	rsp = &req->rsp->nvme_cpl;
1065 
1066 	ut_reservation_build_registrants();
1067 
1068 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1069 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1070 	 */
1071 	rsp->status.sc = 0xff;
1072 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1073 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1074 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1075 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1076 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1077 
1078 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation.
1079 	 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C.
1080 	 */
1081 	rsp->status.sc = 0xff;
1082 	g_ctrlr1_A.num_avail_log_pages = 0;
1083 	g_ctrlr2_A.num_avail_log_pages = 0;
1084 	g_ctrlr_B.num_avail_log_pages = 5;
1085 	g_ctrlr_C.num_avail_log_pages = 0;
1086 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1087 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1);
1088 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1089 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1090 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1091 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1092 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1093 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1094 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1095 
1096 	ut_reservation_free_req(req);
1097 	ut_reservation_deinit();
1098 }
1099 
1100 static void
1101 test_reservation_release_notification_write_exclusive(void)
1102 {
1103 	struct spdk_nvmf_request *req;
1104 	struct spdk_nvme_cpl *rsp;
1105 
1106 	ut_reservation_init();
1107 
1108 	req = ut_reservation_build_req(16);
1109 	SPDK_CU_ASSERT_FATAL(req != NULL);
1110 	rsp = &req->rsp->nvme_cpl;
1111 
1112 	ut_reservation_build_registrants();
1113 
1114 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1115 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
1116 	 */
1117 	rsp->status.sc = 0xff;
1118 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1119 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1, 0x0);
1120 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1121 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1122 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
1123 
1124 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation.
1125 	 * Because the reservation type is SPDK_NVME_RESERVE_WRITE_EXCLUSIVE,
1126 	 * no reservation notification occurs.
1127 	 */
1128 	rsp->status.sc = 0xff;
1129 	g_ctrlr1_A.num_avail_log_pages = 5;
1130 	g_ctrlr2_A.num_avail_log_pages = 5;
1131 	g_ctrlr_B.num_avail_log_pages = 5;
1132 	g_ctrlr_C.num_avail_log_pages = 5;
1133 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1134 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1);
1135 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1136 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1137 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1138 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr1_A.num_avail_log_pages);
1139 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr2_A.num_avail_log_pages);
1140 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1141 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages);
1142 
1143 	ut_reservation_free_req(req);
1144 	ut_reservation_deinit();
1145 }
1146 
1147 static void
1148 test_reservation_clear_notification(void)
1149 {
1150 	struct spdk_nvmf_request *req;
1151 	struct spdk_nvme_cpl *rsp;
1152 
1153 	ut_reservation_init();
1154 
1155 	req = ut_reservation_build_req(16);
1156 	SPDK_CU_ASSERT_FATAL(req != NULL);
1157 	rsp = &req->rsp->nvme_cpl;
1158 
1159 	ut_reservation_build_registrants();
1160 
1161 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1162 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1163 	 */
1164 	rsp->status.sc = 0xff;
1165 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1166 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1167 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1168 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1169 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1170 
1171 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B clear the reservation.
1172 	 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C.
1173 	 */
1174 	rsp->status.sc = 0xff;
1175 	g_ctrlr1_A.num_avail_log_pages = 0;
1176 	g_ctrlr2_A.num_avail_log_pages = 0;
1177 	g_ctrlr_B.num_avail_log_pages = 5;
1178 	g_ctrlr_C.num_avail_log_pages = 0;
1179 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0,
1180 					     0, 0xb1);
1181 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1182 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1183 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1184 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1185 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1186 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1187 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1188 
1189 	ut_reservation_free_req(req);
1190 	ut_reservation_deinit();
1191 }
1192 
1193 static void
1194 test_reservation_preempt_notification(void)
1195 {
1196 	struct spdk_nvmf_request *req;
1197 	struct spdk_nvme_cpl *rsp;
1198 
1199 	ut_reservation_init();
1200 
1201 	req = ut_reservation_build_req(16);
1202 	SPDK_CU_ASSERT_FATAL(req != NULL);
1203 	rsp = &req->rsp->nvme_cpl;
1204 
1205 	ut_reservation_build_registrants();
1206 
1207 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1208 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1209 	 */
1210 	rsp->status.sc = 0xff;
1211 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1212 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1213 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1214 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1215 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1216 
1217 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B,
1218 	 * g_ctrlr_B registrant is unregistred, and reservation is preempted.
1219 	 * Registration Preempted notification sends to g_ctrlr_B.
1220 	 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A.
1221 	 */
1222 	rsp->status.sc = 0xff;
1223 	g_ctrlr1_A.num_avail_log_pages = 0;
1224 	g_ctrlr2_A.num_avail_log_pages = 0;
1225 	g_ctrlr_B.num_avail_log_pages = 0;
1226 	g_ctrlr_C.num_avail_log_pages = 5;
1227 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
1228 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0xb1);
1229 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req);
1230 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1231 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
1232 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1233 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1234 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_B.num_avail_log_pages);
1235 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages);
1236 
1237 	ut_reservation_free_req(req);
1238 	ut_reservation_deinit();
1239 }
1240 
1241 static void
1242 test_spdk_nvmf_ns_event(void)
1243 {
1244 	struct spdk_nvmf_tgt tgt = {};
1245 	struct spdk_nvmf_subsystem subsystem = {
1246 		.max_nsid = 0,
1247 		.ns = NULL,
1248 		.tgt = &tgt
1249 	};
1250 	struct spdk_nvmf_ctrlr ctrlr = {
1251 		.subsys = &subsystem
1252 	};
1253 	struct spdk_bdev bdev1 = {};
1254 	struct spdk_nvmf_ns_opts ns_opts;
1255 	uint32_t nsid;
1256 
1257 	tgt.max_subsystems = 1024;
1258 	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
1259 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
1260 
1261 	/* Add one namespace */
1262 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
1263 	nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev1, &ns_opts, sizeof(ns_opts), NULL);
1264 	CU_ASSERT(nsid == 1);
1265 	CU_ASSERT(NULL != subsystem.ns[0]);
1266 
1267 	/* Add one controller */
1268 	TAILQ_INIT(&subsystem.ctrlrs);
1269 	TAILQ_INSERT_TAIL(&subsystem.ctrlrs, &ctrlr, link);
1270 
1271 	/* Namespace resize event */
1272 	subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
1273 	g_ns_changed_nsid = 0xFFFFFFFF;
1274 	g_ns_changed_ctrlr = NULL;
1275 	spdk_nvmf_ns_event(SPDK_BDEV_EVENT_RESIZE, &bdev1, subsystem.ns[0]);
1276 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state);
1277 
1278 	poll_threads();
1279 	CU_ASSERT(1 == g_ns_changed_nsid);
1280 	CU_ASSERT(&ctrlr == g_ns_changed_ctrlr);
1281 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state);
1282 
1283 	/* Namespace remove event */
1284 	subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
1285 	g_ns_changed_nsid = 0xFFFFFFFF;
1286 	g_ns_changed_ctrlr = NULL;
1287 	spdk_nvmf_ns_event(SPDK_BDEV_EVENT_REMOVE, &bdev1, subsystem.ns[0]);
1288 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state);
1289 	CU_ASSERT(0xFFFFFFFF == g_ns_changed_nsid);
1290 	CU_ASSERT(NULL == g_ns_changed_ctrlr);
1291 
1292 	poll_threads();
1293 	CU_ASSERT(1 == g_ns_changed_nsid);
1294 	CU_ASSERT(&ctrlr == g_ns_changed_ctrlr);
1295 	CU_ASSERT(NULL == subsystem.ns[0]);
1296 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state);
1297 
1298 	free(subsystem.ns);
1299 	free(tgt.subsystems);
1300 }
1301 
1302 
1303 int main(int argc, char **argv)
1304 {
1305 	CU_pSuite	suite = NULL;
1306 	unsigned int	num_failures;
1307 
1308 	if (CU_initialize_registry() != CUE_SUCCESS) {
1309 		return CU_get_error();
1310 	}
1311 
1312 	suite = CU_add_suite("nvmf", NULL, NULL);
1313 	if (suite == NULL) {
1314 		CU_cleanup_registry();
1315 		return CU_get_error();
1316 	}
1317 
1318 	if (
1319 		CU_add_test(suite, "create_subsystem", nvmf_test_create_subsystem) == NULL ||
1320 		CU_add_test(suite, "nvmf_subsystem_add_ns", test_spdk_nvmf_subsystem_add_ns) == NULL ||
1321 		CU_add_test(suite, "nvmf_subsystem_set_sn", test_spdk_nvmf_subsystem_set_sn) == NULL ||
1322 		CU_add_test(suite, "reservation_register", test_reservation_register) == NULL ||
1323 		CU_add_test(suite, "reservation_register_with_ptpl", test_reservation_register_with_ptpl) == NULL ||
1324 		CU_add_test(suite, "reservation_acquire_preempt_1", test_reservation_acquire_preempt_1) == NULL ||
1325 		CU_add_test(suite, "reservation_acquire_release_with_ptpl",
1326 			    test_reservation_acquire_release_with_ptpl) == NULL ||
1327 		CU_add_test(suite, "reservation_release", test_reservation_release) == NULL ||
1328 		CU_add_test(suite, "reservation_unregister_notification",
1329 			    test_reservation_unregister_notification) == NULL ||
1330 		CU_add_test(suite, "reservation_release_notification",
1331 			    test_reservation_release_notification) == NULL ||
1332 		CU_add_test(suite, "reservation_release_notification_write_exclusive",
1333 			    test_reservation_release_notification_write_exclusive) == NULL ||
1334 		CU_add_test(suite, "reservation_clear_notification", test_reservation_clear_notification) == NULL ||
1335 		CU_add_test(suite, "reservation_preempt_notification",
1336 			    test_reservation_preempt_notification) == NULL ||
1337 		CU_add_test(suite, "spdk_nvmf_ns_event", test_spdk_nvmf_ns_event) == NULL
1338 	) {
1339 		CU_cleanup_registry();
1340 		return CU_get_error();
1341 	}
1342 
1343 	allocate_threads(1);
1344 	set_thread(0);
1345 
1346 	CU_basic_set_mode(CU_BRM_VERBOSE);
1347 	CU_basic_run_tests();
1348 	num_failures = CU_get_number_of_failures();
1349 	CU_cleanup_registry();
1350 
1351 	free_threads();
1352 
1353 	return num_failures;
1354 }
1355