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