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