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