xref: /spdk/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c (revision 7c06be855a536a76a47e88f1632af3f64afc3af2)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation. All rights reserved.
5  *   Copyright (c) 2019 Mellanox Technologies LTD. All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/stdinc.h"
35 
36 #include "common/lib/ut_multithread.c"
37 #include "spdk_cunit.h"
38 #include "spdk_internal/mock.h"
39 
40 #include "spdk/bdev_module.h"
41 #include "nvmf/subsystem.c"
42 
43 SPDK_LOG_REGISTER_COMPONENT(nvmf)
44 
45 DEFINE_STUB(spdk_bdev_module_claim_bdev,
46 	    int,
47 	    (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
48 	     struct spdk_bdev_module *module), 0);
49 
50 DEFINE_STUB_V(spdk_bdev_module_release_bdev,
51 	      (struct spdk_bdev *bdev));
52 
53 DEFINE_STUB(spdk_bdev_get_block_size, uint32_t,
54 	    (const struct spdk_bdev *bdev), 512);
55 
56 DEFINE_STUB(spdk_bdev_get_md_size, uint32_t,
57 	    (const struct spdk_bdev *bdev), 0);
58 
59 DEFINE_STUB(spdk_bdev_is_md_interleaved, bool,
60 	    (const struct spdk_bdev *bdev), false);
61 
62 DEFINE_STUB(spdk_bdev_io_type_supported, bool,
63 	    (struct spdk_bdev *bdev,
64 	     enum spdk_bdev_io_type io_type), false);
65 
66 DEFINE_STUB(spdk_nvmf_transport_stop_listen,
67 	    int,
68 	    (struct spdk_nvmf_transport *transport,
69 	     const struct spdk_nvme_transport_id *trid), 0);
70 
71 DEFINE_STUB_V(nvmf_update_discovery_log,
72 	      (struct spdk_nvmf_tgt *tgt, const char *hostnqn));
73 
74 DEFINE_STUB(spdk_nvmf_qpair_disconnect,
75 	    int,
76 	    (struct spdk_nvmf_qpair *qpair,
77 	     nvmf_qpair_disconnect_cb cb_fn, void *ctx), 0);
78 
79 DEFINE_STUB(nvmf_transport_find_listener,
80 	    struct spdk_nvmf_listener *,
81 	    (struct spdk_nvmf_transport *transport,
82 	     const struct spdk_nvme_transport_id *trid), NULL);
83 
84 DEFINE_STUB(spdk_nvmf_transport_get_first,
85 	    struct spdk_nvmf_transport *,
86 	    (struct spdk_nvmf_tgt *tgt), NULL);
87 
88 DEFINE_STUB(spdk_nvmf_transport_get_next,
89 	    struct spdk_nvmf_transport *,
90 	    (struct spdk_nvmf_transport *transport), NULL);
91 
92 DEFINE_STUB(spdk_nvmf_request_complete,
93 	    int,
94 	    (struct spdk_nvmf_request *req), 0);
95 
96 DEFINE_STUB(nvmf_ctrlr_async_event_ana_change_notice,
97 	    int,
98 	    (struct spdk_nvmf_ctrlr *ctrlr), 0);
99 
100 DEFINE_STUB(spdk_nvme_transport_id_trtype_str,
101 	    const char *,
102 	    (enum spdk_nvme_transport_type trtype), NULL);
103 
104 int
105 spdk_nvmf_transport_listen(struct spdk_nvmf_transport *transport,
106 			   const struct spdk_nvme_transport_id *trid, struct spdk_nvmf_listen_opts *opts)
107 {
108 	return 0;
109 }
110 
111 void
112 nvmf_transport_listener_discover(struct spdk_nvmf_transport *transport,
113 				 struct spdk_nvme_transport_id *trid,
114 				 struct spdk_nvmf_discovery_log_page_entry *entry)
115 {
116 	entry->trtype = 42;
117 }
118 
119 static struct spdk_nvmf_transport g_transport = {};
120 
121 struct spdk_nvmf_transport *
122 spdk_nvmf_transport_create(const char *transport_name,
123 			   struct spdk_nvmf_transport_opts *tprt_opts)
124 {
125 	if (strcasecmp(transport_name, spdk_nvme_transport_id_trtype_str(SPDK_NVME_TRANSPORT_RDMA))) {
126 		return &g_transport;
127 	}
128 
129 	return NULL;
130 }
131 
132 struct spdk_nvmf_subsystem *
133 spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt *tgt, const char *subnqn)
134 {
135 	return NULL;
136 }
137 
138 struct spdk_nvmf_transport *
139 spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, const char *transport_name)
140 {
141 	if (strncmp(transport_name, SPDK_NVME_TRANSPORT_NAME_RDMA, SPDK_NVMF_TRSTRING_MAX_LEN)) {
142 		return &g_transport;
143 	}
144 
145 	return NULL;
146 }
147 
148 int
149 nvmf_poll_group_update_subsystem(struct spdk_nvmf_poll_group *group,
150 				 struct spdk_nvmf_subsystem *subsystem)
151 {
152 	return 0;
153 }
154 
155 int
156 nvmf_poll_group_add_subsystem(struct spdk_nvmf_poll_group *group,
157 			      struct spdk_nvmf_subsystem *subsystem,
158 			      spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
159 {
160 	return 0;
161 }
162 
163 void
164 nvmf_poll_group_remove_subsystem(struct spdk_nvmf_poll_group *group,
165 				 struct spdk_nvmf_subsystem *subsystem,
166 				 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
167 {
168 }
169 
170 void
171 nvmf_poll_group_pause_subsystem(struct spdk_nvmf_poll_group *group,
172 				struct spdk_nvmf_subsystem *subsystem,
173 				uint32_t nsid,
174 				spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
175 {
176 }
177 
178 void
179 nvmf_poll_group_resume_subsystem(struct spdk_nvmf_poll_group *group,
180 				 struct spdk_nvmf_subsystem *subsystem,
181 				 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
182 {
183 }
184 
185 int
186 spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type *trtype, const char *str)
187 {
188 	if (trtype == NULL || str == NULL) {
189 		return -EINVAL;
190 	}
191 
192 	if (strcasecmp(str, "PCIe") == 0) {
193 		*trtype = SPDK_NVME_TRANSPORT_PCIE;
194 	} else if (strcasecmp(str, "RDMA") == 0) {
195 		*trtype = SPDK_NVME_TRANSPORT_RDMA;
196 	} else {
197 		return -ENOENT;
198 	}
199 	return 0;
200 }
201 
202 int
203 spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id *trid1,
204 			       const struct spdk_nvme_transport_id *trid2)
205 {
206 	return 0;
207 }
208 
209 int32_t
210 spdk_nvme_ctrlr_process_admin_completions(struct spdk_nvme_ctrlr *ctrlr)
211 {
212 	return -1;
213 }
214 
215 int32_t
216 spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_completions)
217 {
218 	return -1;
219 }
220 
221 int
222 spdk_nvme_detach(struct spdk_nvme_ctrlr *ctrlr)
223 {
224 	return -1;
225 }
226 
227 void
228 nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr)
229 {
230 }
231 
232 static struct spdk_nvmf_ctrlr *g_ns_changed_ctrlr = NULL;
233 static uint32_t g_ns_changed_nsid = 0;
234 void
235 nvmf_ctrlr_ns_changed(struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid)
236 {
237 	g_ns_changed_ctrlr = ctrlr;
238 	g_ns_changed_nsid = nsid;
239 }
240 
241 static struct spdk_bdev g_bdevs[] = {
242 	{ .name = "bdev1" },
243 	{ .name = "bdev2" },
244 };
245 
246 struct spdk_bdev_desc {
247 	struct spdk_bdev	*bdev;
248 };
249 
250 int
251 spdk_bdev_open_ext(const char *bdev_name, bool write, spdk_bdev_event_cb_t event_cb,
252 		   void *event_ctx, struct spdk_bdev_desc **_desc)
253 {
254 	struct spdk_bdev_desc *desc;
255 	size_t i;
256 
257 	for (i = 0; i < sizeof(g_bdevs); i++) {
258 		if (strcmp(bdev_name, g_bdevs[i].name) == 0) {
259 
260 			desc = calloc(1, sizeof(*desc));
261 			SPDK_CU_ASSERT_FATAL(desc != NULL);
262 
263 			desc->bdev = &g_bdevs[i];
264 			*_desc = desc;
265 			return 0;
266 		}
267 	}
268 
269 	return -EINVAL;
270 }
271 
272 void
273 spdk_bdev_close(struct spdk_bdev_desc *desc)
274 {
275 	free(desc);
276 }
277 
278 struct spdk_bdev *
279 spdk_bdev_desc_get_bdev(struct spdk_bdev_desc *desc)
280 {
281 	return desc->bdev;
282 }
283 
284 const char *
285 spdk_bdev_get_name(const struct spdk_bdev *bdev)
286 {
287 	return "test";
288 }
289 
290 const struct spdk_uuid *
291 spdk_bdev_get_uuid(const struct spdk_bdev *bdev)
292 {
293 	return &bdev->uuid;
294 }
295 
296 static void
297 test_spdk_nvmf_subsystem_add_ns(void)
298 {
299 	struct spdk_nvmf_tgt tgt = {};
300 	struct spdk_nvmf_subsystem subsystem = {
301 		.max_nsid = 1024,
302 		.ns = NULL,
303 		.tgt = &tgt
304 	};
305 	struct spdk_nvmf_ns_opts ns_opts;
306 	uint32_t nsid;
307 	int rc;
308 
309 	subsystem.ns = calloc(subsystem.max_nsid, sizeof(struct spdk_nvmf_subsystem_ns *));
310 	SPDK_CU_ASSERT_FATAL(subsystem.ns != NULL);
311 
312 	tgt.max_subsystems = 1024;
313 	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
314 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
315 
316 	/* Request a specific NSID */
317 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
318 	ns_opts.nsid = 5;
319 	nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL);
320 	CU_ASSERT(nsid == 5);
321 	CU_ASSERT(subsystem.max_nsid == 1024);
322 	SPDK_CU_ASSERT_FATAL(subsystem.ns[nsid - 1] != NULL);
323 	CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &g_bdevs[1]);
324 
325 	/* Request an NSID that is already in use */
326 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
327 	ns_opts.nsid = 5;
328 	nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL);
329 	CU_ASSERT(nsid == 0);
330 	CU_ASSERT(subsystem.max_nsid == 1024);
331 
332 	/* Request 0xFFFFFFFF (invalid NSID, reserved for broadcast) */
333 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
334 	ns_opts.nsid = 0xFFFFFFFF;
335 	nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL);
336 	CU_ASSERT(nsid == 0);
337 	CU_ASSERT(subsystem.max_nsid == 1024);
338 
339 	rc = spdk_nvmf_subsystem_remove_ns(&subsystem, 5);
340 	CU_ASSERT(rc == 0);
341 
342 	free(subsystem.ns);
343 	free(tgt.subsystems);
344 }
345 
346 static void
347 nvmf_test_create_subsystem(void)
348 {
349 	struct spdk_nvmf_tgt tgt = {};
350 	char nqn[256];
351 	struct spdk_nvmf_subsystem *subsystem;
352 
353 	tgt.max_subsystems = 1024;
354 	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
355 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
356 
357 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
358 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
359 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
360 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
361 	spdk_nvmf_subsystem_destroy(subsystem);
362 
363 	/* valid name with complex reverse domain */
364 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-full--rev-domain.name:subsystem1");
365 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
366 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
367 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
368 	spdk_nvmf_subsystem_destroy(subsystem);
369 
370 	/* Valid name discovery controller */
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 	spdk_nvmf_subsystem_destroy(subsystem);
376 
377 
378 	/* Invalid name, no user supplied string */
379 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:");
380 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
381 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
382 
383 	/* Valid name, only contains top-level domain name */
384 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
385 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
386 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
387 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
388 	spdk_nvmf_subsystem_destroy(subsystem);
389 
390 	/* Invalid name, domain label > 63 characters */
391 	snprintf(nqn, sizeof(nqn),
392 		 "nqn.2016-06.io.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz:sub");
393 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
394 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
395 
396 	/* Invalid name, domain label starts with digit */
397 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.3spdk:sub");
398 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
399 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
400 
401 	/* Invalid name, domain label starts with - */
402 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.-spdk:subsystem1");
403 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
404 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
405 
406 	/* Invalid name, domain label ends with - */
407 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-:subsystem1");
408 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
409 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
410 
411 	/* Invalid name, domain label with multiple consecutive periods */
412 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io..spdk:subsystem1");
413 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
414 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
415 
416 	/* Longest valid name */
417 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:");
418 	memset(nqn + strlen(nqn), 'a', 223 - strlen(nqn));
419 	nqn[223] = '\0';
420 	CU_ASSERT(strlen(nqn) == 223);
421 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
422 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
423 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
424 	spdk_nvmf_subsystem_destroy(subsystem);
425 
426 	/* Invalid name, too long */
427 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:");
428 	memset(nqn + strlen(nqn), 'a', 224 - strlen(nqn));
429 	nqn[224] = '\0';
430 	CU_ASSERT(strlen(nqn) == 224);
431 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
432 	CU_ASSERT(subsystem == NULL);
433 
434 	/* Valid name using uuid format */
435 	snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:11111111-aaaa-bbdd-FFEE-123456789abc");
436 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
437 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
438 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
439 	spdk_nvmf_subsystem_destroy(subsystem);
440 
441 	/* Invalid name user string contains an invalid utf-8 character */
442 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xFFsubsystem1");
443 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
444 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
445 
446 	/* Valid name with non-ascii but valid utf-8 characters */
447 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xe1\x8a\x88subsystem1\xca\x80");
448 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
449 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
450 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
451 	spdk_nvmf_subsystem_destroy(subsystem);
452 
453 	/* Invalid uuid (too long) */
454 	snprintf(nqn, sizeof(nqn),
455 		 "nqn.2014-08.org.nvmexpress:uuid:11111111-aaaa-bbdd-FFEE-123456789abcdef");
456 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
457 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
458 
459 	/* Invalid uuid (dashes placed incorrectly) */
460 	snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:111111-11aaaa-bbdd-FFEE-123456789abc");
461 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
462 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
463 
464 	/* Invalid uuid (invalid characters in uuid) */
465 	snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:111hg111-aaaa-bbdd-FFEE-123456789abc");
466 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
467 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
468 
469 	free(tgt.subsystems);
470 }
471 
472 static void
473 test_spdk_nvmf_subsystem_set_sn(void)
474 {
475 	struct spdk_nvmf_subsystem subsystem = {};
476 
477 	/* Basic valid serial number */
478 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd xyz") == 0);
479 	CU_ASSERT(strcmp(subsystem.sn, "abcd xyz") == 0);
480 
481 	/* Exactly 20 characters (valid) */
482 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "12345678901234567890") == 0);
483 	CU_ASSERT(strcmp(subsystem.sn, "12345678901234567890") == 0);
484 
485 	/* 21 characters (too long, invalid) */
486 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "123456789012345678901") < 0);
487 
488 	/* Non-ASCII characters (invalid) */
489 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd\txyz") < 0);
490 }
491 
492 /*
493  * Reservation Unit Test Configuration
494  *       --------             --------    --------
495  *      | Host A |           | Host B |  | Host C |
496  *       --------             --------    --------
497  *      /        \               |           |
498  *  --------   --------       -------     -------
499  * |Ctrlr1_A| |Ctrlr2_A|     |Ctrlr_B|   |Ctrlr_C|
500  *  --------   --------       -------     -------
501  *    \           \              /           /
502  *     \           \            /           /
503  *      \           \          /           /
504  *      --------------------------------------
505  *     |            NAMESPACE 1               |
506  *      --------------------------------------
507  */
508 static struct spdk_nvmf_subsystem g_subsystem;
509 static struct spdk_nvmf_ctrlr g_ctrlr1_A, g_ctrlr2_A, g_ctrlr_B, g_ctrlr_C;
510 static struct spdk_nvmf_ns g_ns;
511 static struct spdk_bdev g_bdev;
512 struct spdk_nvmf_subsystem_pg_ns_info g_ns_info;
513 
514 void
515 nvmf_ctrlr_async_event_reservation_notification(struct spdk_nvmf_ctrlr *ctrlr)
516 {
517 }
518 
519 static void
520 ut_reservation_init(void)
521 {
522 
523 	TAILQ_INIT(&g_subsystem.ctrlrs);
524 
525 	memset(&g_ns, 0, sizeof(g_ns));
526 	TAILQ_INIT(&g_ns.registrants);
527 	g_ns.subsystem = &g_subsystem;
528 	g_ns.ptpl_file = NULL;
529 	g_ns.ptpl_activated = false;
530 	spdk_uuid_generate(&g_bdev.uuid);
531 	g_ns.bdev = &g_bdev;
532 
533 	/* Host A has two controllers */
534 	spdk_uuid_generate(&g_ctrlr1_A.hostid);
535 	TAILQ_INIT(&g_ctrlr1_A.log_head);
536 	g_ctrlr1_A.subsys = &g_subsystem;
537 	g_ctrlr1_A.num_avail_log_pages = 0;
538 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr1_A, link);
539 	spdk_uuid_copy(&g_ctrlr2_A.hostid, &g_ctrlr1_A.hostid);
540 	TAILQ_INIT(&g_ctrlr2_A.log_head);
541 	g_ctrlr2_A.subsys = &g_subsystem;
542 	g_ctrlr2_A.num_avail_log_pages = 0;
543 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr2_A, link);
544 
545 	/* Host B has 1 controller */
546 	spdk_uuid_generate(&g_ctrlr_B.hostid);
547 	TAILQ_INIT(&g_ctrlr_B.log_head);
548 	g_ctrlr_B.subsys = &g_subsystem;
549 	g_ctrlr_B.num_avail_log_pages = 0;
550 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_B, link);
551 
552 	/* Host C has 1 controller */
553 	spdk_uuid_generate(&g_ctrlr_C.hostid);
554 	TAILQ_INIT(&g_ctrlr_C.log_head);
555 	g_ctrlr_C.subsys = &g_subsystem;
556 	g_ctrlr_C.num_avail_log_pages = 0;
557 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_C, link);
558 }
559 
560 static void
561 ut_reservation_deinit(void)
562 {
563 	struct spdk_nvmf_registrant *reg, *tmp;
564 	struct spdk_nvmf_reservation_log *log, *log_tmp;
565 	struct spdk_nvmf_ctrlr *ctrlr, *ctrlr_tmp;
566 
567 	TAILQ_FOREACH_SAFE(reg, &g_ns.registrants, link, tmp) {
568 		TAILQ_REMOVE(&g_ns.registrants, reg, link);
569 		free(reg);
570 	}
571 	TAILQ_FOREACH_SAFE(log, &g_ctrlr1_A.log_head, link, log_tmp) {
572 		TAILQ_REMOVE(&g_ctrlr1_A.log_head, log, link);
573 		free(log);
574 	}
575 	g_ctrlr1_A.num_avail_log_pages = 0;
576 	TAILQ_FOREACH_SAFE(log, &g_ctrlr2_A.log_head, link, log_tmp) {
577 		TAILQ_REMOVE(&g_ctrlr2_A.log_head, log, link);
578 		free(log);
579 	}
580 	g_ctrlr2_A.num_avail_log_pages = 0;
581 	TAILQ_FOREACH_SAFE(log, &g_ctrlr_B.log_head, link, log_tmp) {
582 		TAILQ_REMOVE(&g_ctrlr_B.log_head, log, link);
583 		free(log);
584 	}
585 	g_ctrlr_B.num_avail_log_pages = 0;
586 	TAILQ_FOREACH_SAFE(log, &g_ctrlr_C.log_head, link, log_tmp) {
587 		TAILQ_REMOVE(&g_ctrlr_C.log_head, log, link);
588 		free(log);
589 	}
590 	g_ctrlr_C.num_avail_log_pages = 0;
591 
592 	TAILQ_FOREACH_SAFE(ctrlr, &g_subsystem.ctrlrs, link, ctrlr_tmp) {
593 		TAILQ_REMOVE(&g_subsystem.ctrlrs, ctrlr, link);
594 	}
595 }
596 
597 static struct spdk_nvmf_request *
598 ut_reservation_build_req(uint32_t length)
599 {
600 	struct spdk_nvmf_request *req;
601 
602 	req = calloc(1, sizeof(*req));
603 	assert(req != NULL);
604 
605 	req->data = calloc(1, length);
606 	assert(req->data != NULL);
607 	req->length = length;
608 
609 	req->cmd = (union nvmf_h2c_msg *)calloc(1, sizeof(union nvmf_h2c_msg));
610 	assert(req->cmd != NULL);
611 
612 	req->rsp = (union nvmf_c2h_msg *)calloc(1, sizeof(union nvmf_c2h_msg));
613 	assert(req->rsp != NULL);
614 
615 	return req;
616 }
617 
618 static void
619 ut_reservation_free_req(struct spdk_nvmf_request *req)
620 {
621 	free(req->cmd);
622 	free(req->rsp);
623 	free(req->data);
624 	free(req);
625 }
626 
627 static void
628 ut_reservation_build_register_request(struct spdk_nvmf_request *req,
629 				      uint8_t rrega, uint8_t iekey,
630 				      uint8_t cptpl, uint64_t crkey,
631 				      uint64_t nrkey)
632 {
633 	struct spdk_nvme_reservation_register_data key;
634 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
635 
636 	key.crkey = crkey;
637 	key.nrkey = nrkey;
638 	cmd->cdw10 = 0;
639 	cmd->cdw10_bits.resv_register.rrega = rrega;
640 	cmd->cdw10_bits.resv_register.iekey = iekey;
641 	cmd->cdw10_bits.resv_register.cptpl = cptpl;
642 	memcpy(req->data, &key, sizeof(key));
643 }
644 
645 static void
646 ut_reservation_build_acquire_request(struct spdk_nvmf_request *req,
647 				     uint8_t racqa, uint8_t iekey,
648 				     uint8_t rtype, uint64_t crkey,
649 				     uint64_t prkey)
650 {
651 	struct spdk_nvme_reservation_acquire_data key;
652 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
653 
654 	key.crkey = crkey;
655 	key.prkey = prkey;
656 	cmd->cdw10 = 0;
657 	cmd->cdw10_bits.resv_acquire.racqa = racqa;
658 	cmd->cdw10_bits.resv_acquire.iekey = iekey;
659 	cmd->cdw10_bits.resv_acquire.rtype = rtype;
660 	memcpy(req->data, &key, sizeof(key));
661 }
662 
663 static void
664 ut_reservation_build_release_request(struct spdk_nvmf_request *req,
665 				     uint8_t rrela, uint8_t iekey,
666 				     uint8_t rtype, uint64_t crkey)
667 {
668 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
669 
670 	cmd->cdw10 = 0;
671 	cmd->cdw10_bits.resv_release.rrela = rrela;
672 	cmd->cdw10_bits.resv_release.iekey = iekey;
673 	cmd->cdw10_bits.resv_release.rtype = rtype;
674 	memcpy(req->data, &crkey, sizeof(crkey));
675 }
676 
677 /*
678  * Construct four registrants for other test cases.
679  *
680  * g_ctrlr1_A register with key 0xa1.
681  * g_ctrlr2_A register with key 0xa1.
682  * g_ctrlr_B register with key 0xb1.
683  * g_ctrlr_C register with key 0xc1.
684  * */
685 static void
686 ut_reservation_build_registrants(void)
687 {
688 	struct spdk_nvmf_request *req;
689 	struct spdk_nvme_cpl *rsp;
690 	struct spdk_nvmf_registrant *reg;
691 	uint32_t gen;
692 
693 	req = ut_reservation_build_req(16);
694 	rsp = &req->rsp->nvme_cpl;
695 	SPDK_CU_ASSERT_FATAL(req != NULL);
696 	gen = g_ns.gen;
697 
698 	/* TEST CASE: g_ctrlr1_A register with a new key */
699 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
700 					      0, 0, 0, 0xa1);
701 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
702 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
703 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
704 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa1);
705 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 1);
706 
707 	/* TEST CASE: g_ctrlr2_A register with a new key, because it has same
708 	 * Host Identifier with g_ctrlr1_A, so the register key should same.
709 	 */
710 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
711 					      0, 0, 0, 0xa2);
712 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr2_A, req);
713 	/* Reservation conflict for other key than 0xa1 */
714 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT);
715 
716 	/* g_ctrlr_B register with a new key */
717 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
718 					      0, 0, 0, 0xb1);
719 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
720 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
721 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
722 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb1);
723 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 2);
724 
725 	/* g_ctrlr_C register with a new key */
726 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
727 					      0, 0, 0, 0xc1);
728 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req);
729 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
730 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
731 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xc1);
732 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 3);
733 
734 	ut_reservation_free_req(req);
735 }
736 
737 static void
738 test_reservation_register(void)
739 {
740 	struct spdk_nvmf_request *req;
741 	struct spdk_nvme_cpl *rsp;
742 	struct spdk_nvmf_registrant *reg;
743 	uint32_t gen;
744 
745 	ut_reservation_init();
746 
747 	req = ut_reservation_build_req(16);
748 	rsp = &req->rsp->nvme_cpl;
749 	SPDK_CU_ASSERT_FATAL(req != NULL);
750 
751 	ut_reservation_build_registrants();
752 
753 	/* TEST CASE: Replace g_ctrlr1_A with a new key */
754 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
755 					      0, 0, 0xa1, 0xa11);
756 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
757 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
758 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
759 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa11);
760 
761 	/* TEST CASE: Host A with g_ctrlr1_A get reservation with
762 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
763 	 */
764 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
765 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xa11, 0x0);
766 	gen = g_ns.gen;
767 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
768 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
769 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
770 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
771 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa11);
772 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
773 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen);
774 
775 	/* TEST CASE: g_ctrlr_C unregister with IEKEY enabled */
776 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
777 					      1, 0, 0, 0);
778 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req);
779 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
780 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
781 	SPDK_CU_ASSERT_FATAL(reg == NULL);
782 
783 	/* TEST CASE: g_ctrlr_B unregister with correct key */
784 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
785 					      0, 0, 0xb1, 0);
786 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
787 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
788 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
789 	SPDK_CU_ASSERT_FATAL(reg == NULL);
790 
791 	/* TEST CASE: No registrant now, g_ctrlr_B replace new key with IEKEY disabled */
792 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
793 					      0, 0, 0, 0xb1);
794 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
795 	SPDK_CU_ASSERT_FATAL(rsp->status.sc != SPDK_NVME_SC_SUCCESS);
796 
797 	/* TEST CASE: No registrant now, g_ctrlr_B replace new key with IEKEY enabled */
798 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
799 					      1, 0, 0, 0xb1);
800 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
801 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
802 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
803 	SPDK_CU_ASSERT_FATAL(reg != NULL);
804 
805 	/* TEST CASE: g_ctrlr_B replace new key with IEKEY enabled and wrong crkey  */
806 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
807 					      1, 0, 0xff, 0xb2);
808 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
809 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
810 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
811 	SPDK_CU_ASSERT_FATAL(reg != NULL);
812 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb2);
813 
814 	/* TEST CASE: g_ctrlr1_A unregister with correct key,
815 	 * reservation should be removed as well.
816 	 */
817 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
818 					      0, 0, 0xa11, 0);
819 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
820 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
821 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
822 	SPDK_CU_ASSERT_FATAL(reg == NULL);
823 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
824 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0);
825 	SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL);
826 
827 	ut_reservation_free_req(req);
828 	ut_reservation_deinit();
829 }
830 
831 static void
832 test_reservation_register_with_ptpl(void)
833 {
834 	struct spdk_nvmf_request *req;
835 	struct spdk_nvme_cpl *rsp;
836 	struct spdk_nvmf_registrant *reg;
837 	bool update_sgroup = false;
838 	int rc;
839 	struct spdk_nvmf_reservation_info info;
840 
841 	ut_reservation_init();
842 
843 	req = ut_reservation_build_req(16);
844 	rsp = &req->rsp->nvme_cpl;
845 	SPDK_CU_ASSERT_FATAL(req != NULL);
846 
847 	/* TEST CASE: No persistent file, register with PTPL enabled will fail */
848 	g_ns.ptpl_file = NULL;
849 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
850 					      SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
851 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
852 	SPDK_CU_ASSERT_FATAL(update_sgroup == false);
853 	SPDK_CU_ASSERT_FATAL(rsp->status.sc != SPDK_NVME_SC_SUCCESS);
854 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
855 	SPDK_CU_ASSERT_FATAL(reg == NULL);
856 
857 	/* TEST CASE: Enable PTPL */
858 	g_ns.ptpl_file = "/tmp/Ns1PR.cfg";
859 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
860 					      SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
861 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
862 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
863 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
864 	SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true);
865 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
866 	SPDK_CU_ASSERT_FATAL(reg != NULL);
867 	SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &reg->hostid));
868 	/* Load reservation information from configuration file */
869 	memset(&info, 0, sizeof(info));
870 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
871 	SPDK_CU_ASSERT_FATAL(rc == 0);
872 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
873 
874 	/* TEST CASE: Disable PTPL */
875 	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
876 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
877 					      SPDK_NVME_RESERVE_PTPL_CLEAR_POWER_ON, 0, 0xa1);
878 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
879 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
880 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
881 	SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == false);
882 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
883 	SPDK_CU_ASSERT_FATAL(rc < 0);
884 	unlink(g_ns.ptpl_file);
885 
886 	ut_reservation_free_req(req);
887 	ut_reservation_deinit();
888 }
889 
890 static void
891 test_reservation_acquire_preempt_1(void)
892 {
893 	struct spdk_nvmf_request *req;
894 	struct spdk_nvme_cpl *rsp;
895 	struct spdk_nvmf_registrant *reg;
896 	uint32_t gen;
897 
898 	ut_reservation_init();
899 
900 	req = ut_reservation_build_req(16);
901 	rsp = &req->rsp->nvme_cpl;
902 	SPDK_CU_ASSERT_FATAL(req != NULL);
903 
904 	ut_reservation_build_registrants();
905 
906 	gen = g_ns.gen;
907 	/* ACQUIRE: Host A with g_ctrlr1_A acquire reservation with
908 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE.
909 	 */
910 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
911 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0);
912 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
913 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
914 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
915 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
916 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa1);
917 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
918 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen);
919 
920 	/* TEST CASE: g_ctrlr1_A holds the reservation, g_ctrlr_B preempt g_ctrl1_A,
921 	 * g_ctrl1_A registrant is unregistred.
922 	 */
923 	gen = g_ns.gen;
924 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
925 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1, 0xa1);
926 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
927 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
928 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
929 	SPDK_CU_ASSERT_FATAL(reg == NULL);
930 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
931 	SPDK_CU_ASSERT_FATAL(reg != NULL);
932 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
933 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
934 	SPDK_CU_ASSERT_FATAL(reg != NULL);
935 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
936 	SPDK_CU_ASSERT_FATAL(g_ns.gen > gen);
937 
938 	/* TEST CASE: g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B
939 	 * with valid key and PRKEY set to 0, all registrants other the host that issued
940 	 * the command are unregistered.
941 	 */
942 	gen = g_ns.gen;
943 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
944 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0x0);
945 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req);
946 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
947 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid);
948 	SPDK_CU_ASSERT_FATAL(reg == NULL);
949 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
950 	SPDK_CU_ASSERT_FATAL(reg == NULL);
951 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
952 	SPDK_CU_ASSERT_FATAL(reg != NULL);
953 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
954 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
955 	SPDK_CU_ASSERT_FATAL(g_ns.gen > gen);
956 
957 	ut_reservation_free_req(req);
958 	ut_reservation_deinit();
959 }
960 
961 static void
962 test_reservation_acquire_release_with_ptpl(void)
963 {
964 	struct spdk_nvmf_request *req;
965 	struct spdk_nvme_cpl *rsp;
966 	struct spdk_nvmf_registrant *reg;
967 	bool update_sgroup = false;
968 	struct spdk_uuid holder_uuid;
969 	int rc;
970 	struct spdk_nvmf_reservation_info info;
971 
972 	ut_reservation_init();
973 
974 	req = ut_reservation_build_req(16);
975 	rsp = &req->rsp->nvme_cpl;
976 	SPDK_CU_ASSERT_FATAL(req != NULL);
977 
978 	/* TEST CASE: Enable PTPL */
979 	g_ns.ptpl_file = "/tmp/Ns1PR.cfg";
980 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
981 					      SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
982 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
983 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
984 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
985 	SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true);
986 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
987 	SPDK_CU_ASSERT_FATAL(reg != NULL);
988 	SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &reg->hostid));
989 	/* Load reservation information from configuration file */
990 	memset(&info, 0, sizeof(info));
991 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
992 	SPDK_CU_ASSERT_FATAL(rc == 0);
993 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
994 
995 	/* TEST CASE: Acquire the reservation */
996 	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
997 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
998 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0);
999 	update_sgroup = nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
1000 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
1001 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1002 	memset(&info, 0, sizeof(info));
1003 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
1004 	SPDK_CU_ASSERT_FATAL(rc == 0);
1005 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
1006 	SPDK_CU_ASSERT_FATAL(info.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1007 	SPDK_CU_ASSERT_FATAL(info.crkey == 0xa1);
1008 	spdk_uuid_parse(&holder_uuid, info.holder_uuid);
1009 	SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &holder_uuid));
1010 
1011 	/* TEST CASE: Release the reservation */
1012 	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
1013 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1014 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1);
1015 	update_sgroup = nvmf_ns_reservation_release(&g_ns, &g_ctrlr1_A, req);
1016 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
1017 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1018 	memset(&info, 0, sizeof(info));
1019 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
1020 	SPDK_CU_ASSERT_FATAL(rc == 0);
1021 	SPDK_CU_ASSERT_FATAL(info.rtype == 0);
1022 	SPDK_CU_ASSERT_FATAL(info.crkey == 0);
1023 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
1024 	unlink(g_ns.ptpl_file);
1025 
1026 	ut_reservation_free_req(req);
1027 	ut_reservation_deinit();
1028 }
1029 
1030 static void
1031 test_reservation_release(void)
1032 {
1033 	struct spdk_nvmf_request *req;
1034 	struct spdk_nvme_cpl *rsp;
1035 	struct spdk_nvmf_registrant *reg;
1036 
1037 	ut_reservation_init();
1038 
1039 	req = ut_reservation_build_req(16);
1040 	rsp = &req->rsp->nvme_cpl;
1041 	SPDK_CU_ASSERT_FATAL(req != NULL);
1042 
1043 	ut_reservation_build_registrants();
1044 
1045 	/* ACQUIRE: Host A with g_ctrlr1_A get reservation with
1046 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS
1047 	 */
1048 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1049 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xa1, 0x0);
1050 	nvmf_ns_reservation_acquire(&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(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
1054 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
1055 
1056 	/* Test Case: Host B release the reservation */
1057 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1058 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1);
1059 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1060 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1061 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1062 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0);
1063 	SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL);
1064 
1065 	/* Test Case: Host C clear the registrants */
1066 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0,
1067 					     0, 0xc1);
1068 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_C, req);
1069 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1070 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
1071 	SPDK_CU_ASSERT_FATAL(reg == NULL);
1072 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid);
1073 	SPDK_CU_ASSERT_FATAL(reg == NULL);
1074 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
1075 	SPDK_CU_ASSERT_FATAL(reg == NULL);
1076 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
1077 	SPDK_CU_ASSERT_FATAL(reg == NULL);
1078 
1079 	ut_reservation_free_req(req);
1080 	ut_reservation_deinit();
1081 }
1082 
1083 void
1084 nvmf_ctrlr_reservation_notice_log(struct spdk_nvmf_ctrlr *ctrlr,
1085 				  struct spdk_nvmf_ns *ns,
1086 				  enum spdk_nvme_reservation_notification_log_page_type type)
1087 {
1088 	ctrlr->num_avail_log_pages++;
1089 }
1090 
1091 static void
1092 test_reservation_unregister_notification(void)
1093 {
1094 	struct spdk_nvmf_request *req;
1095 	struct spdk_nvme_cpl *rsp;
1096 
1097 	ut_reservation_init();
1098 
1099 	req = ut_reservation_build_req(16);
1100 	SPDK_CU_ASSERT_FATAL(req != NULL);
1101 	rsp = &req->rsp->nvme_cpl;
1102 
1103 	ut_reservation_build_registrants();
1104 
1105 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1106 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1107 	 */
1108 	rsp->status.sc = 0xff;
1109 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1110 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1111 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1112 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1113 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1114 
1115 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B unregister the registration.
1116 	 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C only for
1117 	 * SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY or SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY
1118 	 * type.
1119 	 */
1120 	rsp->status.sc = 0xff;
1121 	g_ctrlr1_A.num_avail_log_pages = 0;
1122 	g_ctrlr2_A.num_avail_log_pages = 0;
1123 	g_ctrlr_B.num_avail_log_pages = 5;
1124 	g_ctrlr_C.num_avail_log_pages = 0;
1125 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
1126 					      0, 0, 0xb1, 0);
1127 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
1128 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1129 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1130 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1131 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1132 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1133 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1134 
1135 	ut_reservation_free_req(req);
1136 	ut_reservation_deinit();
1137 }
1138 
1139 static void
1140 test_reservation_release_notification(void)
1141 {
1142 	struct spdk_nvmf_request *req;
1143 	struct spdk_nvme_cpl *rsp;
1144 
1145 	ut_reservation_init();
1146 
1147 	req = ut_reservation_build_req(16);
1148 	SPDK_CU_ASSERT_FATAL(req != NULL);
1149 	rsp = &req->rsp->nvme_cpl;
1150 
1151 	ut_reservation_build_registrants();
1152 
1153 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1154 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1155 	 */
1156 	rsp->status.sc = 0xff;
1157 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1158 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1159 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1160 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1161 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1162 
1163 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation.
1164 	 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C.
1165 	 */
1166 	rsp->status.sc = 0xff;
1167 	g_ctrlr1_A.num_avail_log_pages = 0;
1168 	g_ctrlr2_A.num_avail_log_pages = 0;
1169 	g_ctrlr_B.num_avail_log_pages = 5;
1170 	g_ctrlr_C.num_avail_log_pages = 0;
1171 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1172 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1);
1173 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1174 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1175 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1176 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1177 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1178 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1179 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1180 
1181 	ut_reservation_free_req(req);
1182 	ut_reservation_deinit();
1183 }
1184 
1185 static void
1186 test_reservation_release_notification_write_exclusive(void)
1187 {
1188 	struct spdk_nvmf_request *req;
1189 	struct spdk_nvme_cpl *rsp;
1190 
1191 	ut_reservation_init();
1192 
1193 	req = ut_reservation_build_req(16);
1194 	SPDK_CU_ASSERT_FATAL(req != NULL);
1195 	rsp = &req->rsp->nvme_cpl;
1196 
1197 	ut_reservation_build_registrants();
1198 
1199 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1200 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
1201 	 */
1202 	rsp->status.sc = 0xff;
1203 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1204 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1, 0x0);
1205 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1206 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1207 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
1208 
1209 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation.
1210 	 * Because the reservation type is SPDK_NVME_RESERVE_WRITE_EXCLUSIVE,
1211 	 * no reservation notification occurs.
1212 	 */
1213 	rsp->status.sc = 0xff;
1214 	g_ctrlr1_A.num_avail_log_pages = 5;
1215 	g_ctrlr2_A.num_avail_log_pages = 5;
1216 	g_ctrlr_B.num_avail_log_pages = 5;
1217 	g_ctrlr_C.num_avail_log_pages = 5;
1218 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1219 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1);
1220 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1221 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1222 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1223 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr1_A.num_avail_log_pages);
1224 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr2_A.num_avail_log_pages);
1225 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1226 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages);
1227 
1228 	ut_reservation_free_req(req);
1229 	ut_reservation_deinit();
1230 }
1231 
1232 static void
1233 test_reservation_clear_notification(void)
1234 {
1235 	struct spdk_nvmf_request *req;
1236 	struct spdk_nvme_cpl *rsp;
1237 
1238 	ut_reservation_init();
1239 
1240 	req = ut_reservation_build_req(16);
1241 	SPDK_CU_ASSERT_FATAL(req != NULL);
1242 	rsp = &req->rsp->nvme_cpl;
1243 
1244 	ut_reservation_build_registrants();
1245 
1246 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1247 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1248 	 */
1249 	rsp->status.sc = 0xff;
1250 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1251 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1252 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1253 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1254 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1255 
1256 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B clear the reservation.
1257 	 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C.
1258 	 */
1259 	rsp->status.sc = 0xff;
1260 	g_ctrlr1_A.num_avail_log_pages = 0;
1261 	g_ctrlr2_A.num_avail_log_pages = 0;
1262 	g_ctrlr_B.num_avail_log_pages = 5;
1263 	g_ctrlr_C.num_avail_log_pages = 0;
1264 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0,
1265 					     0, 0xb1);
1266 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1267 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1268 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1269 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1270 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1271 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1272 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1273 
1274 	ut_reservation_free_req(req);
1275 	ut_reservation_deinit();
1276 }
1277 
1278 static void
1279 test_reservation_preempt_notification(void)
1280 {
1281 	struct spdk_nvmf_request *req;
1282 	struct spdk_nvme_cpl *rsp;
1283 
1284 	ut_reservation_init();
1285 
1286 	req = ut_reservation_build_req(16);
1287 	SPDK_CU_ASSERT_FATAL(req != NULL);
1288 	rsp = &req->rsp->nvme_cpl;
1289 
1290 	ut_reservation_build_registrants();
1291 
1292 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1293 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1294 	 */
1295 	rsp->status.sc = 0xff;
1296 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1297 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1298 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1299 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1300 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1301 
1302 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B,
1303 	 * g_ctrlr_B registrant is unregistred, and reservation is preempted.
1304 	 * Registration Preempted notification sends to g_ctrlr_B.
1305 	 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A.
1306 	 */
1307 	rsp->status.sc = 0xff;
1308 	g_ctrlr1_A.num_avail_log_pages = 0;
1309 	g_ctrlr2_A.num_avail_log_pages = 0;
1310 	g_ctrlr_B.num_avail_log_pages = 0;
1311 	g_ctrlr_C.num_avail_log_pages = 5;
1312 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
1313 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0xb1);
1314 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req);
1315 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1316 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
1317 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1318 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1319 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_B.num_avail_log_pages);
1320 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages);
1321 
1322 	ut_reservation_free_req(req);
1323 	ut_reservation_deinit();
1324 }
1325 
1326 static int
1327 nvmf_tgt_create_poll_group(void *io_device, void *ctx_buf)
1328 {
1329 	return 0;
1330 }
1331 
1332 static void
1333 nvmf_tgt_destroy_poll_group(void *io_device, void *ctx_buf)
1334 {
1335 }
1336 
1337 static void
1338 test_spdk_nvmf_ns_event(void)
1339 {
1340 	struct spdk_nvmf_tgt tgt = {};
1341 	struct spdk_nvmf_subsystem subsystem = {
1342 		.max_nsid = 1024,
1343 		.ns = NULL,
1344 		.tgt = &tgt
1345 	};
1346 	struct spdk_nvmf_ctrlr ctrlr = {
1347 		.subsys = &subsystem
1348 	};
1349 	struct spdk_nvmf_ns_opts ns_opts;
1350 	uint32_t nsid;
1351 	struct spdk_bdev *bdev;
1352 
1353 	subsystem.ns = calloc(subsystem.max_nsid, sizeof(struct spdk_nvmf_subsystem_ns *));
1354 	SPDK_CU_ASSERT_FATAL(subsystem.ns != NULL);
1355 
1356 	tgt.max_subsystems = 1024;
1357 	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
1358 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
1359 
1360 	spdk_io_device_register(&tgt,
1361 				nvmf_tgt_create_poll_group,
1362 				nvmf_tgt_destroy_poll_group,
1363 				sizeof(struct spdk_nvmf_poll_group),
1364 				NULL);
1365 
1366 	/* Add one namespace */
1367 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
1368 	nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev1", &ns_opts, sizeof(ns_opts), NULL);
1369 	CU_ASSERT(nsid == 1);
1370 	CU_ASSERT(NULL != subsystem.ns[0]);
1371 	CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &g_bdevs[nsid - 1]);
1372 
1373 	bdev = subsystem.ns[nsid - 1]->bdev;
1374 
1375 	/* Add one controller */
1376 	TAILQ_INIT(&subsystem.ctrlrs);
1377 	TAILQ_INSERT_TAIL(&subsystem.ctrlrs, &ctrlr, link);
1378 
1379 	/* Namespace resize event */
1380 	subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
1381 	g_ns_changed_nsid = 0xFFFFFFFF;
1382 	g_ns_changed_ctrlr = NULL;
1383 	nvmf_ns_event(SPDK_BDEV_EVENT_RESIZE, bdev, subsystem.ns[0]);
1384 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state);
1385 
1386 	poll_threads();
1387 	CU_ASSERT(1 == g_ns_changed_nsid);
1388 	CU_ASSERT(&ctrlr == g_ns_changed_ctrlr);
1389 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state);
1390 
1391 	/* Namespace remove event */
1392 	subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
1393 	g_ns_changed_nsid = 0xFFFFFFFF;
1394 	g_ns_changed_ctrlr = NULL;
1395 	nvmf_ns_event(SPDK_BDEV_EVENT_REMOVE, bdev, subsystem.ns[0]);
1396 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state);
1397 	CU_ASSERT(0xFFFFFFFF == g_ns_changed_nsid);
1398 	CU_ASSERT(NULL == g_ns_changed_ctrlr);
1399 
1400 	poll_threads();
1401 	CU_ASSERT(1 == g_ns_changed_nsid);
1402 	CU_ASSERT(&ctrlr == g_ns_changed_ctrlr);
1403 	CU_ASSERT(NULL == subsystem.ns[0]);
1404 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state);
1405 
1406 	spdk_io_device_unregister(&tgt, NULL);
1407 
1408 	poll_threads();
1409 
1410 	free(subsystem.ns);
1411 	free(tgt.subsystems);
1412 }
1413 
1414 static void
1415 test_nvmf_ns_reservation_add_remove_registrant(void)
1416 {
1417 	struct spdk_nvmf_ns ns = {};
1418 	struct spdk_nvmf_ctrlr ctrlr = {};
1419 	struct spdk_nvmf_registrant *reg = NULL;
1420 	int rc;
1421 
1422 	TAILQ_INIT(&ns.registrants);
1423 	spdk_uuid_generate(&ctrlr.hostid);
1424 
1425 	rc = nvmf_ns_reservation_add_registrant(&ns, &ctrlr, 0xa11);
1426 	CU_ASSERT(rc == 0);
1427 	reg = TAILQ_FIRST(&ns.registrants);
1428 	SPDK_CU_ASSERT_FATAL(reg != NULL);
1429 	CU_ASSERT(ns.gen == 1);
1430 	CU_ASSERT(reg->rkey == 0xa11);
1431 	CU_ASSERT(!strncmp((uint8_t *)&reg->hostid, (uint8_t *)&ctrlr.hostid, sizeof(ctrlr.hostid)));
1432 
1433 	nvmf_ns_reservation_remove_registrant(&ns, reg);
1434 	CU_ASSERT(TAILQ_EMPTY(&ns.registrants));
1435 	CU_ASSERT(ns.gen == 2);
1436 }
1437 
1438 static void
1439 test_nvmf_subsystem_add_ctrlr(void)
1440 {
1441 	int rc;
1442 	struct spdk_nvmf_ctrlr ctrlr = {};
1443 	struct spdk_nvmf_tgt tgt = {};
1444 	char nqn[256] = "nqn.2016-06.io.spdk:subsystem1";
1445 	struct spdk_nvmf_subsystem *subsystem = NULL;
1446 
1447 	tgt.max_subsystems = 1024;
1448 	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
1449 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
1450 
1451 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
1452 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
1453 	ctrlr.subsys = subsystem;
1454 
1455 	rc = nvmf_subsystem_add_ctrlr(subsystem, &ctrlr);
1456 	CU_ASSERT(rc == 0);
1457 	CU_ASSERT(!TAILQ_EMPTY(&subsystem->ctrlrs));
1458 	CU_ASSERT(ctrlr.cntlid == 1);
1459 	CU_ASSERT(nvmf_subsystem_get_ctrlr(subsystem, 1) == &ctrlr);
1460 
1461 	nvmf_subsystem_remove_ctrlr(subsystem, &ctrlr);
1462 	CU_ASSERT(TAILQ_EMPTY(&subsystem->ctrlrs));
1463 	spdk_nvmf_subsystem_destroy(subsystem);
1464 	free(tgt.subsystems);
1465 }
1466 
1467 static void
1468 test_spdk_nvmf_subsystem_add_host(void)
1469 {
1470 	struct spdk_nvmf_tgt tgt = {};
1471 	struct spdk_nvmf_subsystem *subsystem = NULL;
1472 	int rc;
1473 	const char hostnqn[] = "nqn.2016-06.io.spdk:host1";
1474 	const char subsystemnqn[] = "nqn.2016-06.io.spdk:subsystem1";
1475 
1476 	tgt.max_subsystems = 1024;
1477 	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
1478 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
1479 
1480 	subsystem = spdk_nvmf_subsystem_create(&tgt, subsystemnqn, SPDK_NVMF_SUBTYPE_NVME, 0);
1481 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
1482 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, subsystemnqn);
1483 
1484 	rc = spdk_nvmf_subsystem_add_host(subsystem, hostnqn);
1485 	CU_ASSERT(rc == 0);
1486 	CU_ASSERT(!TAILQ_EMPTY(&subsystem->hosts));
1487 
1488 	/* Add existing nqn, this function is allowed to be called if the nqn was previously added. */
1489 	rc = spdk_nvmf_subsystem_add_host(subsystem, hostnqn);
1490 	CU_ASSERT(rc == 0);
1491 
1492 	rc = spdk_nvmf_subsystem_remove_host(subsystem, hostnqn);
1493 	CU_ASSERT(rc == 0);
1494 	CU_ASSERT(TAILQ_EMPTY(&subsystem->hosts));
1495 
1496 	/* No available nqn */
1497 	rc = spdk_nvmf_subsystem_remove_host(subsystem, hostnqn);
1498 	CU_ASSERT(rc == -ENOENT);
1499 
1500 	spdk_nvmf_subsystem_destroy(subsystem);
1501 	free(tgt.subsystems);
1502 }
1503 
1504 static void
1505 test_nvmf_ns_reservation_report(void)
1506 {
1507 	struct spdk_nvmf_ns ns = {};
1508 	struct spdk_nvmf_ctrlr ctrlr = {};
1509 	struct spdk_nvmf_request req = {};
1510 	union nvmf_h2c_msg cmd = {};
1511 	union nvmf_c2h_msg rsp = {};
1512 	struct spdk_nvme_registered_ctrlr_extended_data *ctrlr_data;
1513 	struct spdk_nvme_reservation_status_extended_data *status_data;
1514 	struct spdk_nvmf_registrant *reg;
1515 
1516 	req.data = calloc(1, sizeof(*status_data) + sizeof(*ctrlr_data) * 2);
1517 	reg = calloc(2, sizeof(struct spdk_nvmf_registrant));
1518 	SPDK_CU_ASSERT_FATAL(req.data != NULL && reg != NULL);
1519 
1520 	req.cmd = &cmd;
1521 	req.rsp = &rsp;
1522 	ns.gen = 1;
1523 	ns.rtype = SPDK_NVME_RESERVE_WRITE_EXCLUSIVE;
1524 	ns.ptpl_activated = true;
1525 	cmd.nvme_cmd.cdw11_bits.resv_report.eds = true;
1526 	cmd.nvme_cmd.cdw10 = 100;
1527 	reg[0].rkey = 0xa;
1528 	reg[1].rkey = 0xb;
1529 	spdk_uuid_generate(&reg[0].hostid);
1530 	spdk_uuid_generate(&reg[1].hostid);
1531 	TAILQ_INIT(&ns.registrants);
1532 	TAILQ_INSERT_TAIL(&ns.registrants, &reg[0], link);
1533 	TAILQ_INSERT_TAIL(&ns.registrants, &reg[1], link);
1534 
1535 	nvmf_ns_reservation_report(&ns, &ctrlr, &req);
1536 	CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC);
1537 	CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS);
1538 	/* Get ctrlr data and status data pointers */
1539 	ctrlr_data = (void *)((uint64_t)req.data + sizeof(*status_data));
1540 	status_data = (void *)req.data;
1541 	SPDK_CU_ASSERT_FATAL(status_data != NULL && ctrlr_data != NULL);
1542 	CU_ASSERT(status_data->data.gen == 1);
1543 	CU_ASSERT(status_data->data.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
1544 	CU_ASSERT(status_data->data.ptpls == true);
1545 	CU_ASSERT(status_data->data.regctl == 2);
1546 	CU_ASSERT(ctrlr_data->cntlid == 0xffff);
1547 	CU_ASSERT(ctrlr_data->rcsts.status == false);
1548 	CU_ASSERT(ctrlr_data->rkey ==  0xa);
1549 	CU_ASSERT(!spdk_uuid_compare((struct spdk_uuid *)ctrlr_data->hostid, &reg[0].hostid));
1550 	/* Check second ctrlr data */
1551 	ctrlr_data++;
1552 	CU_ASSERT(ctrlr_data->cntlid == 0xffff);
1553 	CU_ASSERT(ctrlr_data->rcsts.status == false);
1554 	CU_ASSERT(ctrlr_data->rkey ==  0xb);
1555 	CU_ASSERT(!spdk_uuid_compare((struct spdk_uuid *)ctrlr_data->hostid, &reg[1].hostid));
1556 
1557 	/* extended controller data structure */
1558 	memset(req.data, 0, sizeof(*status_data) + sizeof(*ctrlr_data) * 2);
1559 	memset(req.rsp, 0, sizeof(*req.rsp));
1560 	cmd.nvme_cmd.cdw11_bits.resv_report.eds = false;
1561 
1562 	nvmf_ns_reservation_report(&ns, &ctrlr, &req);
1563 	CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_HOSTID_INCONSISTENT_FORMAT);
1564 	CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC);
1565 
1566 	/* Transfer length invalid */
1567 	memset(req.data, 0, sizeof(*status_data) + sizeof(*ctrlr_data) * 2);
1568 	memset(req.rsp, 0, sizeof(*req.rsp));
1569 	cmd.nvme_cmd.cdw11_bits.resv_report.eds = true;
1570 	cmd.nvme_cmd.cdw10 = 0;
1571 
1572 	nvmf_ns_reservation_report(&ns, &ctrlr, &req);
1573 	CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_INTERNAL_DEVICE_ERROR);
1574 	CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC);
1575 
1576 	free(req.data);
1577 	free(reg);
1578 }
1579 
1580 
1581 int main(int argc, char **argv)
1582 {
1583 	CU_pSuite	suite = NULL;
1584 	unsigned int	num_failures;
1585 
1586 	CU_set_error_action(CUEA_ABORT);
1587 	CU_initialize_registry();
1588 
1589 	suite = CU_add_suite("nvmf", NULL, NULL);
1590 
1591 	CU_ADD_TEST(suite, nvmf_test_create_subsystem);
1592 	CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_add_ns);
1593 	CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_set_sn);
1594 	CU_ADD_TEST(suite, test_reservation_register);
1595 	CU_ADD_TEST(suite, test_reservation_register_with_ptpl);
1596 	CU_ADD_TEST(suite, test_reservation_acquire_preempt_1);
1597 	CU_ADD_TEST(suite, test_reservation_acquire_release_with_ptpl);
1598 	CU_ADD_TEST(suite, test_reservation_release);
1599 	CU_ADD_TEST(suite, test_reservation_unregister_notification);
1600 	CU_ADD_TEST(suite, test_reservation_release_notification);
1601 	CU_ADD_TEST(suite, test_reservation_release_notification_write_exclusive);
1602 	CU_ADD_TEST(suite, test_reservation_clear_notification);
1603 	CU_ADD_TEST(suite, test_reservation_preempt_notification);
1604 	CU_ADD_TEST(suite, test_spdk_nvmf_ns_event);
1605 	CU_ADD_TEST(suite, test_nvmf_ns_reservation_add_remove_registrant);
1606 	CU_ADD_TEST(suite, test_nvmf_subsystem_add_ctrlr);
1607 	CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_add_host);
1608 	CU_ADD_TEST(suite, test_nvmf_ns_reservation_report);
1609 
1610 	allocate_threads(1);
1611 	set_thread(0);
1612 
1613 	CU_basic_set_mode(CU_BRM_VERBOSE);
1614 	CU_basic_run_tests();
1615 	num_failures = CU_get_number_of_failures();
1616 	CU_cleanup_registry();
1617 
1618 	free_threads();
1619 
1620 	return num_failures;
1621 }
1622