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