xref: /spdk/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c (revision 6e5d6032a09ca918509e7c6f28d6d2e20b8dc832)
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 	subsystem.ana_group = calloc(subsystem.max_nsid, sizeof(uint32_t));
312 	SPDK_CU_ASSERT_FATAL(subsystem.ana_group != NULL);
313 
314 	tgt.max_subsystems = 1024;
315 	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
316 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
317 
318 	/* Request a specific NSID */
319 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
320 	ns_opts.nsid = 5;
321 	nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL);
322 	CU_ASSERT(nsid == 5);
323 	CU_ASSERT(subsystem.max_nsid == 1024);
324 	SPDK_CU_ASSERT_FATAL(subsystem.ns[nsid - 1] != NULL);
325 	CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &g_bdevs[1]);
326 
327 	/* Request an NSID that is already in use */
328 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
329 	ns_opts.nsid = 5;
330 	nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL);
331 	CU_ASSERT(nsid == 0);
332 	CU_ASSERT(subsystem.max_nsid == 1024);
333 
334 	/* Request 0xFFFFFFFF (invalid NSID, reserved for broadcast) */
335 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
336 	ns_opts.nsid = 0xFFFFFFFF;
337 	nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL);
338 	CU_ASSERT(nsid == 0);
339 	CU_ASSERT(subsystem.max_nsid == 1024);
340 
341 	rc = spdk_nvmf_subsystem_remove_ns(&subsystem, 5);
342 	CU_ASSERT(rc == 0);
343 
344 	free(subsystem.ns);
345 	free(subsystem.ana_group);
346 	free(tgt.subsystems);
347 }
348 
349 static void
350 nvmf_test_create_subsystem(void)
351 {
352 	struct spdk_nvmf_tgt tgt = {};
353 	char nqn[256];
354 	struct spdk_nvmf_subsystem *subsystem;
355 
356 	tgt.max_subsystems = 1024;
357 	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
358 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
359 
360 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
361 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
362 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
363 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
364 	spdk_nvmf_subsystem_destroy(subsystem);
365 
366 	/* valid name with complex reverse domain */
367 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-full--rev-domain.name:subsystem1");
368 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
369 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
370 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
371 	spdk_nvmf_subsystem_destroy(subsystem);
372 
373 	/* Valid name discovery controller */
374 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
375 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
376 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
377 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
378 	spdk_nvmf_subsystem_destroy(subsystem);
379 
380 
381 	/* Invalid name, no user supplied string */
382 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:");
383 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
384 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
385 
386 	/* Valid name, only contains top-level domain name */
387 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
388 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
389 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
390 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
391 	spdk_nvmf_subsystem_destroy(subsystem);
392 
393 	/* Invalid name, domain label > 63 characters */
394 	snprintf(nqn, sizeof(nqn),
395 		 "nqn.2016-06.io.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz:sub");
396 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
397 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
398 
399 	/* Invalid name, domain label starts with digit */
400 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.3spdk:sub");
401 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
402 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
403 
404 	/* Invalid name, domain label starts with - */
405 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.-spdk:subsystem1");
406 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
407 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
408 
409 	/* Invalid name, domain label ends with - */
410 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-:subsystem1");
411 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
412 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
413 
414 	/* Invalid name, domain label with multiple consecutive periods */
415 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io..spdk:subsystem1");
416 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
417 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
418 
419 	/* Longest valid name */
420 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:");
421 	memset(nqn + strlen(nqn), 'a', 223 - strlen(nqn));
422 	nqn[223] = '\0';
423 	CU_ASSERT(strlen(nqn) == 223);
424 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
425 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
426 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
427 	spdk_nvmf_subsystem_destroy(subsystem);
428 
429 	/* Invalid name, too long */
430 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:");
431 	memset(nqn + strlen(nqn), 'a', 224 - strlen(nqn));
432 	nqn[224] = '\0';
433 	CU_ASSERT(strlen(nqn) == 224);
434 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
435 	CU_ASSERT(subsystem == NULL);
436 
437 	/* Valid name using uuid format */
438 	snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:11111111-aaaa-bbdd-FFEE-123456789abc");
439 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
440 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
441 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
442 	spdk_nvmf_subsystem_destroy(subsystem);
443 
444 	/* Invalid name user string contains an invalid utf-8 character */
445 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xFFsubsystem1");
446 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
447 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
448 
449 	/* Valid name with non-ascii but valid utf-8 characters */
450 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xe1\x8a\x88subsystem1\xca\x80");
451 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
452 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
453 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
454 	spdk_nvmf_subsystem_destroy(subsystem);
455 
456 	/* Invalid uuid (too long) */
457 	snprintf(nqn, sizeof(nqn),
458 		 "nqn.2014-08.org.nvmexpress:uuid:11111111-aaaa-bbdd-FFEE-123456789abcdef");
459 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
460 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
461 
462 	/* Invalid uuid (dashes placed incorrectly) */
463 	snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:111111-11aaaa-bbdd-FFEE-123456789abc");
464 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
465 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
466 
467 	/* Invalid uuid (invalid characters in uuid) */
468 	snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:111hg111-aaaa-bbdd-FFEE-123456789abc");
469 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
470 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
471 
472 	free(tgt.subsystems);
473 }
474 
475 static void
476 test_spdk_nvmf_subsystem_set_sn(void)
477 {
478 	struct spdk_nvmf_subsystem subsystem = {};
479 
480 	/* Basic valid serial number */
481 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd xyz") == 0);
482 	CU_ASSERT(strcmp(subsystem.sn, "abcd xyz") == 0);
483 
484 	/* Exactly 20 characters (valid) */
485 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "12345678901234567890") == 0);
486 	CU_ASSERT(strcmp(subsystem.sn, "12345678901234567890") == 0);
487 
488 	/* 21 characters (too long, invalid) */
489 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "123456789012345678901") < 0);
490 
491 	/* Non-ASCII characters (invalid) */
492 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd\txyz") < 0);
493 }
494 
495 /*
496  * Reservation Unit Test Configuration
497  *       --------             --------    --------
498  *      | Host A |           | Host B |  | Host C |
499  *       --------             --------    --------
500  *      /        \               |           |
501  *  --------   --------       -------     -------
502  * |Ctrlr1_A| |Ctrlr2_A|     |Ctrlr_B|   |Ctrlr_C|
503  *  --------   --------       -------     -------
504  *    \           \              /           /
505  *     \           \            /           /
506  *      \           \          /           /
507  *      --------------------------------------
508  *     |            NAMESPACE 1               |
509  *      --------------------------------------
510  */
511 static struct spdk_nvmf_subsystem g_subsystem;
512 static struct spdk_nvmf_ctrlr g_ctrlr1_A, g_ctrlr2_A, g_ctrlr_B, g_ctrlr_C;
513 static struct spdk_nvmf_ns g_ns;
514 static struct spdk_bdev g_bdev;
515 struct spdk_nvmf_subsystem_pg_ns_info g_ns_info;
516 
517 void
518 nvmf_ctrlr_async_event_reservation_notification(struct spdk_nvmf_ctrlr *ctrlr)
519 {
520 }
521 
522 static void
523 ut_reservation_init(void)
524 {
525 
526 	TAILQ_INIT(&g_subsystem.ctrlrs);
527 
528 	memset(&g_ns, 0, sizeof(g_ns));
529 	TAILQ_INIT(&g_ns.registrants);
530 	g_ns.subsystem = &g_subsystem;
531 	g_ns.ptpl_file = NULL;
532 	g_ns.ptpl_activated = false;
533 	spdk_uuid_generate(&g_bdev.uuid);
534 	g_ns.bdev = &g_bdev;
535 
536 	/* Host A has two controllers */
537 	spdk_uuid_generate(&g_ctrlr1_A.hostid);
538 	TAILQ_INIT(&g_ctrlr1_A.log_head);
539 	g_ctrlr1_A.subsys = &g_subsystem;
540 	g_ctrlr1_A.num_avail_log_pages = 0;
541 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr1_A, link);
542 	spdk_uuid_copy(&g_ctrlr2_A.hostid, &g_ctrlr1_A.hostid);
543 	TAILQ_INIT(&g_ctrlr2_A.log_head);
544 	g_ctrlr2_A.subsys = &g_subsystem;
545 	g_ctrlr2_A.num_avail_log_pages = 0;
546 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr2_A, link);
547 
548 	/* Host B has 1 controller */
549 	spdk_uuid_generate(&g_ctrlr_B.hostid);
550 	TAILQ_INIT(&g_ctrlr_B.log_head);
551 	g_ctrlr_B.subsys = &g_subsystem;
552 	g_ctrlr_B.num_avail_log_pages = 0;
553 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_B, link);
554 
555 	/* Host C has 1 controller */
556 	spdk_uuid_generate(&g_ctrlr_C.hostid);
557 	TAILQ_INIT(&g_ctrlr_C.log_head);
558 	g_ctrlr_C.subsys = &g_subsystem;
559 	g_ctrlr_C.num_avail_log_pages = 0;
560 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_C, link);
561 }
562 
563 static void
564 ut_reservation_deinit(void)
565 {
566 	struct spdk_nvmf_registrant *reg, *tmp;
567 	struct spdk_nvmf_reservation_log *log, *log_tmp;
568 	struct spdk_nvmf_ctrlr *ctrlr, *ctrlr_tmp;
569 
570 	TAILQ_FOREACH_SAFE(reg, &g_ns.registrants, link, tmp) {
571 		TAILQ_REMOVE(&g_ns.registrants, reg, link);
572 		free(reg);
573 	}
574 	TAILQ_FOREACH_SAFE(log, &g_ctrlr1_A.log_head, link, log_tmp) {
575 		TAILQ_REMOVE(&g_ctrlr1_A.log_head, log, link);
576 		free(log);
577 	}
578 	g_ctrlr1_A.num_avail_log_pages = 0;
579 	TAILQ_FOREACH_SAFE(log, &g_ctrlr2_A.log_head, link, log_tmp) {
580 		TAILQ_REMOVE(&g_ctrlr2_A.log_head, log, link);
581 		free(log);
582 	}
583 	g_ctrlr2_A.num_avail_log_pages = 0;
584 	TAILQ_FOREACH_SAFE(log, &g_ctrlr_B.log_head, link, log_tmp) {
585 		TAILQ_REMOVE(&g_ctrlr_B.log_head, log, link);
586 		free(log);
587 	}
588 	g_ctrlr_B.num_avail_log_pages = 0;
589 	TAILQ_FOREACH_SAFE(log, &g_ctrlr_C.log_head, link, log_tmp) {
590 		TAILQ_REMOVE(&g_ctrlr_C.log_head, log, link);
591 		free(log);
592 	}
593 	g_ctrlr_C.num_avail_log_pages = 0;
594 
595 	TAILQ_FOREACH_SAFE(ctrlr, &g_subsystem.ctrlrs, link, ctrlr_tmp) {
596 		TAILQ_REMOVE(&g_subsystem.ctrlrs, ctrlr, link);
597 	}
598 }
599 
600 static struct spdk_nvmf_request *
601 ut_reservation_build_req(uint32_t length)
602 {
603 	struct spdk_nvmf_request *req;
604 
605 	req = calloc(1, sizeof(*req));
606 	assert(req != NULL);
607 
608 	req->data = calloc(1, length);
609 	assert(req->data != NULL);
610 	req->length = length;
611 
612 	req->cmd = (union nvmf_h2c_msg *)calloc(1, sizeof(union nvmf_h2c_msg));
613 	assert(req->cmd != NULL);
614 
615 	req->rsp = (union nvmf_c2h_msg *)calloc(1, sizeof(union nvmf_c2h_msg));
616 	assert(req->rsp != NULL);
617 
618 	return req;
619 }
620 
621 static void
622 ut_reservation_free_req(struct spdk_nvmf_request *req)
623 {
624 	free(req->cmd);
625 	free(req->rsp);
626 	free(req->data);
627 	free(req);
628 }
629 
630 static void
631 ut_reservation_build_register_request(struct spdk_nvmf_request *req,
632 				      uint8_t rrega, uint8_t iekey,
633 				      uint8_t cptpl, uint64_t crkey,
634 				      uint64_t nrkey)
635 {
636 	struct spdk_nvme_reservation_register_data key;
637 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
638 
639 	key.crkey = crkey;
640 	key.nrkey = nrkey;
641 	cmd->cdw10 = 0;
642 	cmd->cdw10_bits.resv_register.rrega = rrega;
643 	cmd->cdw10_bits.resv_register.iekey = iekey;
644 	cmd->cdw10_bits.resv_register.cptpl = cptpl;
645 	memcpy(req->data, &key, sizeof(key));
646 }
647 
648 static void
649 ut_reservation_build_acquire_request(struct spdk_nvmf_request *req,
650 				     uint8_t racqa, uint8_t iekey,
651 				     uint8_t rtype, uint64_t crkey,
652 				     uint64_t prkey)
653 {
654 	struct spdk_nvme_reservation_acquire_data key;
655 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
656 
657 	key.crkey = crkey;
658 	key.prkey = prkey;
659 	cmd->cdw10 = 0;
660 	cmd->cdw10_bits.resv_acquire.racqa = racqa;
661 	cmd->cdw10_bits.resv_acquire.iekey = iekey;
662 	cmd->cdw10_bits.resv_acquire.rtype = rtype;
663 	memcpy(req->data, &key, sizeof(key));
664 }
665 
666 static void
667 ut_reservation_build_release_request(struct spdk_nvmf_request *req,
668 				     uint8_t rrela, uint8_t iekey,
669 				     uint8_t rtype, uint64_t crkey)
670 {
671 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
672 
673 	cmd->cdw10 = 0;
674 	cmd->cdw10_bits.resv_release.rrela = rrela;
675 	cmd->cdw10_bits.resv_release.iekey = iekey;
676 	cmd->cdw10_bits.resv_release.rtype = rtype;
677 	memcpy(req->data, &crkey, sizeof(crkey));
678 }
679 
680 /*
681  * Construct four registrants for other test cases.
682  *
683  * g_ctrlr1_A register with key 0xa1.
684  * g_ctrlr2_A register with key 0xa1.
685  * g_ctrlr_B register with key 0xb1.
686  * g_ctrlr_C register with key 0xc1.
687  * */
688 static void
689 ut_reservation_build_registrants(void)
690 {
691 	struct spdk_nvmf_request *req;
692 	struct spdk_nvme_cpl *rsp;
693 	struct spdk_nvmf_registrant *reg;
694 	uint32_t gen;
695 
696 	req = ut_reservation_build_req(16);
697 	rsp = &req->rsp->nvme_cpl;
698 	SPDK_CU_ASSERT_FATAL(req != NULL);
699 	gen = g_ns.gen;
700 
701 	/* TEST CASE: g_ctrlr1_A register with a new key */
702 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
703 					      0, 0, 0, 0xa1);
704 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
705 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
706 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
707 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa1);
708 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 1);
709 
710 	/* TEST CASE: g_ctrlr2_A register with a new key, because it has same
711 	 * Host Identifier with g_ctrlr1_A, so the register key should same.
712 	 */
713 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
714 					      0, 0, 0, 0xa2);
715 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr2_A, req);
716 	/* Reservation conflict for other key than 0xa1 */
717 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT);
718 
719 	/* g_ctrlr_B register with a new key */
720 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
721 					      0, 0, 0, 0xb1);
722 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
723 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
724 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
725 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb1);
726 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 2);
727 
728 	/* g_ctrlr_C register with a new key */
729 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
730 					      0, 0, 0, 0xc1);
731 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req);
732 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
733 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
734 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xc1);
735 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 3);
736 
737 	ut_reservation_free_req(req);
738 }
739 
740 static void
741 test_reservation_register(void)
742 {
743 	struct spdk_nvmf_request *req;
744 	struct spdk_nvme_cpl *rsp;
745 	struct spdk_nvmf_registrant *reg;
746 	uint32_t gen;
747 
748 	ut_reservation_init();
749 
750 	req = ut_reservation_build_req(16);
751 	rsp = &req->rsp->nvme_cpl;
752 	SPDK_CU_ASSERT_FATAL(req != NULL);
753 
754 	ut_reservation_build_registrants();
755 
756 	/* TEST CASE: Replace g_ctrlr1_A with a new key */
757 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
758 					      0, 0, 0xa1, 0xa11);
759 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
760 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
761 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
762 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa11);
763 
764 	/* TEST CASE: Host A with g_ctrlr1_A get reservation with
765 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
766 	 */
767 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
768 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xa11, 0x0);
769 	gen = g_ns.gen;
770 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
771 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
772 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
773 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
774 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa11);
775 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
776 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen);
777 
778 	/* TEST CASE: g_ctrlr_C unregister with IEKEY enabled */
779 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
780 					      1, 0, 0, 0);
781 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req);
782 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
783 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
784 	SPDK_CU_ASSERT_FATAL(reg == NULL);
785 
786 	/* TEST CASE: g_ctrlr_B unregister with correct key */
787 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
788 					      0, 0, 0xb1, 0);
789 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
790 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
791 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
792 	SPDK_CU_ASSERT_FATAL(reg == NULL);
793 
794 	/* TEST CASE: No registrant now, g_ctrlr_B replace new key with IEKEY disabled */
795 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
796 					      0, 0, 0, 0xb1);
797 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
798 	SPDK_CU_ASSERT_FATAL(rsp->status.sc != SPDK_NVME_SC_SUCCESS);
799 
800 	/* TEST CASE: No registrant now, g_ctrlr_B replace new key with IEKEY enabled */
801 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
802 					      1, 0, 0, 0xb1);
803 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
804 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
805 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
806 	SPDK_CU_ASSERT_FATAL(reg != NULL);
807 
808 	/* TEST CASE: g_ctrlr_B replace new key with IEKEY enabled and wrong crkey  */
809 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
810 					      1, 0, 0xff, 0xb2);
811 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
812 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
813 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
814 	SPDK_CU_ASSERT_FATAL(reg != NULL);
815 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb2);
816 
817 	/* TEST CASE: g_ctrlr1_A unregister with correct key,
818 	 * reservation should be removed as well.
819 	 */
820 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
821 					      0, 0, 0xa11, 0);
822 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
823 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
824 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
825 	SPDK_CU_ASSERT_FATAL(reg == NULL);
826 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
827 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0);
828 	SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL);
829 
830 	ut_reservation_free_req(req);
831 	ut_reservation_deinit();
832 }
833 
834 static void
835 test_reservation_register_with_ptpl(void)
836 {
837 	struct spdk_nvmf_request *req;
838 	struct spdk_nvme_cpl *rsp;
839 	struct spdk_nvmf_registrant *reg;
840 	bool update_sgroup = false;
841 	int rc;
842 	struct spdk_nvmf_reservation_info info;
843 
844 	ut_reservation_init();
845 
846 	req = ut_reservation_build_req(16);
847 	rsp = &req->rsp->nvme_cpl;
848 	SPDK_CU_ASSERT_FATAL(req != NULL);
849 
850 	/* TEST CASE: No persistent file, register with PTPL enabled will fail */
851 	g_ns.ptpl_file = NULL;
852 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
853 					      SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
854 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
855 	SPDK_CU_ASSERT_FATAL(update_sgroup == false);
856 	SPDK_CU_ASSERT_FATAL(rsp->status.sc != SPDK_NVME_SC_SUCCESS);
857 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
858 	SPDK_CU_ASSERT_FATAL(reg == NULL);
859 
860 	/* TEST CASE: Enable PTPL */
861 	g_ns.ptpl_file = "/tmp/Ns1PR.cfg";
862 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
863 					      SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
864 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
865 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
866 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
867 	SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true);
868 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
869 	SPDK_CU_ASSERT_FATAL(reg != NULL);
870 	SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &reg->hostid));
871 	/* Load reservation information from configuration file */
872 	memset(&info, 0, sizeof(info));
873 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
874 	SPDK_CU_ASSERT_FATAL(rc == 0);
875 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
876 
877 	/* TEST CASE: Disable PTPL */
878 	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
879 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
880 					      SPDK_NVME_RESERVE_PTPL_CLEAR_POWER_ON, 0, 0xa1);
881 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
882 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
883 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
884 	SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == false);
885 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
886 	SPDK_CU_ASSERT_FATAL(rc < 0);
887 	unlink(g_ns.ptpl_file);
888 
889 	ut_reservation_free_req(req);
890 	ut_reservation_deinit();
891 }
892 
893 static void
894 test_reservation_acquire_preempt_1(void)
895 {
896 	struct spdk_nvmf_request *req;
897 	struct spdk_nvme_cpl *rsp;
898 	struct spdk_nvmf_registrant *reg;
899 	uint32_t gen;
900 
901 	ut_reservation_init();
902 
903 	req = ut_reservation_build_req(16);
904 	rsp = &req->rsp->nvme_cpl;
905 	SPDK_CU_ASSERT_FATAL(req != NULL);
906 
907 	ut_reservation_build_registrants();
908 
909 	gen = g_ns.gen;
910 	/* ACQUIRE: Host A with g_ctrlr1_A acquire reservation with
911 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE.
912 	 */
913 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
914 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0);
915 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
916 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
917 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
918 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
919 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa1);
920 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
921 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen);
922 
923 	/* TEST CASE: g_ctrlr1_A holds the reservation, g_ctrlr_B preempt g_ctrl1_A,
924 	 * g_ctrl1_A registrant is unregistred.
925 	 */
926 	gen = g_ns.gen;
927 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
928 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1, 0xa1);
929 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
930 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
931 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
932 	SPDK_CU_ASSERT_FATAL(reg == NULL);
933 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
934 	SPDK_CU_ASSERT_FATAL(reg != NULL);
935 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
936 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
937 	SPDK_CU_ASSERT_FATAL(reg != NULL);
938 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
939 	SPDK_CU_ASSERT_FATAL(g_ns.gen > gen);
940 
941 	/* TEST CASE: g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B
942 	 * with valid key and PRKEY set to 0, all registrants other the host that issued
943 	 * the command are unregistered.
944 	 */
945 	gen = g_ns.gen;
946 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
947 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0x0);
948 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req);
949 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
950 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid);
951 	SPDK_CU_ASSERT_FATAL(reg == NULL);
952 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
953 	SPDK_CU_ASSERT_FATAL(reg == NULL);
954 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
955 	SPDK_CU_ASSERT_FATAL(reg != NULL);
956 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
957 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
958 	SPDK_CU_ASSERT_FATAL(g_ns.gen > gen);
959 
960 	ut_reservation_free_req(req);
961 	ut_reservation_deinit();
962 }
963 
964 static void
965 test_reservation_acquire_release_with_ptpl(void)
966 {
967 	struct spdk_nvmf_request *req;
968 	struct spdk_nvme_cpl *rsp;
969 	struct spdk_nvmf_registrant *reg;
970 	bool update_sgroup = false;
971 	struct spdk_uuid holder_uuid;
972 	int rc;
973 	struct spdk_nvmf_reservation_info info;
974 
975 	ut_reservation_init();
976 
977 	req = ut_reservation_build_req(16);
978 	rsp = &req->rsp->nvme_cpl;
979 	SPDK_CU_ASSERT_FATAL(req != NULL);
980 
981 	/* TEST CASE: Enable PTPL */
982 	g_ns.ptpl_file = "/tmp/Ns1PR.cfg";
983 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
984 					      SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
985 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
986 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
987 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
988 	SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true);
989 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
990 	SPDK_CU_ASSERT_FATAL(reg != NULL);
991 	SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &reg->hostid));
992 	/* Load reservation information from configuration file */
993 	memset(&info, 0, sizeof(info));
994 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
995 	SPDK_CU_ASSERT_FATAL(rc == 0);
996 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
997 
998 	/* TEST CASE: Acquire the reservation */
999 	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
1000 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1001 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0);
1002 	update_sgroup = nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
1003 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
1004 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1005 	memset(&info, 0, sizeof(info));
1006 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
1007 	SPDK_CU_ASSERT_FATAL(rc == 0);
1008 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
1009 	SPDK_CU_ASSERT_FATAL(info.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1010 	SPDK_CU_ASSERT_FATAL(info.crkey == 0xa1);
1011 	spdk_uuid_parse(&holder_uuid, info.holder_uuid);
1012 	SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &holder_uuid));
1013 
1014 	/* TEST CASE: Release the reservation */
1015 	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
1016 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1017 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1);
1018 	update_sgroup = nvmf_ns_reservation_release(&g_ns, &g_ctrlr1_A, req);
1019 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
1020 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1021 	memset(&info, 0, sizeof(info));
1022 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
1023 	SPDK_CU_ASSERT_FATAL(rc == 0);
1024 	SPDK_CU_ASSERT_FATAL(info.rtype == 0);
1025 	SPDK_CU_ASSERT_FATAL(info.crkey == 0);
1026 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
1027 	unlink(g_ns.ptpl_file);
1028 
1029 	ut_reservation_free_req(req);
1030 	ut_reservation_deinit();
1031 }
1032 
1033 static void
1034 test_reservation_release(void)
1035 {
1036 	struct spdk_nvmf_request *req;
1037 	struct spdk_nvme_cpl *rsp;
1038 	struct spdk_nvmf_registrant *reg;
1039 
1040 	ut_reservation_init();
1041 
1042 	req = ut_reservation_build_req(16);
1043 	rsp = &req->rsp->nvme_cpl;
1044 	SPDK_CU_ASSERT_FATAL(req != NULL);
1045 
1046 	ut_reservation_build_registrants();
1047 
1048 	/* ACQUIRE: Host A with g_ctrlr1_A get reservation with
1049 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS
1050 	 */
1051 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1052 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xa1, 0x0);
1053 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
1054 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1055 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
1056 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
1057 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
1058 
1059 	/* Test Case: Host B release the reservation */
1060 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1061 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1);
1062 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1063 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1064 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1065 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0);
1066 	SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL);
1067 
1068 	/* Test Case: Host C clear the registrants */
1069 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0,
1070 					     0, 0xc1);
1071 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_C, req);
1072 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1073 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
1074 	SPDK_CU_ASSERT_FATAL(reg == NULL);
1075 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid);
1076 	SPDK_CU_ASSERT_FATAL(reg == NULL);
1077 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
1078 	SPDK_CU_ASSERT_FATAL(reg == NULL);
1079 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
1080 	SPDK_CU_ASSERT_FATAL(reg == NULL);
1081 
1082 	ut_reservation_free_req(req);
1083 	ut_reservation_deinit();
1084 }
1085 
1086 void
1087 nvmf_ctrlr_reservation_notice_log(struct spdk_nvmf_ctrlr *ctrlr,
1088 				  struct spdk_nvmf_ns *ns,
1089 				  enum spdk_nvme_reservation_notification_log_page_type type)
1090 {
1091 	ctrlr->num_avail_log_pages++;
1092 }
1093 
1094 static void
1095 test_reservation_unregister_notification(void)
1096 {
1097 	struct spdk_nvmf_request *req;
1098 	struct spdk_nvme_cpl *rsp;
1099 
1100 	ut_reservation_init();
1101 
1102 	req = ut_reservation_build_req(16);
1103 	SPDK_CU_ASSERT_FATAL(req != NULL);
1104 	rsp = &req->rsp->nvme_cpl;
1105 
1106 	ut_reservation_build_registrants();
1107 
1108 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1109 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1110 	 */
1111 	rsp->status.sc = 0xff;
1112 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1113 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1114 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1115 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1116 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1117 
1118 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B unregister the registration.
1119 	 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C only for
1120 	 * SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY or SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY
1121 	 * type.
1122 	 */
1123 	rsp->status.sc = 0xff;
1124 	g_ctrlr1_A.num_avail_log_pages = 0;
1125 	g_ctrlr2_A.num_avail_log_pages = 0;
1126 	g_ctrlr_B.num_avail_log_pages = 5;
1127 	g_ctrlr_C.num_avail_log_pages = 0;
1128 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
1129 					      0, 0, 0xb1, 0);
1130 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
1131 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1132 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1133 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1134 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1135 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1136 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1137 
1138 	ut_reservation_free_req(req);
1139 	ut_reservation_deinit();
1140 }
1141 
1142 static void
1143 test_reservation_release_notification(void)
1144 {
1145 	struct spdk_nvmf_request *req;
1146 	struct spdk_nvme_cpl *rsp;
1147 
1148 	ut_reservation_init();
1149 
1150 	req = ut_reservation_build_req(16);
1151 	SPDK_CU_ASSERT_FATAL(req != NULL);
1152 	rsp = &req->rsp->nvme_cpl;
1153 
1154 	ut_reservation_build_registrants();
1155 
1156 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1157 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1158 	 */
1159 	rsp->status.sc = 0xff;
1160 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1161 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1162 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1163 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1164 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1165 
1166 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation.
1167 	 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C.
1168 	 */
1169 	rsp->status.sc = 0xff;
1170 	g_ctrlr1_A.num_avail_log_pages = 0;
1171 	g_ctrlr2_A.num_avail_log_pages = 0;
1172 	g_ctrlr_B.num_avail_log_pages = 5;
1173 	g_ctrlr_C.num_avail_log_pages = 0;
1174 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1175 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1);
1176 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1177 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1178 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1179 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1180 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1181 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1182 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1183 
1184 	ut_reservation_free_req(req);
1185 	ut_reservation_deinit();
1186 }
1187 
1188 static void
1189 test_reservation_release_notification_write_exclusive(void)
1190 {
1191 	struct spdk_nvmf_request *req;
1192 	struct spdk_nvme_cpl *rsp;
1193 
1194 	ut_reservation_init();
1195 
1196 	req = ut_reservation_build_req(16);
1197 	SPDK_CU_ASSERT_FATAL(req != NULL);
1198 	rsp = &req->rsp->nvme_cpl;
1199 
1200 	ut_reservation_build_registrants();
1201 
1202 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1203 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
1204 	 */
1205 	rsp->status.sc = 0xff;
1206 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1207 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1, 0x0);
1208 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1209 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1210 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
1211 
1212 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation.
1213 	 * Because the reservation type is SPDK_NVME_RESERVE_WRITE_EXCLUSIVE,
1214 	 * no reservation notification occurs.
1215 	 */
1216 	rsp->status.sc = 0xff;
1217 	g_ctrlr1_A.num_avail_log_pages = 5;
1218 	g_ctrlr2_A.num_avail_log_pages = 5;
1219 	g_ctrlr_B.num_avail_log_pages = 5;
1220 	g_ctrlr_C.num_avail_log_pages = 5;
1221 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1222 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1);
1223 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1224 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1225 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1226 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr1_A.num_avail_log_pages);
1227 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr2_A.num_avail_log_pages);
1228 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1229 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages);
1230 
1231 	ut_reservation_free_req(req);
1232 	ut_reservation_deinit();
1233 }
1234 
1235 static void
1236 test_reservation_clear_notification(void)
1237 {
1238 	struct spdk_nvmf_request *req;
1239 	struct spdk_nvme_cpl *rsp;
1240 
1241 	ut_reservation_init();
1242 
1243 	req = ut_reservation_build_req(16);
1244 	SPDK_CU_ASSERT_FATAL(req != NULL);
1245 	rsp = &req->rsp->nvme_cpl;
1246 
1247 	ut_reservation_build_registrants();
1248 
1249 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1250 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1251 	 */
1252 	rsp->status.sc = 0xff;
1253 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1254 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1255 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1256 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1257 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1258 
1259 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B clear the reservation.
1260 	 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C.
1261 	 */
1262 	rsp->status.sc = 0xff;
1263 	g_ctrlr1_A.num_avail_log_pages = 0;
1264 	g_ctrlr2_A.num_avail_log_pages = 0;
1265 	g_ctrlr_B.num_avail_log_pages = 5;
1266 	g_ctrlr_C.num_avail_log_pages = 0;
1267 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0,
1268 					     0, 0xb1);
1269 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1270 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1271 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1272 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1273 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1274 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1275 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1276 
1277 	ut_reservation_free_req(req);
1278 	ut_reservation_deinit();
1279 }
1280 
1281 static void
1282 test_reservation_preempt_notification(void)
1283 {
1284 	struct spdk_nvmf_request *req;
1285 	struct spdk_nvme_cpl *rsp;
1286 
1287 	ut_reservation_init();
1288 
1289 	req = ut_reservation_build_req(16);
1290 	SPDK_CU_ASSERT_FATAL(req != NULL);
1291 	rsp = &req->rsp->nvme_cpl;
1292 
1293 	ut_reservation_build_registrants();
1294 
1295 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1296 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1297 	 */
1298 	rsp->status.sc = 0xff;
1299 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1300 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1301 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1302 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1303 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1304 
1305 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B,
1306 	 * g_ctrlr_B registrant is unregistred, and reservation is preempted.
1307 	 * Registration Preempted notification sends to g_ctrlr_B.
1308 	 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A.
1309 	 */
1310 	rsp->status.sc = 0xff;
1311 	g_ctrlr1_A.num_avail_log_pages = 0;
1312 	g_ctrlr2_A.num_avail_log_pages = 0;
1313 	g_ctrlr_B.num_avail_log_pages = 0;
1314 	g_ctrlr_C.num_avail_log_pages = 5;
1315 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
1316 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0xb1);
1317 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req);
1318 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1319 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
1320 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1321 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1322 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_B.num_avail_log_pages);
1323 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages);
1324 
1325 	ut_reservation_free_req(req);
1326 	ut_reservation_deinit();
1327 }
1328 
1329 static int
1330 nvmf_tgt_create_poll_group(void *io_device, void *ctx_buf)
1331 {
1332 	return 0;
1333 }
1334 
1335 static void
1336 nvmf_tgt_destroy_poll_group(void *io_device, void *ctx_buf)
1337 {
1338 }
1339 
1340 static void
1341 test_spdk_nvmf_ns_event(void)
1342 {
1343 	struct spdk_nvmf_tgt tgt = {};
1344 	struct spdk_nvmf_subsystem subsystem = {
1345 		.max_nsid = 1024,
1346 		.ns = NULL,
1347 		.tgt = &tgt,
1348 	};
1349 	struct spdk_nvmf_ctrlr ctrlr = {
1350 		.subsys = &subsystem
1351 	};
1352 	struct spdk_nvmf_ns_opts ns_opts;
1353 	uint32_t nsid;
1354 	struct spdk_bdev *bdev;
1355 
1356 	subsystem.ns = calloc(subsystem.max_nsid, sizeof(struct spdk_nvmf_subsystem_ns *));
1357 	SPDK_CU_ASSERT_FATAL(subsystem.ns != NULL);
1358 	subsystem.ana_group = calloc(subsystem.max_nsid, sizeof(uint32_t));
1359 	SPDK_CU_ASSERT_FATAL(subsystem.ana_group != NULL);
1360 
1361 	tgt.max_subsystems = 1024;
1362 	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
1363 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
1364 
1365 	spdk_io_device_register(&tgt,
1366 				nvmf_tgt_create_poll_group,
1367 				nvmf_tgt_destroy_poll_group,
1368 				sizeof(struct spdk_nvmf_poll_group),
1369 				NULL);
1370 
1371 	/* Add one namespace */
1372 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
1373 	nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev1", &ns_opts, sizeof(ns_opts), NULL);
1374 	CU_ASSERT(nsid == 1);
1375 	CU_ASSERT(NULL != subsystem.ns[0]);
1376 	CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &g_bdevs[nsid - 1]);
1377 
1378 	bdev = subsystem.ns[nsid - 1]->bdev;
1379 
1380 	/* Add one controller */
1381 	TAILQ_INIT(&subsystem.ctrlrs);
1382 	TAILQ_INSERT_TAIL(&subsystem.ctrlrs, &ctrlr, link);
1383 
1384 	/* Namespace resize event */
1385 	subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
1386 	g_ns_changed_nsid = 0xFFFFFFFF;
1387 	g_ns_changed_ctrlr = NULL;
1388 	nvmf_ns_event(SPDK_BDEV_EVENT_RESIZE, bdev, subsystem.ns[0]);
1389 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state);
1390 
1391 	poll_threads();
1392 	CU_ASSERT(1 == g_ns_changed_nsid);
1393 	CU_ASSERT(&ctrlr == g_ns_changed_ctrlr);
1394 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state);
1395 
1396 	/* Namespace remove event */
1397 	subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
1398 	g_ns_changed_nsid = 0xFFFFFFFF;
1399 	g_ns_changed_ctrlr = NULL;
1400 	nvmf_ns_event(SPDK_BDEV_EVENT_REMOVE, bdev, subsystem.ns[0]);
1401 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state);
1402 	CU_ASSERT(0xFFFFFFFF == g_ns_changed_nsid);
1403 	CU_ASSERT(NULL == g_ns_changed_ctrlr);
1404 
1405 	poll_threads();
1406 	CU_ASSERT(1 == g_ns_changed_nsid);
1407 	CU_ASSERT(&ctrlr == g_ns_changed_ctrlr);
1408 	CU_ASSERT(NULL == subsystem.ns[0]);
1409 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state);
1410 
1411 	spdk_io_device_unregister(&tgt, NULL);
1412 
1413 	poll_threads();
1414 
1415 	free(subsystem.ns);
1416 	free(subsystem.ana_group);
1417 	free(tgt.subsystems);
1418 }
1419 
1420 static void
1421 test_nvmf_ns_reservation_add_remove_registrant(void)
1422 {
1423 	struct spdk_nvmf_ns ns = {};
1424 	struct spdk_nvmf_ctrlr ctrlr = {};
1425 	struct spdk_nvmf_registrant *reg = NULL;
1426 	int rc;
1427 
1428 	TAILQ_INIT(&ns.registrants);
1429 	spdk_uuid_generate(&ctrlr.hostid);
1430 
1431 	rc = nvmf_ns_reservation_add_registrant(&ns, &ctrlr, 0xa11);
1432 	CU_ASSERT(rc == 0);
1433 	reg = TAILQ_FIRST(&ns.registrants);
1434 	SPDK_CU_ASSERT_FATAL(reg != NULL);
1435 	CU_ASSERT(ns.gen == 1);
1436 	CU_ASSERT(reg->rkey == 0xa11);
1437 	CU_ASSERT(!strncmp((uint8_t *)&reg->hostid, (uint8_t *)&ctrlr.hostid, sizeof(ctrlr.hostid)));
1438 
1439 	nvmf_ns_reservation_remove_registrant(&ns, reg);
1440 	CU_ASSERT(TAILQ_EMPTY(&ns.registrants));
1441 	CU_ASSERT(ns.gen == 2);
1442 }
1443 
1444 static void
1445 test_nvmf_subsystem_add_ctrlr(void)
1446 {
1447 	int rc;
1448 	struct spdk_nvmf_ctrlr ctrlr = {};
1449 	struct spdk_nvmf_tgt tgt = {};
1450 	char nqn[256] = "nqn.2016-06.io.spdk:subsystem1";
1451 	struct spdk_nvmf_subsystem *subsystem = NULL;
1452 
1453 	tgt.max_subsystems = 1024;
1454 	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
1455 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
1456 
1457 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
1458 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
1459 	ctrlr.subsys = subsystem;
1460 
1461 	rc = nvmf_subsystem_add_ctrlr(subsystem, &ctrlr);
1462 	CU_ASSERT(rc == 0);
1463 	CU_ASSERT(!TAILQ_EMPTY(&subsystem->ctrlrs));
1464 	CU_ASSERT(ctrlr.cntlid == 1);
1465 	CU_ASSERT(nvmf_subsystem_get_ctrlr(subsystem, 1) == &ctrlr);
1466 
1467 	nvmf_subsystem_remove_ctrlr(subsystem, &ctrlr);
1468 	CU_ASSERT(TAILQ_EMPTY(&subsystem->ctrlrs));
1469 	spdk_nvmf_subsystem_destroy(subsystem);
1470 	free(tgt.subsystems);
1471 }
1472 
1473 static void
1474 test_spdk_nvmf_subsystem_add_host(void)
1475 {
1476 	struct spdk_nvmf_tgt tgt = {};
1477 	struct spdk_nvmf_subsystem *subsystem = NULL;
1478 	int rc;
1479 	const char hostnqn[] = "nqn.2016-06.io.spdk:host1";
1480 	const char subsystemnqn[] = "nqn.2016-06.io.spdk:subsystem1";
1481 
1482 	tgt.max_subsystems = 1024;
1483 	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
1484 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
1485 
1486 	subsystem = spdk_nvmf_subsystem_create(&tgt, subsystemnqn, SPDK_NVMF_SUBTYPE_NVME, 0);
1487 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
1488 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, subsystemnqn);
1489 
1490 	rc = spdk_nvmf_subsystem_add_host(subsystem, hostnqn);
1491 	CU_ASSERT(rc == 0);
1492 	CU_ASSERT(!TAILQ_EMPTY(&subsystem->hosts));
1493 
1494 	/* Add existing nqn, this function is allowed to be called if the nqn was previously added. */
1495 	rc = spdk_nvmf_subsystem_add_host(subsystem, hostnqn);
1496 	CU_ASSERT(rc == 0);
1497 
1498 	rc = spdk_nvmf_subsystem_remove_host(subsystem, hostnqn);
1499 	CU_ASSERT(rc == 0);
1500 	CU_ASSERT(TAILQ_EMPTY(&subsystem->hosts));
1501 
1502 	/* No available nqn */
1503 	rc = spdk_nvmf_subsystem_remove_host(subsystem, hostnqn);
1504 	CU_ASSERT(rc == -ENOENT);
1505 
1506 	spdk_nvmf_subsystem_destroy(subsystem);
1507 	free(tgt.subsystems);
1508 }
1509 
1510 static void
1511 test_nvmf_ns_reservation_report(void)
1512 {
1513 	struct spdk_nvmf_ns ns = {};
1514 	struct spdk_nvmf_ctrlr ctrlr = {};
1515 	struct spdk_nvmf_request req = {};
1516 	union nvmf_h2c_msg cmd = {};
1517 	union nvmf_c2h_msg rsp = {};
1518 	struct spdk_nvme_registered_ctrlr_extended_data *ctrlr_data;
1519 	struct spdk_nvme_reservation_status_extended_data *status_data;
1520 	struct spdk_nvmf_registrant *reg;
1521 
1522 	req.data = calloc(1, sizeof(*status_data) + sizeof(*ctrlr_data) * 2);
1523 	reg = calloc(2, sizeof(struct spdk_nvmf_registrant));
1524 	SPDK_CU_ASSERT_FATAL(req.data != NULL && reg != NULL);
1525 
1526 	req.cmd = &cmd;
1527 	req.rsp = &rsp;
1528 	ns.gen = 1;
1529 	ns.rtype = SPDK_NVME_RESERVE_WRITE_EXCLUSIVE;
1530 	ns.ptpl_activated = true;
1531 	cmd.nvme_cmd.cdw11_bits.resv_report.eds = true;
1532 	cmd.nvme_cmd.cdw10 = 100;
1533 	reg[0].rkey = 0xa;
1534 	reg[1].rkey = 0xb;
1535 	spdk_uuid_generate(&reg[0].hostid);
1536 	spdk_uuid_generate(&reg[1].hostid);
1537 	TAILQ_INIT(&ns.registrants);
1538 	TAILQ_INSERT_TAIL(&ns.registrants, &reg[0], link);
1539 	TAILQ_INSERT_TAIL(&ns.registrants, &reg[1], link);
1540 
1541 	nvmf_ns_reservation_report(&ns, &ctrlr, &req);
1542 	CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC);
1543 	CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS);
1544 	/* Get ctrlr data and status data pointers */
1545 	ctrlr_data = (void *)((uint64_t)req.data + sizeof(*status_data));
1546 	status_data = (void *)req.data;
1547 	SPDK_CU_ASSERT_FATAL(status_data != NULL && ctrlr_data != NULL);
1548 	CU_ASSERT(status_data->data.gen == 1);
1549 	CU_ASSERT(status_data->data.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
1550 	CU_ASSERT(status_data->data.ptpls == true);
1551 	CU_ASSERT(status_data->data.regctl == 2);
1552 	CU_ASSERT(ctrlr_data->cntlid == 0xffff);
1553 	CU_ASSERT(ctrlr_data->rcsts.status == false);
1554 	CU_ASSERT(ctrlr_data->rkey ==  0xa);
1555 	CU_ASSERT(!spdk_uuid_compare((struct spdk_uuid *)ctrlr_data->hostid, &reg[0].hostid));
1556 	/* Check second ctrlr data */
1557 	ctrlr_data++;
1558 	CU_ASSERT(ctrlr_data->cntlid == 0xffff);
1559 	CU_ASSERT(ctrlr_data->rcsts.status == false);
1560 	CU_ASSERT(ctrlr_data->rkey ==  0xb);
1561 	CU_ASSERT(!spdk_uuid_compare((struct spdk_uuid *)ctrlr_data->hostid, &reg[1].hostid));
1562 
1563 	/* extended controller data structure */
1564 	memset(req.data, 0, sizeof(*status_data) + sizeof(*ctrlr_data) * 2);
1565 	memset(req.rsp, 0, sizeof(*req.rsp));
1566 	cmd.nvme_cmd.cdw11_bits.resv_report.eds = false;
1567 
1568 	nvmf_ns_reservation_report(&ns, &ctrlr, &req);
1569 	CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_HOSTID_INCONSISTENT_FORMAT);
1570 	CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC);
1571 
1572 	/* Transfer length invalid */
1573 	memset(req.data, 0, sizeof(*status_data) + sizeof(*ctrlr_data) * 2);
1574 	memset(req.rsp, 0, sizeof(*req.rsp));
1575 	cmd.nvme_cmd.cdw11_bits.resv_report.eds = true;
1576 	cmd.nvme_cmd.cdw10 = 0;
1577 
1578 	nvmf_ns_reservation_report(&ns, &ctrlr, &req);
1579 	CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_INTERNAL_DEVICE_ERROR);
1580 	CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC);
1581 
1582 	free(req.data);
1583 	free(reg);
1584 }
1585 
1586 
1587 int main(int argc, char **argv)
1588 {
1589 	CU_pSuite	suite = NULL;
1590 	unsigned int	num_failures;
1591 
1592 	CU_set_error_action(CUEA_ABORT);
1593 	CU_initialize_registry();
1594 
1595 	suite = CU_add_suite("nvmf", NULL, NULL);
1596 
1597 	CU_ADD_TEST(suite, nvmf_test_create_subsystem);
1598 	CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_add_ns);
1599 	CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_set_sn);
1600 	CU_ADD_TEST(suite, test_reservation_register);
1601 	CU_ADD_TEST(suite, test_reservation_register_with_ptpl);
1602 	CU_ADD_TEST(suite, test_reservation_acquire_preempt_1);
1603 	CU_ADD_TEST(suite, test_reservation_acquire_release_with_ptpl);
1604 	CU_ADD_TEST(suite, test_reservation_release);
1605 	CU_ADD_TEST(suite, test_reservation_unregister_notification);
1606 	CU_ADD_TEST(suite, test_reservation_release_notification);
1607 	CU_ADD_TEST(suite, test_reservation_release_notification_write_exclusive);
1608 	CU_ADD_TEST(suite, test_reservation_clear_notification);
1609 	CU_ADD_TEST(suite, test_reservation_preempt_notification);
1610 	CU_ADD_TEST(suite, test_spdk_nvmf_ns_event);
1611 	CU_ADD_TEST(suite, test_nvmf_ns_reservation_add_remove_registrant);
1612 	CU_ADD_TEST(suite, test_nvmf_subsystem_add_ctrlr);
1613 	CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_add_host);
1614 	CU_ADD_TEST(suite, test_nvmf_ns_reservation_report);
1615 
1616 	allocate_threads(1);
1617 	set_thread(0);
1618 
1619 	CU_basic_set_mode(CU_BRM_VERBOSE);
1620 	CU_basic_run_tests();
1621 	num_failures = CU_get_number_of_failures();
1622 	CU_cleanup_registry();
1623 
1624 	free_threads();
1625 
1626 	return num_failures;
1627 }
1628