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