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