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