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