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